]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/aarch64/aarch64-builtins.c
Fortran/OpenMP: Fix detecting not perfectly nested loops
[thirdparty/gcc.git] / gcc / config / aarch64 / aarch64-builtins.c
CommitLineData
43e9d192 1/* Builtins' description for AArch64 SIMD architecture.
8d9254fc 2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
43e9d192
IB
3 Contributed by ARM Ltd.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
8fcc61f8
RS
21#define IN_TARGET_CODE 1
22
43e9d192
IB
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "tm.h"
c7131fb2 27#include "function.h"
c7131fb2 28#include "basic-block.h"
e11c4407 29#include "rtl.h"
c7131fb2
AM
30#include "tree.h"
31#include "gimple.h"
4d0cdd0c 32#include "memmodel.h"
e11c4407
AM
33#include "tm_p.h"
34#include "expmed.h"
35#include "optabs.h"
36#include "recog.h"
37#include "diagnostic-core.h"
40e23961 38#include "fold-const.h"
d8a2d370 39#include "stor-layout.h"
36566b39 40#include "explow.h"
43e9d192 41#include "expr.h"
43e9d192 42#include "langhooks.h"
5be5c238 43#include "gimple-iterator.h"
10766209 44#include "case-cfn-macros.h"
9d63f43b 45#include "emit-rtl.h"
31427b97
RS
46#include "stringpool.h"
47#include "attribs.h"
43e9d192 48
0d4a1197
RS
49#define v8qi_UP E_V8QImode
50#define v4hi_UP E_V4HImode
51#define v4hf_UP E_V4HFmode
52#define v2si_UP E_V2SImode
53#define v2sf_UP E_V2SFmode
54#define v1df_UP E_V1DFmode
55#define di_UP E_DImode
56#define df_UP E_DFmode
57#define v16qi_UP E_V16QImode
58#define v8hi_UP E_V8HImode
59#define v8hf_UP E_V8HFmode
60#define v4si_UP E_V4SImode
61#define v4sf_UP E_V4SFmode
62#define v2di_UP E_V2DImode
63#define v2df_UP E_V2DFmode
64#define ti_UP E_TImode
65#define oi_UP E_OImode
66#define ci_UP E_CImode
67#define xi_UP E_XImode
68#define si_UP E_SImode
69#define sf_UP E_SFmode
70#define hi_UP E_HImode
71#define hf_UP E_HFmode
72#define qi_UP E_QImode
abbe1ed2
SMW
73#define bf_UP E_BFmode
74#define v4bf_UP E_V4BFmode
75#define v8bf_UP E_V8BFmode
43e9d192
IB
76#define UP(X) X##_UP
77
b5828b4b
JG
78#define SIMD_MAX_BUILTIN_ARGS 5
79
80enum aarch64_type_qualifiers
43e9d192 81{
b5828b4b
JG
82 /* T foo. */
83 qualifier_none = 0x0,
84 /* unsigned T foo. */
85 qualifier_unsigned = 0x1, /* 1 << 0 */
86 /* const T foo. */
87 qualifier_const = 0x2, /* 1 << 1 */
88 /* T *foo. */
89 qualifier_pointer = 0x4, /* 1 << 2 */
b5828b4b
JG
90 /* Used when expanding arguments if an operand could
91 be an immediate. */
92 qualifier_immediate = 0x8, /* 1 << 3 */
93 qualifier_maybe_immediate = 0x10, /* 1 << 4 */
94 /* void foo (...). */
95 qualifier_void = 0x20, /* 1 << 5 */
96 /* Some patterns may have internal operands, this qualifier is an
97 instruction to the initialisation code to skip this operand. */
98 qualifier_internal = 0x40, /* 1 << 6 */
99 /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
100 rather than using the type of the operand. */
101 qualifier_map_mode = 0x80, /* 1 << 7 */
102 /* qualifier_pointer | qualifier_map_mode */
103 qualifier_pointer_map_mode = 0x84,
e625e715 104 /* qualifier_const | qualifier_pointer | qualifier_map_mode */
6db1ec94
JG
105 qualifier_const_pointer_map_mode = 0x86,
106 /* Polynomial types. */
2a49c16d
AL
107 qualifier_poly = 0x100,
108 /* Lane indices - must be in range, and flipped for bigendian. */
4d0a0237
CB
109 qualifier_lane_index = 0x200,
110 /* Lane indices for single lane structure loads and stores. */
9d63f43b
TC
111 qualifier_struct_load_store_lane_index = 0x400,
112 /* Lane indices selected in pairs. - must be in range, and flipped for
113 bigendian. */
114 qualifier_lane_pair_index = 0x800,
8c197c85
SMW
115 /* Lane indices selected in quadtuplets. - must be in range, and flipped for
116 bigendian. */
117 qualifier_lane_quadtup_index = 0x1000,
b5828b4b 118};
43e9d192 119
bf592b2f 120/* Flags that describe what a function might do. */
121const unsigned int FLAG_NONE = 0U;
122const unsigned int FLAG_READ_FPCR = 1U << 0;
123const unsigned int FLAG_RAISE_FP_EXCEPTIONS = 1U << 1;
124const unsigned int FLAG_READ_MEMORY = 1U << 2;
125const unsigned int FLAG_PREFETCH_MEMORY = 1U << 3;
126const unsigned int FLAG_WRITE_MEMORY = 1U << 4;
127
128const unsigned int FLAG_FP = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS;
129const unsigned int FLAG_ALL = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS
130 | FLAG_READ_MEMORY | FLAG_PREFETCH_MEMORY | FLAG_WRITE_MEMORY;
131
43e9d192
IB
132typedef struct
133{
134 const char *name;
ef4bddc2 135 machine_mode mode;
342be7f7
JG
136 const enum insn_code code;
137 unsigned int fcode;
b5828b4b 138 enum aarch64_type_qualifiers *qualifiers;
bf592b2f 139 unsigned int flags;
43e9d192
IB
140} aarch64_simd_builtin_datum;
141
b5828b4b
JG
142static enum aarch64_type_qualifiers
143aarch64_types_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
8f905d69 144 = { qualifier_none, qualifier_none };
b5828b4b 145#define TYPES_UNOP (aarch64_types_unop_qualifiers)
5a7a4e80
TB
146static enum aarch64_type_qualifiers
147aarch64_types_unopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
148 = { qualifier_unsigned, qualifier_unsigned };
149#define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
b5828b4b 150static enum aarch64_type_qualifiers
a579f4c7
JW
151aarch64_types_unopus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
152 = { qualifier_unsigned, qualifier_none };
153#define TYPES_UNOPUS (aarch64_types_unopus_qualifiers)
154static enum aarch64_type_qualifiers
b5828b4b
JG
155aarch64_types_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
156 = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
157#define TYPES_BINOP (aarch64_types_binop_qualifiers)
158static enum aarch64_type_qualifiers
5a7a4e80
TB
159aarch64_types_binopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
160 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
161#define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
7baa225d 162static enum aarch64_type_qualifiers
de10bcce
AL
163aarch64_types_binop_uus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
164 = { qualifier_unsigned, qualifier_unsigned, qualifier_none };
165#define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
166static enum aarch64_type_qualifiers
918621d3
AL
167aarch64_types_binop_ssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
168 = { qualifier_none, qualifier_none, qualifier_unsigned };
169#define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
170static enum aarch64_type_qualifiers
daef0a8c
JW
171aarch64_types_binop_uss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
172 = { qualifier_unsigned, qualifier_none, qualifier_none };
173#define TYPES_BINOP_USS (aarch64_types_binop_uss_qualifiers)
174static enum aarch64_type_qualifiers
7baa225d
TB
175aarch64_types_binopp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
176 = { qualifier_poly, qualifier_poly, qualifier_poly };
177#define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
178
5a7a4e80 179static enum aarch64_type_qualifiers
b5828b4b
JG
180aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
181 = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
182#define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
30442682 183static enum aarch64_type_qualifiers
2a49c16d
AL
184aarch64_types_ternop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
185 = { qualifier_none, qualifier_none, qualifier_none, qualifier_lane_index };
186#define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
187static enum aarch64_type_qualifiers
30442682
TB
188aarch64_types_ternopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
189 = { qualifier_unsigned, qualifier_unsigned,
190 qualifier_unsigned, qualifier_unsigned };
191#define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
27086ea3 192static enum aarch64_type_qualifiers
0b839322
WD
193aarch64_types_ternopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
194 = { qualifier_unsigned, qualifier_unsigned,
195 qualifier_unsigned, qualifier_lane_index };
196#define TYPES_TERNOPU_LANE (aarch64_types_ternopu_lane_qualifiers)
197static enum aarch64_type_qualifiers
27086ea3
MC
198aarch64_types_ternopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
199 = { qualifier_unsigned, qualifier_unsigned,
200 qualifier_unsigned, qualifier_immediate };
201#define TYPES_TERNOPUI (aarch64_types_ternopu_imm_qualifiers)
8c197c85
SMW
202static enum aarch64_type_qualifiers
203aarch64_types_ternop_ssus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
204 = { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_none };
205#define TYPES_TERNOP_SSUS (aarch64_types_ternop_ssus_qualifiers)
27086ea3 206
30442682 207
9d63f43b
TC
208static enum aarch64_type_qualifiers
209aarch64_types_quadop_lane_pair_qualifiers[SIMD_MAX_BUILTIN_ARGS]
210 = { qualifier_none, qualifier_none, qualifier_none,
211 qualifier_none, qualifier_lane_pair_index };
212#define TYPES_QUADOP_LANE_PAIR (aarch64_types_quadop_lane_pair_qualifiers)
b5828b4b 213static enum aarch64_type_qualifiers
2a49c16d 214aarch64_types_quadop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
b5828b4b 215 = { qualifier_none, qualifier_none, qualifier_none,
2a49c16d
AL
216 qualifier_none, qualifier_lane_index };
217#define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
7a08d813
TC
218static enum aarch64_type_qualifiers
219aarch64_types_quadopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
220 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
221 qualifier_unsigned, qualifier_lane_index };
222#define TYPES_QUADOPU_LANE (aarch64_types_quadopu_lane_qualifiers)
b5828b4b 223
8c197c85
SMW
224static enum aarch64_type_qualifiers
225aarch64_types_quadopssus_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
226 = { qualifier_none, qualifier_none, qualifier_unsigned,
227 qualifier_none, qualifier_lane_quadtup_index };
228#define TYPES_QUADOPSSUS_LANE_QUADTUP \
229 (aarch64_types_quadopssus_lane_quadtup_qualifiers)
230static enum aarch64_type_qualifiers
231aarch64_types_quadopsssu_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
232 = { qualifier_none, qualifier_none, qualifier_none,
233 qualifier_unsigned, qualifier_lane_quadtup_index };
234#define TYPES_QUADOPSSSU_LANE_QUADTUP \
235 (aarch64_types_quadopsssu_lane_quadtup_qualifiers)
236
27086ea3
MC
237static enum aarch64_type_qualifiers
238aarch64_types_quadopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
239 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
240 qualifier_unsigned, qualifier_immediate };
241#define TYPES_QUADOPUI (aarch64_types_quadopu_imm_qualifiers)
242
159b8724
TC
243static enum aarch64_type_qualifiers
244aarch64_types_binop_imm_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
245 = { qualifier_poly, qualifier_none, qualifier_immediate };
246#define TYPES_GETREGP (aarch64_types_binop_imm_p_qualifiers)
b5828b4b 247static enum aarch64_type_qualifiers
2a49c16d 248aarch64_types_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
b5828b4b 249 = { qualifier_none, qualifier_none, qualifier_immediate };
2a49c16d
AL
250#define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
251#define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
b5828b4b 252static enum aarch64_type_qualifiers
de10bcce
AL
253aarch64_types_shift_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
254 = { qualifier_unsigned, qualifier_none, qualifier_immediate };
255#define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
256static enum aarch64_type_qualifiers
1f0e9e34
JG
257aarch64_types_fcvt_from_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
258 = { qualifier_none, qualifier_unsigned, qualifier_immediate };
259#define TYPES_FCVTIMM_SUS (aarch64_types_fcvt_from_unsigned_qualifiers)
260static enum aarch64_type_qualifiers
252c7556
AV
261aarch64_types_unsigned_shift_qualifiers[SIMD_MAX_BUILTIN_ARGS]
262 = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate };
263#define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
de10bcce 264
252c7556 265static enum aarch64_type_qualifiers
159b8724
TC
266aarch64_types_ternop_s_imm_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
267 = { qualifier_none, qualifier_none, qualifier_poly, qualifier_immediate};
268#define TYPES_SETREGP (aarch64_types_ternop_s_imm_p_qualifiers)
269static enum aarch64_type_qualifiers
270aarch64_types_ternop_s_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
271 = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate};
272#define TYPES_SETREG (aarch64_types_ternop_s_imm_qualifiers)
273#define TYPES_SHIFTINSERT (aarch64_types_ternop_s_imm_qualifiers)
274#define TYPES_SHIFTACC (aarch64_types_ternop_s_imm_qualifiers)
275
276static enum aarch64_type_qualifiers
277aarch64_types_ternop_p_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
278 = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_immediate};
279#define TYPES_SHIFTINSERTP (aarch64_types_ternop_p_imm_qualifiers)
b5828b4b 280
de10bcce
AL
281static enum aarch64_type_qualifiers
282aarch64_types_unsigned_shiftacc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
283 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
284 qualifier_immediate };
285#define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
286
287
b5828b4b
JG
288static enum aarch64_type_qualifiers
289aarch64_types_combine_qualifiers[SIMD_MAX_BUILTIN_ARGS]
290 = { qualifier_none, qualifier_none, qualifier_none };
291#define TYPES_COMBINE (aarch64_types_combine_qualifiers)
292
159b8724
TC
293static enum aarch64_type_qualifiers
294aarch64_types_combine_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
295 = { qualifier_poly, qualifier_poly, qualifier_poly };
296#define TYPES_COMBINEP (aarch64_types_combine_p_qualifiers)
297
b5828b4b
JG
298static enum aarch64_type_qualifiers
299aarch64_types_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
300 = { qualifier_none, qualifier_const_pointer_map_mode };
301#define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
302#define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
3ec1be97
CB
303static enum aarch64_type_qualifiers
304aarch64_types_loadstruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
305 = { qualifier_none, qualifier_const_pointer_map_mode,
4d0a0237 306 qualifier_none, qualifier_struct_load_store_lane_index };
3ec1be97 307#define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
b5828b4b 308
46e778c4
JG
309static enum aarch64_type_qualifiers
310aarch64_types_bsl_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
311 = { qualifier_poly, qualifier_unsigned,
312 qualifier_poly, qualifier_poly };
313#define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
314static enum aarch64_type_qualifiers
315aarch64_types_bsl_s_qualifiers[SIMD_MAX_BUILTIN_ARGS]
316 = { qualifier_none, qualifier_unsigned,
317 qualifier_none, qualifier_none };
318#define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
319static enum aarch64_type_qualifiers
320aarch64_types_bsl_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
321 = { qualifier_unsigned, qualifier_unsigned,
322 qualifier_unsigned, qualifier_unsigned };
323#define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
324
b5828b4b
JG
325/* The first argument (return type) of a store should be void type,
326 which we represent with qualifier_void. Their first operand will be
327 a DImode pointer to the location to store to, so we must use
328 qualifier_map_mode | qualifier_pointer to build a pointer to the
329 element type of the vector. */
330static enum aarch64_type_qualifiers
159b8724
TC
331aarch64_types_store1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
332 = { qualifier_void, qualifier_pointer_map_mode, qualifier_poly };
333#define TYPES_STORE1P (aarch64_types_store1_p_qualifiers)
334static enum aarch64_type_qualifiers
b5828b4b
JG
335aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
336 = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
337#define TYPES_STORE1 (aarch64_types_store1_qualifiers)
338#define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
ba081b77
JG
339static enum aarch64_type_qualifiers
340aarch64_types_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
341 = { qualifier_void, qualifier_pointer_map_mode,
4d0a0237 342 qualifier_none, qualifier_struct_load_store_lane_index };
ba081b77 343#define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
b5828b4b 344
0ddec79f
JG
345#define CF0(N, X) CODE_FOR_aarch64_##N##X
346#define CF1(N, X) CODE_FOR_##N##X##1
347#define CF2(N, X) CODE_FOR_##N##X##2
348#define CF3(N, X) CODE_FOR_##N##X##3
349#define CF4(N, X) CODE_FOR_##N##X##4
350#define CF10(N, X) CODE_FOR_##N##X
351
bf592b2f 352#define VAR1(T, N, MAP, FLAG, A) \
353 {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T, FLAG_##FLAG},
354#define VAR2(T, N, MAP, FLAG, A, B) \
355 VAR1 (T, N, MAP, FLAG, A) \
356 VAR1 (T, N, MAP, FLAG, B)
357#define VAR3(T, N, MAP, FLAG, A, B, C) \
358 VAR2 (T, N, MAP, FLAG, A, B) \
359 VAR1 (T, N, MAP, FLAG, C)
360#define VAR4(T, N, MAP, FLAG, A, B, C, D) \
361 VAR3 (T, N, MAP, FLAG, A, B, C) \
362 VAR1 (T, N, MAP, FLAG, D)
363#define VAR5(T, N, MAP, FLAG, A, B, C, D, E) \
364 VAR4 (T, N, MAP, FLAG, A, B, C, D) \
365 VAR1 (T, N, MAP, FLAG, E)
366#define VAR6(T, N, MAP, FLAG, A, B, C, D, E, F) \
367 VAR5 (T, N, MAP, FLAG, A, B, C, D, E) \
368 VAR1 (T, N, MAP, FLAG, F)
369#define VAR7(T, N, MAP, FLAG, A, B, C, D, E, F, G) \
370 VAR6 (T, N, MAP, FLAG, A, B, C, D, E, F) \
371 VAR1 (T, N, MAP, FLAG, G)
372#define VAR8(T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
373 VAR7 (T, N, MAP, FLAG, A, B, C, D, E, F, G) \
374 VAR1 (T, N, MAP, FLAG, H)
375#define VAR9(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
376 VAR8 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
377 VAR1 (T, N, MAP, FLAG, I)
378#define VAR10(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
379 VAR9 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
380 VAR1 (T, N, MAP, FLAG, J)
381#define VAR11(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
382 VAR10 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
383 VAR1 (T, N, MAP, FLAG, K)
384#define VAR12(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
385 VAR11 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
386 VAR1 (T, N, MAP, FLAG, L)
387#define VAR13(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
388 VAR12 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
389 VAR1 (T, N, MAP, FLAG, M)
390#define VAR14(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
391 VAR13 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
392 VAR1 (T, X, MAP, FLAG, N)
393#define VAR15(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
394 VAR14 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
395 VAR1 (T, X, MAP, FLAG, O)
396#define VAR16(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
397 VAR15 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
398 VAR1 (T, X, MAP, FLAG, P)
342be7f7 399
f421c516 400#include "aarch64-builtin-iterators.h"
43e9d192
IB
401
402static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
342be7f7
JG
403#include "aarch64-simd-builtins.def"
404};
405
5d357f26
KT
406/* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
407#define AARCH64_CRC32_BUILTINS \
408 CRC32_BUILTIN (crc32b, QI) \
409 CRC32_BUILTIN (crc32h, HI) \
410 CRC32_BUILTIN (crc32w, SI) \
411 CRC32_BUILTIN (crc32x, DI) \
412 CRC32_BUILTIN (crc32cb, QI) \
413 CRC32_BUILTIN (crc32ch, HI) \
414 CRC32_BUILTIN (crc32cw, SI) \
415 CRC32_BUILTIN (crc32cx, DI)
416
9d63f43b
TC
417/* The next 8 FCMLA instrinsics require some special handling compared the
418 normal simd intrinsics. */
419#define AARCH64_SIMD_FCMLA_LANEQ_BUILTINS \
420 FCMLA_LANEQ_BUILTIN (0, v2sf, fcmla, V2SF, false) \
421 FCMLA_LANEQ_BUILTIN (90, v2sf, fcmla, V2SF, false) \
422 FCMLA_LANEQ_BUILTIN (180, v2sf, fcmla, V2SF, false) \
423 FCMLA_LANEQ_BUILTIN (270, v2sf, fcmla, V2SF, false) \
424 FCMLA_LANEQ_BUILTIN (0, v4hf, fcmla_laneq, V4HF, true) \
425 FCMLA_LANEQ_BUILTIN (90, v4hf, fcmla_laneq, V4HF, true) \
426 FCMLA_LANEQ_BUILTIN (180, v4hf, fcmla_laneq, V4HF, true) \
427 FCMLA_LANEQ_BUILTIN (270, v4hf, fcmla_laneq, V4HF, true) \
428
5d357f26
KT
429typedef struct
430{
431 const char *name;
ef4bddc2 432 machine_mode mode;
5d357f26
KT
433 const enum insn_code icode;
434 unsigned int fcode;
435} aarch64_crc_builtin_datum;
436
9d63f43b
TC
437/* Hold information about how to expand the FCMLA_LANEQ builtins. */
438typedef struct
439{
440 const char *name;
441 machine_mode mode;
442 const enum insn_code icode;
443 unsigned int fcode;
444 bool lane;
445} aarch64_fcmla_laneq_builtin_datum;
446
5d357f26
KT
447#define CRC32_BUILTIN(N, M) \
448 AARCH64_BUILTIN_##N,
449
9d63f43b
TC
450#define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
451 AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M,
452
342be7f7 453#undef VAR1
bf592b2f 454#define VAR1(T, N, MAP, FLAG, A) \
e993fea1 455 AARCH64_SIMD_BUILTIN_##T##_##N##A,
342be7f7
JG
456
457enum aarch64_builtins
458{
459 AARCH64_BUILTIN_MIN,
aa87aced
KV
460
461 AARCH64_BUILTIN_GET_FPCR,
462 AARCH64_BUILTIN_SET_FPCR,
463 AARCH64_BUILTIN_GET_FPSR,
464 AARCH64_BUILTIN_SET_FPSR,
465
0d7e5fa6
AC
466 AARCH64_BUILTIN_GET_FPCR64,
467 AARCH64_BUILTIN_SET_FPCR64,
468 AARCH64_BUILTIN_GET_FPSR64,
469 AARCH64_BUILTIN_SET_FPSR64,
470
a6fc00da
BH
471 AARCH64_BUILTIN_RSQRT_DF,
472 AARCH64_BUILTIN_RSQRT_SF,
473 AARCH64_BUILTIN_RSQRT_V2DF,
474 AARCH64_BUILTIN_RSQRT_V2SF,
475 AARCH64_BUILTIN_RSQRT_V4SF,
342be7f7 476 AARCH64_SIMD_BUILTIN_BASE,
661fce82 477 AARCH64_SIMD_BUILTIN_LANE_CHECK,
342be7f7 478#include "aarch64-simd-builtins.def"
661fce82
AL
479 /* The first enum element which is based on an insn_data pattern. */
480 AARCH64_SIMD_PATTERN_START = AARCH64_SIMD_BUILTIN_LANE_CHECK + 1,
481 AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_PATTERN_START
482 + ARRAY_SIZE (aarch64_simd_builtin_data) - 1,
5d357f26
KT
483 AARCH64_CRC32_BUILTIN_BASE,
484 AARCH64_CRC32_BUILTINS
485 AARCH64_CRC32_BUILTIN_MAX,
312492bd
JW
486 /* ARMv8.3-A Pointer Authentication Builtins. */
487 AARCH64_PAUTH_BUILTIN_AUTIA1716,
488 AARCH64_PAUTH_BUILTIN_PACIA1716,
8fc16d72
ST
489 AARCH64_PAUTH_BUILTIN_AUTIB1716,
490 AARCH64_PAUTH_BUILTIN_PACIB1716,
312492bd 491 AARCH64_PAUTH_BUILTIN_XPACLRI,
9d63f43b
TC
492 /* Special cased Armv8.3-A Complex FMA by Lane quad Builtins. */
493 AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE,
494 AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
e1d5d19e
KT
495 /* Builtin for Arm8.3-a Javascript conversion instruction. */
496 AARCH64_JSCVT,
89626179
SD
497 /* TME builtins. */
498 AARCH64_TME_BUILTIN_TSTART,
499 AARCH64_TME_BUILTIN_TCOMMIT,
500 AARCH64_TME_BUILTIN_TTEST,
501 AARCH64_TME_BUILTIN_TCANCEL,
c5dc215d
KT
502 /* Armv8.5-a RNG instruction builtins. */
503 AARCH64_BUILTIN_RNG_RNDR,
504 AARCH64_BUILTIN_RNG_RNDRRS,
ef01e6bb
DZ
505 /* MEMTAG builtins. */
506 AARCH64_MEMTAG_BUILTIN_START,
507 AARCH64_MEMTAG_BUILTIN_IRG,
508 AARCH64_MEMTAG_BUILTIN_GMI,
509 AARCH64_MEMTAG_BUILTIN_SUBP,
510 AARCH64_MEMTAG_BUILTIN_INC_TAG,
511 AARCH64_MEMTAG_BUILTIN_SET_TAG,
512 AARCH64_MEMTAG_BUILTIN_GET_TAG,
513 AARCH64_MEMTAG_BUILTIN_END,
342be7f7 514 AARCH64_BUILTIN_MAX
43e9d192
IB
515};
516
5d357f26
KT
517#undef CRC32_BUILTIN
518#define CRC32_BUILTIN(N, M) \
0d4a1197 519 {"__builtin_aarch64_"#N, E_##M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
5d357f26
KT
520
521static aarch64_crc_builtin_datum aarch64_crc_builtin_data[] = {
522 AARCH64_CRC32_BUILTINS
523};
524
9d63f43b
TC
525
526#undef FCMLA_LANEQ_BUILTIN
527#define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
528 {"__builtin_aarch64_fcmla_laneq"#I#N, E_##M##mode, CODE_FOR_aarch64_##X##I##N, \
529 AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M, T},
530
531/* This structure contains how to manage the mapping form the builtin to the
532 instruction to generate in the backend and how to invoke the instruction. */
5eb9ac1e 533static aarch64_fcmla_laneq_builtin_datum aarch64_fcmla_lane_builtin_data[] = {
9d63f43b
TC
534 AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
535};
536
5d357f26
KT
537#undef CRC32_BUILTIN
538
119103ca
JG
539static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX];
540
43e9d192
IB
541#define NUM_DREG_TYPES 6
542#define NUM_QREG_TYPES 6
543
f9d53c27
TB
544/* Internal scalar builtin types. These types are used to support
545 neon intrinsic builtins. They are _not_ user-visible types. Therefore
546 the mangling for these types are implementation defined. */
547const char *aarch64_scalar_builtin_types[] = {
548 "__builtin_aarch64_simd_qi",
549 "__builtin_aarch64_simd_hi",
550 "__builtin_aarch64_simd_si",
7c369485 551 "__builtin_aarch64_simd_hf",
f9d53c27
TB
552 "__builtin_aarch64_simd_sf",
553 "__builtin_aarch64_simd_di",
554 "__builtin_aarch64_simd_df",
555 "__builtin_aarch64_simd_poly8",
556 "__builtin_aarch64_simd_poly16",
557 "__builtin_aarch64_simd_poly64",
558 "__builtin_aarch64_simd_poly128",
559 "__builtin_aarch64_simd_ti",
560 "__builtin_aarch64_simd_uqi",
561 "__builtin_aarch64_simd_uhi",
562 "__builtin_aarch64_simd_usi",
563 "__builtin_aarch64_simd_udi",
564 "__builtin_aarch64_simd_ei",
565 "__builtin_aarch64_simd_oi",
566 "__builtin_aarch64_simd_ci",
567 "__builtin_aarch64_simd_xi",
e603cd43 568 "__builtin_aarch64_simd_bf",
f9d53c27
TB
569 NULL
570};
b5828b4b 571
f9d53c27
TB
572#define ENTRY(E, M, Q, G) E,
573enum aarch64_simd_type
574{
575#include "aarch64-simd-builtin-types.def"
576 ARM_NEON_H_TYPES_LAST
577};
578#undef ENTRY
b5828b4b 579
f9d53c27 580struct aarch64_simd_type_info
b5828b4b 581{
f9d53c27
TB
582 enum aarch64_simd_type type;
583
584 /* Internal type name. */
585 const char *name;
586
587 /* Internal type name(mangled). The mangled names conform to the
588 AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
589 Appendix A). To qualify for emission with the mangled names defined in
590 that document, a vector type must not only be of the correct mode but also
591 be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
592 types are registered by aarch64_init_simd_builtin_types (). In other
593 words, vector types defined in other ways e.g. via vector_size attribute
594 will get default mangled names. */
595 const char *mangle;
596
597 /* Internal type. */
598 tree itype;
599
600 /* Element type. */
b5828b4b
JG
601 tree eltype;
602
f9d53c27
TB
603 /* Machine mode the internal type maps to. */
604 enum machine_mode mode;
b5828b4b 605
f9d53c27
TB
606 /* Qualifiers. */
607 enum aarch64_type_qualifiers q;
608};
609
610#define ENTRY(E, M, Q, G) \
0d4a1197 611 {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, E_##M##mode, qualifier_##Q},
f9d53c27
TB
612static struct aarch64_simd_type_info aarch64_simd_types [] = {
613#include "aarch64-simd-builtin-types.def"
614};
615#undef ENTRY
616
617static tree aarch64_simd_intOI_type_node = NULL_TREE;
f9d53c27
TB
618static tree aarch64_simd_intCI_type_node = NULL_TREE;
619static tree aarch64_simd_intXI_type_node = NULL_TREE;
620
1b62ed4f
JG
621/* The user-visible __fp16 type, and a pointer to that type. Used
622 across the back-end. */
623tree aarch64_fp16_type_node = NULL_TREE;
624tree aarch64_fp16_ptr_type_node = NULL_TREE;
625
abbe1ed2
SMW
626/* Back-end node type for brain float (bfloat) types. */
627tree aarch64_bf16_type_node = NULL_TREE;
628tree aarch64_bf16_ptr_type_node = NULL_TREE;
629
6d4d616a 630/* Wrapper around add_builtin_function. NAME is the name of the built-in
072a8b8f 631 function, TYPE is the function type, CODE is the function subcode
632 (relative to AARCH64_BUILTIN_GENERAL), and ATTRS is the function
633 attributes. */
6d4d616a 634static tree
072a8b8f 635aarch64_general_add_builtin (const char *name, tree type, unsigned int code,
636 tree attrs = NULL_TREE)
6d4d616a
RS
637{
638 code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
639 return add_builtin_function (name, type, code, BUILT_IN_MD,
072a8b8f 640 NULL, attrs);
6d4d616a
RS
641}
642
f9d53c27
TB
643static const char *
644aarch64_mangle_builtin_scalar_type (const_tree type)
645{
646 int i = 0;
647
648 while (aarch64_scalar_builtin_types[i] != NULL)
b5828b4b 649 {
f9d53c27
TB
650 const char *name = aarch64_scalar_builtin_types[i];
651
652 if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
653 && DECL_NAME (TYPE_NAME (type))
654 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), name))
655 return aarch64_scalar_builtin_types[i];
656 i++;
657 }
658 return NULL;
b5828b4b
JG
659}
660
f9d53c27
TB
661static const char *
662aarch64_mangle_builtin_vector_type (const_tree type)
b5828b4b 663{
31427b97
RS
664 tree attrs = TYPE_ATTRIBUTES (type);
665 if (tree attr = lookup_attribute ("Advanced SIMD type", attrs))
666 {
667 tree mangled_name = TREE_VALUE (TREE_VALUE (attr));
668 return IDENTIFIER_POINTER (mangled_name);
669 }
f9d53c27
TB
670
671 return NULL;
6db1ec94
JG
672}
673
f9d53c27 674const char *
6d4d616a 675aarch64_general_mangle_builtin_type (const_tree type)
6db1ec94 676{
f9d53c27
TB
677 const char *mangle;
678 /* Walk through all the AArch64 builtins types tables to filter out the
679 incoming type. */
680 if ((mangle = aarch64_mangle_builtin_vector_type (type))
681 || (mangle = aarch64_mangle_builtin_scalar_type (type)))
682 return mangle;
683
684 return NULL;
6db1ec94
JG
685}
686
f9d53c27 687static tree
b8506a8a 688aarch64_simd_builtin_std_type (machine_mode mode,
f9d53c27 689 enum aarch64_type_qualifiers q)
6db1ec94 690{
f9d53c27
TB
691#define QUAL_TYPE(M) \
692 ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
693 switch (mode)
694 {
4e10a5a7 695 case E_QImode:
f9d53c27 696 return QUAL_TYPE (QI);
4e10a5a7 697 case E_HImode:
f9d53c27 698 return QUAL_TYPE (HI);
4e10a5a7 699 case E_SImode:
f9d53c27 700 return QUAL_TYPE (SI);
4e10a5a7 701 case E_DImode:
f9d53c27 702 return QUAL_TYPE (DI);
4e10a5a7 703 case E_TImode:
f9d53c27 704 return QUAL_TYPE (TI);
4e10a5a7 705 case E_OImode:
f9d53c27 706 return aarch64_simd_intOI_type_node;
4e10a5a7 707 case E_CImode:
f9d53c27 708 return aarch64_simd_intCI_type_node;
4e10a5a7 709 case E_XImode:
f9d53c27 710 return aarch64_simd_intXI_type_node;
4e10a5a7 711 case E_HFmode:
71a11456 712 return aarch64_fp16_type_node;
4e10a5a7 713 case E_SFmode:
f9d53c27 714 return float_type_node;
4e10a5a7 715 case E_DFmode:
f9d53c27 716 return double_type_node;
abbe1ed2
SMW
717 case E_BFmode:
718 return aarch64_bf16_type_node;
f9d53c27
TB
719 default:
720 gcc_unreachable ();
721 }
722#undef QUAL_TYPE
6db1ec94
JG
723}
724
f9d53c27 725static tree
b8506a8a 726aarch64_lookup_simd_builtin_type (machine_mode mode,
f9d53c27 727 enum aarch64_type_qualifiers q)
6db1ec94 728{
f9d53c27
TB
729 int i;
730 int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
731
732 /* Non-poly scalar modes map to standard types not in the table. */
733 if (q != qualifier_poly && !VECTOR_MODE_P (mode))
734 return aarch64_simd_builtin_std_type (mode, q);
735
736 for (i = 0; i < nelts; i++)
737 if (aarch64_simd_types[i].mode == mode
738 && aarch64_simd_types[i].q == q)
739 return aarch64_simd_types[i].itype;
740
741 return NULL_TREE;
b5828b4b
JG
742}
743
f9d53c27 744static tree
b8506a8a 745aarch64_simd_builtin_type (machine_mode mode,
f9d53c27
TB
746 bool unsigned_p, bool poly_p)
747{
748 if (poly_p)
749 return aarch64_lookup_simd_builtin_type (mode, qualifier_poly);
750 else if (unsigned_p)
751 return aarch64_lookup_simd_builtin_type (mode, qualifier_unsigned);
752 else
753 return aarch64_lookup_simd_builtin_type (mode, qualifier_none);
754}
755
af55e82d 756static void
f9d53c27 757aarch64_init_simd_builtin_types (void)
43e9d192 758{
f9d53c27
TB
759 int i;
760 int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
761 tree tdecl;
762
763 /* Init all the element types built by the front-end. */
764 aarch64_simd_types[Int8x8_t].eltype = intQI_type_node;
765 aarch64_simd_types[Int8x16_t].eltype = intQI_type_node;
766 aarch64_simd_types[Int16x4_t].eltype = intHI_type_node;
767 aarch64_simd_types[Int16x8_t].eltype = intHI_type_node;
768 aarch64_simd_types[Int32x2_t].eltype = intSI_type_node;
769 aarch64_simd_types[Int32x4_t].eltype = intSI_type_node;
770 aarch64_simd_types[Int64x1_t].eltype = intDI_type_node;
771 aarch64_simd_types[Int64x2_t].eltype = intDI_type_node;
772 aarch64_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node;
773 aarch64_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node;
774 aarch64_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node;
775 aarch64_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node;
776 aarch64_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node;
777 aarch64_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
778 aarch64_simd_types[Uint64x1_t].eltype = unsigned_intDI_type_node;
779 aarch64_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
780
781 /* Poly types are a world of their own. */
782 aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
783 build_distinct_type_copy (unsigned_intQI_type_node);
bcee52c4
MS
784 /* Prevent front-ends from transforming Poly8_t arrays into string
785 literals. */
786 TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
787
f9d53c27
TB
788 aarch64_simd_types[Poly16_t].eltype = aarch64_simd_types[Poly16_t].itype =
789 build_distinct_type_copy (unsigned_intHI_type_node);
790 aarch64_simd_types[Poly64_t].eltype = aarch64_simd_types[Poly64_t].itype =
791 build_distinct_type_copy (unsigned_intDI_type_node);
792 aarch64_simd_types[Poly128_t].eltype = aarch64_simd_types[Poly128_t].itype =
793 build_distinct_type_copy (unsigned_intTI_type_node);
794 /* Init poly vector element types with scalar poly types. */
795 aarch64_simd_types[Poly8x8_t].eltype = aarch64_simd_types[Poly8_t].itype;
796 aarch64_simd_types[Poly8x16_t].eltype = aarch64_simd_types[Poly8_t].itype;
797 aarch64_simd_types[Poly16x4_t].eltype = aarch64_simd_types[Poly16_t].itype;
798 aarch64_simd_types[Poly16x8_t].eltype = aarch64_simd_types[Poly16_t].itype;
799 aarch64_simd_types[Poly64x1_t].eltype = aarch64_simd_types[Poly64_t].itype;
800 aarch64_simd_types[Poly64x2_t].eltype = aarch64_simd_types[Poly64_t].itype;
801
802 /* Continue with standard types. */
71a11456
AL
803 aarch64_simd_types[Float16x4_t].eltype = aarch64_fp16_type_node;
804 aarch64_simd_types[Float16x8_t].eltype = aarch64_fp16_type_node;
f9d53c27
TB
805 aarch64_simd_types[Float32x2_t].eltype = float_type_node;
806 aarch64_simd_types[Float32x4_t].eltype = float_type_node;
807 aarch64_simd_types[Float64x1_t].eltype = double_type_node;
808 aarch64_simd_types[Float64x2_t].eltype = double_type_node;
809
abbe1ed2
SMW
810 /* Init Bfloat vector types with underlying __bf16 type. */
811 aarch64_simd_types[Bfloat16x4_t].eltype = aarch64_bf16_type_node;
812 aarch64_simd_types[Bfloat16x8_t].eltype = aarch64_bf16_type_node;
813
f9d53c27
TB
814 for (i = 0; i < nelts; i++)
815 {
816 tree eltype = aarch64_simd_types[i].eltype;
b8506a8a 817 machine_mode mode = aarch64_simd_types[i].mode;
f9d53c27
TB
818
819 if (aarch64_simd_types[i].itype == NULL)
b96824c4 820 {
31427b97
RS
821 tree type = build_vector_type (eltype, GET_MODE_NUNITS (mode));
822 type = build_distinct_type_copy (type);
823 SET_TYPE_STRUCTURAL_EQUALITY (type);
824
825 tree mangled_name = get_identifier (aarch64_simd_types[i].mangle);
826 tree value = tree_cons (NULL_TREE, mangled_name, NULL_TREE);
827 TYPE_ATTRIBUTES (type)
828 = tree_cons (get_identifier ("Advanced SIMD type"), value,
829 TYPE_ATTRIBUTES (type));
830 aarch64_simd_types[i].itype = type;
b96824c4 831 }
f9d53c27
TB
832
833 tdecl = add_builtin_type (aarch64_simd_types[i].name,
834 aarch64_simd_types[i].itype);
835 TYPE_NAME (aarch64_simd_types[i].itype) = tdecl;
f9d53c27 836 }
43e9d192 837
f9d53c27
TB
838#define AARCH64_BUILD_SIGNED_TYPE(mode) \
839 make_signed_type (GET_MODE_PRECISION (mode));
840 aarch64_simd_intOI_type_node = AARCH64_BUILD_SIGNED_TYPE (OImode);
f9d53c27
TB
841 aarch64_simd_intCI_type_node = AARCH64_BUILD_SIGNED_TYPE (CImode);
842 aarch64_simd_intXI_type_node = AARCH64_BUILD_SIGNED_TYPE (XImode);
843#undef AARCH64_BUILD_SIGNED_TYPE
844
f9d53c27
TB
845 tdecl = add_builtin_type
846 ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node);
847 TYPE_NAME (aarch64_simd_intOI_type_node) = tdecl;
848 tdecl = add_builtin_type
849 ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node);
850 TYPE_NAME (aarch64_simd_intCI_type_node) = tdecl;
851 tdecl = add_builtin_type
852 ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node);
853 TYPE_NAME (aarch64_simd_intXI_type_node) = tdecl;
854}
855
856static void
857aarch64_init_simd_builtin_scalar_types (void)
858{
859 /* Define typedefs for all the standard scalar types. */
860 (*lang_hooks.types.register_builtin_type) (intQI_type_node,
43e9d192 861 "__builtin_aarch64_simd_qi");
f9d53c27 862 (*lang_hooks.types.register_builtin_type) (intHI_type_node,
43e9d192 863 "__builtin_aarch64_simd_hi");
7c369485
AL
864 (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node,
865 "__builtin_aarch64_simd_hf");
f9d53c27 866 (*lang_hooks.types.register_builtin_type) (intSI_type_node,
43e9d192 867 "__builtin_aarch64_simd_si");
f9d53c27 868 (*lang_hooks.types.register_builtin_type) (float_type_node,
43e9d192 869 "__builtin_aarch64_simd_sf");
f9d53c27 870 (*lang_hooks.types.register_builtin_type) (intDI_type_node,
43e9d192 871 "__builtin_aarch64_simd_di");
f9d53c27 872 (*lang_hooks.types.register_builtin_type) (double_type_node,
43e9d192 873 "__builtin_aarch64_simd_df");
f9d53c27 874 (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
43e9d192 875 "__builtin_aarch64_simd_poly8");
f9d53c27 876 (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
43e9d192 877 "__builtin_aarch64_simd_poly16");
f9d53c27 878 (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
7baa225d 879 "__builtin_aarch64_simd_poly64");
f9d53c27 880 (*lang_hooks.types.register_builtin_type) (unsigned_intTI_type_node,
7baa225d 881 "__builtin_aarch64_simd_poly128");
f9d53c27 882 (*lang_hooks.types.register_builtin_type) (intTI_type_node,
43e9d192 883 "__builtin_aarch64_simd_ti");
e603cd43
MI
884 (*lang_hooks.types.register_builtin_type) (aarch64_bf16_type_node,
885 "__builtin_aarch64_simd_bf");
b5828b4b 886 /* Unsigned integer types for various mode sizes. */
f9d53c27 887 (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
b5828b4b 888 "__builtin_aarch64_simd_uqi");
f9d53c27 889 (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
b5828b4b 890 "__builtin_aarch64_simd_uhi");
f9d53c27 891 (*lang_hooks.types.register_builtin_type) (unsigned_intSI_type_node,
b5828b4b 892 "__builtin_aarch64_simd_usi");
f9d53c27 893 (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
b5828b4b 894 "__builtin_aarch64_simd_udi");
f9d53c27
TB
895}
896
072a8b8f 897/* Return a set of FLAG_* flags that describe what the function could do,
898 taking the command-line flags into account. */
899static unsigned int
900aarch64_call_properties (aarch64_simd_builtin_datum *d)
901{
902 unsigned int flags = d->flags;
903 switch (d->mode)
904 {
905 /* Floating-point. */
906 case E_BFmode:
907 case E_V4BFmode:
908 case E_V8BFmode:
909 case E_HFmode:
910 case E_V4HFmode:
911 case E_V8HFmode:
912 case E_SFmode:
913 case E_V2SFmode:
914 case E_V4SFmode:
915 case E_DFmode:
916 case E_V1DFmode:
917 case E_V2DFmode:
918 flags |= FLAG_FP;
919 break;
920
921 default:
922 break;
923 }
924
925 /* -fno-trapping-math means that we can assume any FP exceptions
926 are not user-visible. */
927 if (!flag_trapping_math)
928 flags &= ~FLAG_RAISE_FP_EXCEPTIONS;
929
930 return flags;
931}
932
933/* Return true if calls to the function could modify some form of
934 global state. */
935static bool
936aarch64_modifies_global_state_p (aarch64_simd_builtin_datum *d)
937{
938 unsigned int flags = aarch64_call_properties (d);
939
940 if (flags & FLAG_RAISE_FP_EXCEPTIONS)
941 return true;
942
943 if (flags & FLAG_PREFETCH_MEMORY)
944 return true;
945
946 return flags & FLAG_WRITE_MEMORY;
947}
948
949/* Return true if calls to the function could read some form of
950 global state. */
951static bool
952aarch64_reads_global_state_p (aarch64_simd_builtin_datum *d)
953{
954 unsigned int flags = aarch64_call_properties (d);
955
956 if (flags & FLAG_READ_FPCR)
957 return true;
958
959 return flags & FLAG_READ_MEMORY;
960}
961
962/* Return true if calls to the function could raise a signal. */
963static bool
964aarch64_could_trap_p (aarch64_simd_builtin_datum *d)
965{
966 unsigned int flags = aarch64_call_properties (d);
967
968 if (flags & FLAG_RAISE_FP_EXCEPTIONS)
969 return true;
970
971 if (flags & (FLAG_READ_MEMORY | FLAG_WRITE_MEMORY))
972 return true;
973
974 return false;
975}
976
977/* Add attribute NAME to ATTRS. */
978static tree
979aarch64_add_attribute (const char *name, tree attrs)
980{
981 return tree_cons (get_identifier (name), NULL_TREE, attrs);
982}
983
984/* Return the appropriate function attributes. */
985static tree
986aarch64_get_attributes (aarch64_simd_builtin_datum *d)
987{
988 tree attrs = NULL_TREE;
989
990 if (!aarch64_modifies_global_state_p (d))
991 {
992 if (aarch64_reads_global_state_p (d))
993 attrs = aarch64_add_attribute ("pure", attrs);
994 else
995 attrs = aarch64_add_attribute ("const", attrs);
996 }
997
998 if (!flag_non_call_exceptions || !aarch64_could_trap_p (d))
999 attrs = aarch64_add_attribute ("nothrow", attrs);
1000
1001 return aarch64_add_attribute ("leaf", attrs);
1002}
1003
e95a988a
KT
1004static bool aarch64_simd_builtins_initialized_p = false;
1005
9d63f43b
TC
1006/* Due to the architecture not providing lane variant of the lane instructions
1007 for fcmla we can't use the standard simd builtin expansion code, but we
1008 still want the majority of the validation that would normally be done. */
1009
1010void
1011aarch64_init_fcmla_laneq_builtins (void)
1012{
1013 unsigned int i = 0;
1014
1015 for (i = 0; i < ARRAY_SIZE (aarch64_fcmla_lane_builtin_data); ++i)
1016 {
1017 aarch64_fcmla_laneq_builtin_datum* d
1018 = &aarch64_fcmla_lane_builtin_data[i];
1019 tree argtype = aarch64_lookup_simd_builtin_type (d->mode, qualifier_none);
1020 machine_mode quadmode = GET_MODE_2XWIDER_MODE (d->mode).require ();
1021 tree quadtype
1022 = aarch64_lookup_simd_builtin_type (quadmode, qualifier_none);
1023 tree lanetype
1024 = aarch64_simd_builtin_std_type (SImode, qualifier_lane_pair_index);
1025 tree ftype = build_function_type_list (argtype, argtype, argtype,
1026 quadtype, lanetype, NULL_TREE);
6d4d616a 1027 tree fndecl = aarch64_general_add_builtin (d->name, ftype, d->fcode);
9d63f43b
TC
1028
1029 aarch64_builtin_decls[d->fcode] = fndecl;
1030 }
1031}
1032
e95a988a 1033void
f9d53c27
TB
1034aarch64_init_simd_builtins (void)
1035{
661fce82 1036 unsigned int i, fcode = AARCH64_SIMD_PATTERN_START;
f9d53c27 1037
e95a988a
KT
1038 if (aarch64_simd_builtins_initialized_p)
1039 return;
1040
1041 aarch64_simd_builtins_initialized_p = true;
1042
f9d53c27 1043 aarch64_init_simd_builtin_types ();
43e9d192 1044
f9d53c27
TB
1045 /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
1046 Therefore we need to preserve the old __builtin scalar types. It can be
1047 removed once all the intrinsics become strongly typed using the qualifier
1048 system. */
1049 aarch64_init_simd_builtin_scalar_types ();
1050
661fce82 1051 tree lane_check_fpr = build_function_type_list (void_type_node,
9c4f25cc
AP
1052 size_type_node,
1053 size_type_node,
661fce82
AL
1054 intSI_type_node,
1055 NULL);
6d4d616a
RS
1056 aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_LANE_CHECK]
1057 = aarch64_general_add_builtin ("__builtin_aarch64_im_lane_boundsi",
1058 lane_check_fpr,
1059 AARCH64_SIMD_BUILTIN_LANE_CHECK);
661fce82 1060
342be7f7 1061 for (i = 0; i < ARRAY_SIZE (aarch64_simd_builtin_data); i++, fcode++)
43e9d192 1062 {
b5828b4b 1063 bool print_type_signature_p = false;
cae83731 1064 char type_signature[SIMD_MAX_BUILTIN_ARGS + 1] = { 0 };
43e9d192 1065 aarch64_simd_builtin_datum *d = &aarch64_simd_builtin_data[i];
342be7f7
JG
1066 char namebuf[60];
1067 tree ftype = NULL;
119103ca 1068 tree fndecl = NULL;
342be7f7 1069
342be7f7 1070 d->fcode = fcode;
43e9d192 1071
b5828b4b
JG
1072 /* We must track two variables here. op_num is
1073 the operand number as in the RTL pattern. This is
1074 required to access the mode (e.g. V4SF mode) of the
1075 argument, from which the base type can be derived.
1076 arg_num is an index in to the qualifiers data, which
1077 gives qualifiers to the type (e.g. const unsigned).
1078 The reason these two variables may differ by one is the
1079 void return type. While all return types take the 0th entry
1080 in the qualifiers array, there is no operand for them in the
1081 RTL pattern. */
1082 int op_num = insn_data[d->code].n_operands - 1;
1083 int arg_num = d->qualifiers[0] & qualifier_void
1084 ? op_num + 1
1085 : op_num;
1086 tree return_type = void_type_node, args = void_list_node;
1087 tree eltype;
1088
1089 /* Build a function type directly from the insn_data for this
1090 builtin. The build_function_type () function takes care of
1091 removing duplicates for us. */
1092 for (; op_num >= 0; arg_num--, op_num--)
43e9d192 1093 {
ef4bddc2 1094 machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
b5828b4b 1095 enum aarch64_type_qualifiers qualifiers = d->qualifiers[arg_num];
43e9d192 1096
b5828b4b
JG
1097 if (qualifiers & qualifier_unsigned)
1098 {
9fd2074d 1099 type_signature[op_num] = 'u';
b5828b4b
JG
1100 print_type_signature_p = true;
1101 }
6db1ec94
JG
1102 else if (qualifiers & qualifier_poly)
1103 {
9fd2074d 1104 type_signature[op_num] = 'p';
6db1ec94
JG
1105 print_type_signature_p = true;
1106 }
b5828b4b 1107 else
9fd2074d 1108 type_signature[op_num] = 's';
b5828b4b
JG
1109
1110 /* Skip an internal operand for vget_{low, high}. */
1111 if (qualifiers & qualifier_internal)
1112 continue;
1113
1114 /* Some builtins have different user-facing types
1115 for certain arguments, encoded in d->mode. */
1116 if (qualifiers & qualifier_map_mode)
bc5e395d 1117 op_mode = d->mode;
b5828b4b
JG
1118
1119 /* For pointers, we want a pointer to the basic type
1120 of the vector. */
1121 if (qualifiers & qualifier_pointer && VECTOR_MODE_P (op_mode))
1122 op_mode = GET_MODE_INNER (op_mode);
1123
f9d53c27
TB
1124 eltype = aarch64_simd_builtin_type
1125 (op_mode,
1126 (qualifiers & qualifier_unsigned) != 0,
1127 (qualifiers & qualifier_poly) != 0);
1128 gcc_assert (eltype != NULL);
b5828b4b
JG
1129
1130 /* Add qualifiers. */
1131 if (qualifiers & qualifier_const)
1132 eltype = build_qualified_type (eltype, TYPE_QUAL_CONST);
1133
1134 if (qualifiers & qualifier_pointer)
1135 eltype = build_pointer_type (eltype);
1136
1137 /* If we have reached arg_num == 0, we are at a non-void
1138 return type. Otherwise, we are still processing
1139 arguments. */
1140 if (arg_num == 0)
1141 return_type = eltype;
1142 else
1143 args = tree_cons (NULL_TREE, eltype, args);
1144 }
342be7f7 1145
b5828b4b 1146 ftype = build_function_type (return_type, args);
43e9d192 1147
342be7f7 1148 gcc_assert (ftype != NULL);
43e9d192 1149
b5828b4b 1150 if (print_type_signature_p)
bc5e395d
JG
1151 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s_%s",
1152 d->name, type_signature);
b5828b4b 1153 else
bc5e395d
JG
1154 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s",
1155 d->name);
43e9d192 1156
072a8b8f 1157 tree attrs = aarch64_get_attributes (d);
1158
1159 fndecl = aarch64_general_add_builtin (namebuf, ftype, fcode, attrs);
119103ca 1160 aarch64_builtin_decls[fcode] = fndecl;
43e9d192 1161 }
280d970b
TC
1162
1163 /* Initialize the remaining fcmla_laneq intrinsics. */
1164 aarch64_init_fcmla_laneq_builtins ();
43e9d192
IB
1165}
1166
5d357f26
KT
1167static void
1168aarch64_init_crc32_builtins ()
1169{
f9d53c27 1170 tree usi_type = aarch64_simd_builtin_std_type (SImode, qualifier_unsigned);
5d357f26
KT
1171 unsigned int i = 0;
1172
1173 for (i = 0; i < ARRAY_SIZE (aarch64_crc_builtin_data); ++i)
1174 {
1175 aarch64_crc_builtin_datum* d = &aarch64_crc_builtin_data[i];
f9d53c27
TB
1176 tree argtype = aarch64_simd_builtin_std_type (d->mode,
1177 qualifier_unsigned);
5d357f26 1178 tree ftype = build_function_type_list (usi_type, usi_type, argtype, NULL_TREE);
6d4d616a 1179 tree fndecl = aarch64_general_add_builtin (d->name, ftype, d->fcode);
5d357f26
KT
1180
1181 aarch64_builtin_decls[d->fcode] = fndecl;
1182 }
1183}
1184
a6fc00da
BH
1185/* Add builtins for reciprocal square root. */
1186
1187void
1188aarch64_init_builtin_rsqrt (void)
1189{
1190 tree fndecl = NULL;
1191 tree ftype = NULL;
1192
1193 tree V2SF_type_node = build_vector_type (float_type_node, 2);
1194 tree V2DF_type_node = build_vector_type (double_type_node, 2);
1195 tree V4SF_type_node = build_vector_type (float_type_node, 4);
1196
1197 struct builtin_decls_data
1198 {
1199 tree type_node;
1200 const char *builtin_name;
1201 int function_code;
1202 };
1203
1204 builtin_decls_data bdda[] =
1205 {
1206 { double_type_node, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF },
1207 { float_type_node, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF },
1208 { V2DF_type_node, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF },
1209 { V2SF_type_node, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF },
1210 { V4SF_type_node, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF }
1211 };
1212
1213 builtin_decls_data *bdd = bdda;
1214 builtin_decls_data *bdd_end = bdd + (sizeof (bdda) / sizeof (builtin_decls_data));
1215
1216 for (; bdd < bdd_end; bdd++)
1217 {
1218 ftype = build_function_type_list (bdd->type_node, bdd->type_node, NULL_TREE);
6d4d616a
RS
1219 fndecl = aarch64_general_add_builtin (bdd->builtin_name,
1220 ftype, bdd->function_code);
a6fc00da
BH
1221 aarch64_builtin_decls[bdd->function_code] = fndecl;
1222 }
1223}
1224
1b62ed4f
JG
1225/* Initialize the backend types that support the user-visible __fp16
1226 type, also initialize a pointer to that type, to be used when
1227 forming HFAs. */
1228
1229static void
1230aarch64_init_fp16_types (void)
1231{
1232 aarch64_fp16_type_node = make_node (REAL_TYPE);
1233 TYPE_PRECISION (aarch64_fp16_type_node) = 16;
1234 layout_type (aarch64_fp16_type_node);
1235
1236 (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node, "__fp16");
1237 aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
1238}
1239
abbe1ed2
SMW
1240/* Initialize the backend REAL_TYPE type supporting bfloat types. */
1241static void
1242aarch64_init_bf16_types (void)
1243{
1244 aarch64_bf16_type_node = make_node (REAL_TYPE);
1245 TYPE_PRECISION (aarch64_bf16_type_node) = 16;
1246 SET_TYPE_MODE (aarch64_bf16_type_node, BFmode);
1247 layout_type (aarch64_bf16_type_node);
1248
1249 lang_hooks.types.register_builtin_type (aarch64_bf16_type_node, "__bf16");
1250 aarch64_bf16_ptr_type_node = build_pointer_type (aarch64_bf16_type_node);
1251}
1252
312492bd
JW
1253/* Pointer authentication builtins that will become NOP on legacy platform.
1254 Currently, these builtins are for internal use only (libgcc EH unwinder). */
1255
1256void
1257aarch64_init_pauth_hint_builtins (void)
1258{
1259 /* Pointer Authentication builtins. */
1260 tree ftype_pointer_auth
1261 = build_function_type_list (ptr_type_node, ptr_type_node,
1262 unsigned_intDI_type_node, NULL_TREE);
1263 tree ftype_pointer_strip
1264 = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
1265
1266 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
6d4d616a
RS
1267 = aarch64_general_add_builtin ("__builtin_aarch64_autia1716",
1268 ftype_pointer_auth,
1269 AARCH64_PAUTH_BUILTIN_AUTIA1716);
312492bd 1270 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIA1716]
6d4d616a
RS
1271 = aarch64_general_add_builtin ("__builtin_aarch64_pacia1716",
1272 ftype_pointer_auth,
1273 AARCH64_PAUTH_BUILTIN_PACIA1716);
8fc16d72 1274 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIB1716]
6d4d616a
RS
1275 = aarch64_general_add_builtin ("__builtin_aarch64_autib1716",
1276 ftype_pointer_auth,
1277 AARCH64_PAUTH_BUILTIN_AUTIB1716);
8fc16d72 1278 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIB1716]
6d4d616a
RS
1279 = aarch64_general_add_builtin ("__builtin_aarch64_pacib1716",
1280 ftype_pointer_auth,
1281 AARCH64_PAUTH_BUILTIN_PACIB1716);
312492bd 1282 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
6d4d616a
RS
1283 = aarch64_general_add_builtin ("__builtin_aarch64_xpaclri",
1284 ftype_pointer_strip,
1285 AARCH64_PAUTH_BUILTIN_XPACLRI);
312492bd
JW
1286}
1287
89626179
SD
1288/* Initialize the transactional memory extension (TME) builtins. */
1289static void
1290aarch64_init_tme_builtins (void)
1291{
1292 tree ftype_uint64_void
1293 = build_function_type_list (uint64_type_node, NULL);
1294 tree ftype_void_void
1295 = build_function_type_list (void_type_node, NULL);
1296 tree ftype_void_uint64
1297 = build_function_type_list (void_type_node, uint64_type_node, NULL);
1298
1299 aarch64_builtin_decls[AARCH64_TME_BUILTIN_TSTART]
6d4d616a
RS
1300 = aarch64_general_add_builtin ("__builtin_aarch64_tstart",
1301 ftype_uint64_void,
1302 AARCH64_TME_BUILTIN_TSTART);
89626179 1303 aarch64_builtin_decls[AARCH64_TME_BUILTIN_TTEST]
6d4d616a
RS
1304 = aarch64_general_add_builtin ("__builtin_aarch64_ttest",
1305 ftype_uint64_void,
1306 AARCH64_TME_BUILTIN_TTEST);
89626179 1307 aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCOMMIT]
6d4d616a
RS
1308 = aarch64_general_add_builtin ("__builtin_aarch64_tcommit",
1309 ftype_void_void,
1310 AARCH64_TME_BUILTIN_TCOMMIT);
89626179 1311 aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCANCEL]
6d4d616a
RS
1312 = aarch64_general_add_builtin ("__builtin_aarch64_tcancel",
1313 ftype_void_uint64,
1314 AARCH64_TME_BUILTIN_TCANCEL);
89626179
SD
1315}
1316
c5dc215d
KT
1317/* Add builtins for Random Number instructions. */
1318
1319static void
1320aarch64_init_rng_builtins (void)
1321{
1322 tree unsigned_ptr_type = build_pointer_type (unsigned_intDI_type_node);
1323 tree ftype
1324 = build_function_type_list (integer_type_node, unsigned_ptr_type, NULL);
1325 aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDR]
1326 = aarch64_general_add_builtin ("__builtin_aarch64_rndr", ftype,
1327 AARCH64_BUILTIN_RNG_RNDR);
1328 aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDRRS]
1329 = aarch64_general_add_builtin ("__builtin_aarch64_rndrrs", ftype,
1330 AARCH64_BUILTIN_RNG_RNDRRS);
1331}
1332
ef01e6bb
DZ
1333/* Initialize the memory tagging extension (MTE) builtins. */
1334struct
1335{
1336 tree ftype;
1337 enum insn_code icode;
1338} aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_END -
1339 AARCH64_MEMTAG_BUILTIN_START - 1];
1340
1341static void
1342aarch64_init_memtag_builtins (void)
1343{
1344 tree fntype = NULL;
1345
1346#define AARCH64_INIT_MEMTAG_BUILTINS_DECL(F, N, I, T) \
1347 aarch64_builtin_decls[AARCH64_MEMTAG_BUILTIN_##F] \
1348 = aarch64_general_add_builtin ("__builtin_aarch64_memtag_"#N, \
1349 T, AARCH64_MEMTAG_BUILTIN_##F); \
1350 aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_##F - \
1351 AARCH64_MEMTAG_BUILTIN_START - 1] = \
1352 {T, CODE_FOR_##I};
1353
1354 fntype = build_function_type_list (ptr_type_node, ptr_type_node,
1355 uint64_type_node, NULL);
1356 AARCH64_INIT_MEMTAG_BUILTINS_DECL (IRG, irg, irg, fntype);
1357
1358 fntype = build_function_type_list (uint64_type_node, ptr_type_node,
1359 uint64_type_node, NULL);
1360 AARCH64_INIT_MEMTAG_BUILTINS_DECL (GMI, gmi, gmi, fntype);
1361
1362 fntype = build_function_type_list (ptrdiff_type_node, ptr_type_node,
1363 ptr_type_node, NULL);
1364 AARCH64_INIT_MEMTAG_BUILTINS_DECL (SUBP, subp, subp, fntype);
1365
1366 fntype = build_function_type_list (ptr_type_node, ptr_type_node,
1367 unsigned_type_node, NULL);
1368 AARCH64_INIT_MEMTAG_BUILTINS_DECL (INC_TAG, inc_tag, addg, fntype);
1369
1370 fntype = build_function_type_list (void_type_node, ptr_type_node, NULL);
1371 AARCH64_INIT_MEMTAG_BUILTINS_DECL (SET_TAG, set_tag, stg, fntype);
1372
1373 fntype = build_function_type_list (ptr_type_node, ptr_type_node, NULL);
1374 AARCH64_INIT_MEMTAG_BUILTINS_DECL (GET_TAG, get_tag, ldg, fntype);
1375
1376#undef AARCH64_INIT_MEMTAG_BUILTINS_DECL
1377}
c5dc215d 1378
0d7e5fa6 1379/* Initialize fpsr fpcr getters and setters. */
c5dc215d 1380
0d7e5fa6
AC
1381static void
1382aarch64_init_fpsr_fpcr_builtins (void)
43e9d192 1383{
0d7e5fa6 1384 tree ftype_set
aa87aced 1385 = build_function_type_list (void_type_node, unsigned_type_node, NULL);
0d7e5fa6 1386 tree ftype_get
aa87aced
KV
1387 = build_function_type_list (unsigned_type_node, NULL);
1388
1389 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
6d4d616a 1390 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr",
0d7e5fa6 1391 ftype_get,
6d4d616a 1392 AARCH64_BUILTIN_GET_FPCR);
aa87aced 1393 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
6d4d616a 1394 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr",
0d7e5fa6 1395 ftype_set,
6d4d616a 1396 AARCH64_BUILTIN_SET_FPCR);
aa87aced 1397 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
6d4d616a 1398 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr",
0d7e5fa6 1399 ftype_get,
6d4d616a 1400 AARCH64_BUILTIN_GET_FPSR);
aa87aced 1401 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
6d4d616a 1402 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr",
0d7e5fa6 1403 ftype_set,
6d4d616a 1404 AARCH64_BUILTIN_SET_FPSR);
aa87aced 1405
0d7e5fa6
AC
1406 ftype_set
1407 = build_function_type_list (void_type_node, long_long_unsigned_type_node,
1408 NULL);
1409 ftype_get
1410 = build_function_type_list (long_long_unsigned_type_node, NULL);
1411
1412 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR64]
1413 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr64",
1414 ftype_get,
1415 AARCH64_BUILTIN_GET_FPCR64);
1416 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR64]
1417 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr64",
1418 ftype_set,
1419 AARCH64_BUILTIN_SET_FPCR64);
1420 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR64]
1421 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr64",
1422 ftype_get,
1423 AARCH64_BUILTIN_GET_FPSR64);
1424 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR64]
1425 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr64",
1426 ftype_set,
1427 AARCH64_BUILTIN_SET_FPSR64);
1428}
1429
1430/* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group. */
1431
1432void
1433aarch64_general_init_builtins (void)
1434{
1435 aarch64_init_fpsr_fpcr_builtins ();
1436
1b62ed4f 1437 aarch64_init_fp16_types ();
c2ec330c 1438
abbe1ed2
SMW
1439 aarch64_init_bf16_types ();
1440
342be7f7 1441 if (TARGET_SIMD)
280d970b 1442 aarch64_init_simd_builtins ();
e95a988a
KT
1443
1444 aarch64_init_crc32_builtins ();
a6fc00da 1445 aarch64_init_builtin_rsqrt ();
c5dc215d 1446 aarch64_init_rng_builtins ();
312492bd 1447
e1d5d19e
KT
1448 tree ftype_jcvt
1449 = build_function_type_list (intSI_type_node, double_type_node, NULL);
1450 aarch64_builtin_decls[AARCH64_JSCVT]
6d4d616a
RS
1451 = aarch64_general_add_builtin ("__builtin_aarch64_jcvtzs", ftype_jcvt,
1452 AARCH64_JSCVT);
e1d5d19e 1453
a876231c
JW
1454 /* Initialize pointer authentication builtins which are backed by instructions
1455 in NOP encoding space.
1456
1457 NOTE: these builtins are supposed to be used by libgcc unwinder only, as
1458 there is no support on return address signing under ILP32, we don't
1459 register them. */
1460 if (!TARGET_ILP32)
1461 aarch64_init_pauth_hint_builtins ();
89626179
SD
1462
1463 if (TARGET_TME)
1464 aarch64_init_tme_builtins ();
ef01e6bb
DZ
1465
1466 if (TARGET_MEMTAG)
1467 aarch64_init_memtag_builtins ();
43e9d192
IB
1468}
1469
6d4d616a 1470/* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group. */
119103ca 1471tree
6d4d616a 1472aarch64_general_builtin_decl (unsigned code, bool)
119103ca
JG
1473{
1474 if (code >= AARCH64_BUILTIN_MAX)
1475 return error_mark_node;
1476
1477 return aarch64_builtin_decls[code];
1478}
1479
43e9d192
IB
1480typedef enum
1481{
1482 SIMD_ARG_COPY_TO_REG,
1483 SIMD_ARG_CONSTANT,
2a49c16d 1484 SIMD_ARG_LANE_INDEX,
4d0a0237 1485 SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX,
9d63f43b 1486 SIMD_ARG_LANE_PAIR_INDEX,
8c197c85 1487 SIMD_ARG_LANE_QUADTUP_INDEX,
43e9d192
IB
1488 SIMD_ARG_STOP
1489} builtin_simd_arg;
1490
e95a988a 1491
43e9d192
IB
1492static rtx
1493aarch64_simd_expand_args (rtx target, int icode, int have_retval,
4d0a0237 1494 tree exp, builtin_simd_arg *args,
b8506a8a 1495 machine_mode builtin_mode)
43e9d192 1496{
43e9d192 1497 rtx pat;
d9e80f49
AL
1498 rtx op[SIMD_MAX_BUILTIN_ARGS + 1]; /* First element for result operand. */
1499 int opc = 0;
1500
1501 if (have_retval)
1502 {
1503 machine_mode tmode = insn_data[icode].operand[0].mode;
1504 if (!target
43e9d192 1505 || GET_MODE (target) != tmode
d9e80f49
AL
1506 || !(*insn_data[icode].operand[0].predicate) (target, tmode))
1507 target = gen_reg_rtx (tmode);
1508 op[opc++] = target;
1509 }
43e9d192 1510
43e9d192
IB
1511 for (;;)
1512 {
d9e80f49 1513 builtin_simd_arg thisarg = args[opc - have_retval];
43e9d192
IB
1514
1515 if (thisarg == SIMD_ARG_STOP)
1516 break;
1517 else
1518 {
d9e80f49 1519 tree arg = CALL_EXPR_ARG (exp, opc - have_retval);
b8506a8a 1520 machine_mode mode = insn_data[icode].operand[opc].mode;
d9e80f49 1521 op[opc] = expand_normal (arg);
43e9d192
IB
1522
1523 switch (thisarg)
1524 {
1525 case SIMD_ARG_COPY_TO_REG:
d9e80f49
AL
1526 if (POINTER_TYPE_P (TREE_TYPE (arg)))
1527 op[opc] = convert_memory_address (Pmode, op[opc]);
1528 /*gcc_assert (GET_MODE (op[opc]) == mode); */
1529 if (!(*insn_data[icode].operand[opc].predicate)
1530 (op[opc], mode))
1531 op[opc] = copy_to_mode_reg (mode, op[opc]);
43e9d192
IB
1532 break;
1533
4d0a0237
CB
1534 case SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX:
1535 gcc_assert (opc > 1);
1536 if (CONST_INT_P (op[opc]))
1537 {
6a70badb
RS
1538 unsigned int nunits
1539 = GET_MODE_NUNITS (builtin_mode).to_constant ();
1540 aarch64_simd_lane_bounds (op[opc], 0, nunits, exp);
4d0a0237 1541 /* Keep to GCC-vector-extension lane indices in the RTL. */
7ac29c0f
RS
1542 op[opc] = aarch64_endian_lane_rtx (builtin_mode,
1543 INTVAL (op[opc]));
4d0a0237
CB
1544 }
1545 goto constant_arg;
1546
2a49c16d
AL
1547 case SIMD_ARG_LANE_INDEX:
1548 /* Must be a previous operand into which this is an index. */
d9e80f49
AL
1549 gcc_assert (opc > 0);
1550 if (CONST_INT_P (op[opc]))
2a49c16d 1551 {
d9e80f49 1552 machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
6a70badb
RS
1553 unsigned int nunits
1554 = GET_MODE_NUNITS (vmode).to_constant ();
1555 aarch64_simd_lane_bounds (op[opc], 0, nunits, exp);
2a49c16d 1556 /* Keep to GCC-vector-extension lane indices in the RTL. */
7ac29c0f 1557 op[opc] = aarch64_endian_lane_rtx (vmode, INTVAL (op[opc]));
2a49c16d 1558 }
9d63f43b
TC
1559 /* If the lane index isn't a constant then error out. */
1560 goto constant_arg;
1561
1562 case SIMD_ARG_LANE_PAIR_INDEX:
1563 /* Must be a previous operand into which this is an index and
1564 index is restricted to nunits / 2. */
1565 gcc_assert (opc > 0);
1566 if (CONST_INT_P (op[opc]))
1567 {
1568 machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
1569 unsigned int nunits
1570 = GET_MODE_NUNITS (vmode).to_constant ();
1571 aarch64_simd_lane_bounds (op[opc], 0, nunits / 2, exp);
1572 /* Keep to GCC-vector-extension lane indices in the RTL. */
33b5a38c
TC
1573 int lane = INTVAL (op[opc]);
1574 op[opc] = gen_int_mode (ENDIAN_LANE_N (nunits / 2, lane),
1575 SImode);
9d63f43b 1576 }
8c197c85
SMW
1577 /* If the lane index isn't a constant then error out. */
1578 goto constant_arg;
1579 case SIMD_ARG_LANE_QUADTUP_INDEX:
1580 /* Must be a previous operand into which this is an index and
1581 index is restricted to nunits / 4. */
1582 gcc_assert (opc > 0);
1583 if (CONST_INT_P (op[opc]))
1584 {
1585 machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
1586 unsigned int nunits
1587 = GET_MODE_NUNITS (vmode).to_constant ();
1588 aarch64_simd_lane_bounds (op[opc], 0, nunits / 4, exp);
1589 /* Keep to GCC-vector-extension lane indices in the RTL. */
1590 int lane = INTVAL (op[opc]);
1591 op[opc] = gen_int_mode (ENDIAN_LANE_N (nunits / 4, lane),
1592 SImode);
1593 }
1594 /* If the lane index isn't a constant then error out. */
1595 goto constant_arg;
43e9d192 1596 case SIMD_ARG_CONSTANT:
4d0a0237 1597constant_arg:
d9e80f49
AL
1598 if (!(*insn_data[icode].operand[opc].predicate)
1599 (op[opc], mode))
d5a29419 1600 {
fca051af
AL
1601 error ("%Kargument %d must be a constant immediate",
1602 exp, opc + 1 - have_retval);
d5a29419
KT
1603 return const0_rtx;
1604 }
43e9d192
IB
1605 break;
1606
1607 case SIMD_ARG_STOP:
1608 gcc_unreachable ();
1609 }
1610
d9e80f49 1611 opc++;
43e9d192
IB
1612 }
1613 }
1614
d9e80f49
AL
1615 switch (opc)
1616 {
1617 case 1:
1618 pat = GEN_FCN (icode) (op[0]);
1619 break;
43e9d192 1620
d9e80f49
AL
1621 case 2:
1622 pat = GEN_FCN (icode) (op[0], op[1]);
1623 break;
43e9d192 1624
d9e80f49
AL
1625 case 3:
1626 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
1627 break;
43e9d192 1628
d9e80f49
AL
1629 case 4:
1630 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
1631 break;
43e9d192 1632
d9e80f49
AL
1633 case 5:
1634 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
1635 break;
43e9d192 1636
d9e80f49
AL
1637 case 6:
1638 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]);
1639 break;
43e9d192 1640
d9e80f49
AL
1641 default:
1642 gcc_unreachable ();
1643 }
43e9d192
IB
1644
1645 if (!pat)
d5a29419 1646 return NULL_RTX;
43e9d192
IB
1647
1648 emit_insn (pat);
1649
1650 return target;
1651}
1652
1653/* Expand an AArch64 AdvSIMD builtin(intrinsic). */
1654rtx
1655aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
1656{
661fce82
AL
1657 if (fcode == AARCH64_SIMD_BUILTIN_LANE_CHECK)
1658 {
9c4f25cc
AP
1659 rtx totalsize = expand_normal (CALL_EXPR_ARG (exp, 0));
1660 rtx elementsize = expand_normal (CALL_EXPR_ARG (exp, 1));
1661 if (CONST_INT_P (totalsize) && CONST_INT_P (elementsize)
1662 && UINTVAL (elementsize) != 0
1663 && UINTVAL (totalsize) != 0)
1664 {
1665 rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 2));
1666 if (CONST_INT_P (lane_idx))
1667 aarch64_simd_lane_bounds (lane_idx, 0,
1668 UINTVAL (totalsize)
1669 / UINTVAL (elementsize),
1670 exp);
1671 else
1672 error ("%Klane index must be a constant immediate", exp);
1673 }
661fce82 1674 else
9c4f25cc 1675 error ("%Ktotal size and element size must be a non-zero constant immediate", exp);
661fce82
AL
1676 /* Don't generate any RTL. */
1677 return const0_rtx;
1678 }
342be7f7 1679 aarch64_simd_builtin_datum *d =
661fce82 1680 &aarch64_simd_builtin_data[fcode - AARCH64_SIMD_PATTERN_START];
342be7f7 1681 enum insn_code icode = d->code;
0ff2bf46 1682 builtin_simd_arg args[SIMD_MAX_BUILTIN_ARGS + 1];
b5828b4b
JG
1683 int num_args = insn_data[d->code].n_operands;
1684 int is_void = 0;
1685 int k;
43e9d192 1686
b5828b4b 1687 is_void = !!(d->qualifiers[0] & qualifier_void);
43e9d192 1688
b5828b4b
JG
1689 num_args += is_void;
1690
1691 for (k = 1; k < num_args; k++)
1692 {
1693 /* We have four arrays of data, each indexed in a different fashion.
1694 qualifiers - element 0 always describes the function return type.
1695 operands - element 0 is either the operand for return value (if
1696 the function has a non-void return type) or the operand for the
1697 first argument.
1698 expr_args - element 0 always holds the first argument.
1699 args - element 0 is always used for the return type. */
1700 int qualifiers_k = k;
1701 int operands_k = k - is_void;
1702 int expr_args_k = k - 1;
1703
2a49c16d
AL
1704 if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
1705 args[k] = SIMD_ARG_LANE_INDEX;
9d63f43b
TC
1706 else if (d->qualifiers[qualifiers_k] & qualifier_lane_pair_index)
1707 args[k] = SIMD_ARG_LANE_PAIR_INDEX;
8c197c85
SMW
1708 else if (d->qualifiers[qualifiers_k] & qualifier_lane_quadtup_index)
1709 args[k] = SIMD_ARG_LANE_QUADTUP_INDEX;
4d0a0237
CB
1710 else if (d->qualifiers[qualifiers_k] & qualifier_struct_load_store_lane_index)
1711 args[k] = SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX;
2a49c16d 1712 else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
b5828b4b
JG
1713 args[k] = SIMD_ARG_CONSTANT;
1714 else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
1715 {
1716 rtx arg
1717 = expand_normal (CALL_EXPR_ARG (exp,
1718 (expr_args_k)));
1719 /* Handle constants only if the predicate allows it. */
1720 bool op_const_int_p =
1721 (CONST_INT_P (arg)
1722 && (*insn_data[icode].operand[operands_k].predicate)
1723 (arg, insn_data[icode].operand[operands_k].mode));
1724 args[k] = op_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG;
1725 }
1726 else
1727 args[k] = SIMD_ARG_COPY_TO_REG;
43e9d192 1728
43e9d192 1729 }
b5828b4b
JG
1730 args[k] = SIMD_ARG_STOP;
1731
1732 /* The interface to aarch64_simd_expand_args expects a 0 if
1733 the function is void, and a 1 if it is not. */
1734 return aarch64_simd_expand_args
4d0a0237 1735 (target, icode, !is_void, exp, &args[1], d->mode);
43e9d192 1736}
342be7f7 1737
5d357f26
KT
1738rtx
1739aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target)
1740{
1741 rtx pat;
1742 aarch64_crc_builtin_datum *d
1743 = &aarch64_crc_builtin_data[fcode - (AARCH64_CRC32_BUILTIN_BASE + 1)];
1744 enum insn_code icode = d->icode;
1745 tree arg0 = CALL_EXPR_ARG (exp, 0);
1746 tree arg1 = CALL_EXPR_ARG (exp, 1);
1747 rtx op0 = expand_normal (arg0);
1748 rtx op1 = expand_normal (arg1);
ef4bddc2
RS
1749 machine_mode tmode = insn_data[icode].operand[0].mode;
1750 machine_mode mode0 = insn_data[icode].operand[1].mode;
1751 machine_mode mode1 = insn_data[icode].operand[2].mode;
5d357f26
KT
1752
1753 if (! target
1754 || GET_MODE (target) != tmode
1755 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
1756 target = gen_reg_rtx (tmode);
1757
1758 gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
1759 && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
1760
1761 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
1762 op0 = copy_to_mode_reg (mode0, op0);
1763 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
1764 op1 = copy_to_mode_reg (mode1, op1);
1765
1766 pat = GEN_FCN (icode) (target, op0, op1);
d5a29419
KT
1767 if (!pat)
1768 return NULL_RTX;
1769
5d357f26
KT
1770 emit_insn (pat);
1771 return target;
1772}
1773
a6fc00da
BH
1774/* Function to expand reciprocal square root builtins. */
1775
1776static rtx
1777aarch64_expand_builtin_rsqrt (int fcode, tree exp, rtx target)
1778{
1779 tree arg0 = CALL_EXPR_ARG (exp, 0);
1780 rtx op0 = expand_normal (arg0);
1781
1782 rtx (*gen) (rtx, rtx);
1783
1784 switch (fcode)
1785 {
1786 case AARCH64_BUILTIN_RSQRT_DF:
ee62a5a6 1787 gen = gen_rsqrtdf2;
a6fc00da
BH
1788 break;
1789 case AARCH64_BUILTIN_RSQRT_SF:
ee62a5a6 1790 gen = gen_rsqrtsf2;
a6fc00da
BH
1791 break;
1792 case AARCH64_BUILTIN_RSQRT_V2DF:
ee62a5a6 1793 gen = gen_rsqrtv2df2;
a6fc00da
BH
1794 break;
1795 case AARCH64_BUILTIN_RSQRT_V2SF:
ee62a5a6 1796 gen = gen_rsqrtv2sf2;
a6fc00da
BH
1797 break;
1798 case AARCH64_BUILTIN_RSQRT_V4SF:
ee62a5a6 1799 gen = gen_rsqrtv4sf2;
a6fc00da
BH
1800 break;
1801 default: gcc_unreachable ();
1802 }
1803
1804 if (!target)
1805 target = gen_reg_rtx (GET_MODE (op0));
1806
1807 emit_insn (gen (target, op0));
1808
1809 return target;
1810}
1811
9d63f43b
TC
1812/* Expand a FCMLA lane expression EXP with code FCODE and
1813 result going to TARGET if that is convenient. */
1814
1815rtx
1816aarch64_expand_fcmla_builtin (tree exp, rtx target, int fcode)
1817{
1818 int bcode = fcode - AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE - 1;
1819 aarch64_fcmla_laneq_builtin_datum* d
1820 = &aarch64_fcmla_lane_builtin_data[bcode];
1821 machine_mode quadmode = GET_MODE_2XWIDER_MODE (d->mode).require ();
1822 rtx op0 = force_reg (d->mode, expand_normal (CALL_EXPR_ARG (exp, 0)));
1823 rtx op1 = force_reg (d->mode, expand_normal (CALL_EXPR_ARG (exp, 1)));
1824 rtx op2 = force_reg (quadmode, expand_normal (CALL_EXPR_ARG (exp, 2)));
1825 tree tmp = CALL_EXPR_ARG (exp, 3);
1826 rtx lane_idx = expand_expr (tmp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
1827
1828 /* Validate that the lane index is a constant. */
1829 if (!CONST_INT_P (lane_idx))
1830 {
1831 error ("%Kargument %d must be a constant immediate", exp, 4);
1832 return const0_rtx;
1833 }
1834
1835 /* Validate that the index is within the expected range. */
1836 int nunits = GET_MODE_NUNITS (quadmode).to_constant ();
1837 aarch64_simd_lane_bounds (lane_idx, 0, nunits / 2, exp);
1838
9d63f43b
TC
1839 /* Generate the correct register and mode. */
1840 int lane = INTVAL (lane_idx);
1841
1842 if (lane < nunits / 4)
33b5a38c
TC
1843 op2 = simplify_gen_subreg (d->mode, op2, quadmode,
1844 subreg_lowpart_offset (d->mode, quadmode));
9d63f43b
TC
1845 else
1846 {
1847 /* Select the upper 64 bits, either a V2SF or V4HF, this however
1848 is quite messy, as the operation required even though simple
1849 doesn't have a simple RTL pattern, and seems it's quite hard to
1850 define using a single RTL pattern. The target generic version
1851 gen_highpart_mode generates code that isn't optimal. */
1852 rtx temp1 = gen_reg_rtx (d->mode);
1853 rtx temp2 = gen_reg_rtx (DImode);
33b5a38c
TC
1854 temp1 = simplify_gen_subreg (d->mode, op2, quadmode,
1855 subreg_lowpart_offset (d->mode, quadmode));
9d63f43b 1856 temp1 = simplify_gen_subreg (V2DImode, temp1, d->mode, 0);
33b5a38c
TC
1857 if (BYTES_BIG_ENDIAN)
1858 emit_insn (gen_aarch64_get_lanev2di (temp2, temp1, const0_rtx));
1859 else
1860 emit_insn (gen_aarch64_get_lanev2di (temp2, temp1, const1_rtx));
9d63f43b
TC
1861 op2 = simplify_gen_subreg (d->mode, temp2, GET_MODE (temp2), 0);
1862
1863 /* And recalculate the index. */
1864 lane -= nunits / 4;
1865 }
1866
33b5a38c
TC
1867 /* Keep to GCC-vector-extension lane indices in the RTL, only nunits / 4
1868 (max nunits in range check) are valid. Which means only 0-1, so we
1869 only need to know the order in a V2mode. */
1870 lane_idx = aarch64_endian_lane_rtx (V2DImode, lane);
1871
9d63f43b
TC
1872 if (!target)
1873 target = gen_reg_rtx (d->mode);
1874 else
1875 target = force_reg (d->mode, target);
1876
1877 rtx pat = NULL_RTX;
1878
1879 if (d->lane)
33b5a38c 1880 pat = GEN_FCN (d->icode) (target, op0, op1, op2, lane_idx);
9d63f43b
TC
1881 else
1882 pat = GEN_FCN (d->icode) (target, op0, op1, op2);
1883
1884 if (!pat)
1885 return NULL_RTX;
1886
1887 emit_insn (pat);
1888 return target;
1889}
1890
89626179
SD
1891/* Function to expand an expression EXP which calls one of the Transactional
1892 Memory Extension (TME) builtins FCODE with the result going to TARGET. */
1893static rtx
1894aarch64_expand_builtin_tme (int fcode, tree exp, rtx target)
1895{
1896 switch (fcode)
1897 {
1898 case AARCH64_TME_BUILTIN_TSTART:
1899 target = gen_reg_rtx (DImode);
1900 emit_insn (GEN_FCN (CODE_FOR_tstart) (target));
1901 break;
1902
1903 case AARCH64_TME_BUILTIN_TTEST:
1904 target = gen_reg_rtx (DImode);
1905 emit_insn (GEN_FCN (CODE_FOR_ttest) (target));
1906 break;
1907
1908 case AARCH64_TME_BUILTIN_TCOMMIT:
1909 emit_insn (GEN_FCN (CODE_FOR_tcommit) ());
1910 break;
1911
1912 case AARCH64_TME_BUILTIN_TCANCEL:
1913 {
1914 tree arg0 = CALL_EXPR_ARG (exp, 0);
1915 rtx op0 = expand_normal (arg0);
1916 if (CONST_INT_P (op0) && UINTVAL (op0) <= 65536)
1917 emit_insn (GEN_FCN (CODE_FOR_tcancel) (op0));
1918 else
1919 {
1920 error ("%Kargument must be a 16-bit constant immediate", exp);
1921 return const0_rtx;
1922 }
1923 }
1924 break;
1925
1926 default :
1927 gcc_unreachable ();
1928 }
1929 return target;
1930}
1931
c5dc215d
KT
1932/* Expand a random number builtin EXP with code FCODE, putting the result
1933 int TARGET. If IGNORE is true the return value is ignored. */
1934
1935rtx
1936aarch64_expand_rng_builtin (tree exp, rtx target, int fcode, int ignore)
1937{
1938 rtx pat;
1939 enum insn_code icode;
1940 if (fcode == AARCH64_BUILTIN_RNG_RNDR)
1941 icode = CODE_FOR_aarch64_rndr;
1942 else if (fcode == AARCH64_BUILTIN_RNG_RNDRRS)
1943 icode = CODE_FOR_aarch64_rndrrs;
1944 else
1945 gcc_unreachable ();
1946
1947 rtx rand = gen_reg_rtx (DImode);
1948 pat = GEN_FCN (icode) (rand);
1949 if (!pat)
1950 return NULL_RTX;
1951
1952 tree arg0 = CALL_EXPR_ARG (exp, 0);
1953 rtx res_addr = expand_normal (arg0);
1954 res_addr = convert_memory_address (Pmode, res_addr);
1955 rtx res_mem = gen_rtx_MEM (DImode, res_addr);
1956 emit_insn (pat);
1957 emit_move_insn (res_mem, rand);
1958 /* If the status result is unused don't generate the CSET code. */
1959 if (ignore)
1960 return target;
1961
1962 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
1963 rtx cmp_rtx = gen_rtx_fmt_ee (NE, SImode, cc_reg, const0_rtx);
1964 emit_insn (gen_aarch64_cstoresi (target, cmp_rtx, cc_reg));
1965 return target;
1966}
1967
ef01e6bb
DZ
1968/* Expand an expression EXP that calls a MEMTAG built-in FCODE
1969 with result going to TARGET. */
1970static rtx
1971aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)
1972{
1973 if (TARGET_ILP32)
1974 {
1975 error ("Memory Tagging Extension does not support %<-mabi=ilp32%>");
1976 return const0_rtx;
1977 }
1978
1979 rtx pat = NULL;
1980 enum insn_code icode = aarch64_memtag_builtin_data[fcode -
1981 AARCH64_MEMTAG_BUILTIN_START - 1].icode;
1982
1983 rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
1984 machine_mode mode0 = GET_MODE (op0);
1985 op0 = force_reg (mode0 == VOIDmode ? DImode : mode0, op0);
1986 op0 = convert_to_mode (DImode, op0, true);
1987
1988 switch (fcode)
1989 {
1990 case AARCH64_MEMTAG_BUILTIN_IRG:
1991 case AARCH64_MEMTAG_BUILTIN_GMI:
1992 case AARCH64_MEMTAG_BUILTIN_SUBP:
1993 case AARCH64_MEMTAG_BUILTIN_INC_TAG:
1994 {
1995 if (! target
1996 || GET_MODE (target) != DImode
1997 || ! (*insn_data[icode].operand[0].predicate) (target, DImode))
1998 target = gen_reg_rtx (DImode);
1999
2000 if (fcode == AARCH64_MEMTAG_BUILTIN_INC_TAG)
2001 {
2002 rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2003
2004 if ((*insn_data[icode].operand[3].predicate) (op1, QImode))
2005 {
2006 pat = GEN_FCN (icode) (target, op0, const0_rtx, op1);
2007 break;
2008 }
2009 error ("%Kargument %d must be a constant immediate "
2010 "in range [0,15]", exp, 2);
2011 return const0_rtx;
2012 }
2013 else
2014 {
2015 rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2016 machine_mode mode1 = GET_MODE (op1);
2017 op1 = force_reg (mode1 == VOIDmode ? DImode : mode1, op1);
2018 op1 = convert_to_mode (DImode, op1, true);
2019 pat = GEN_FCN (icode) (target, op0, op1);
2020 }
2021 break;
2022 }
2023 case AARCH64_MEMTAG_BUILTIN_GET_TAG:
2024 target = op0;
2025 pat = GEN_FCN (icode) (target, op0, const0_rtx);
2026 break;
2027 case AARCH64_MEMTAG_BUILTIN_SET_TAG:
2028 pat = GEN_FCN (icode) (op0, op0, const0_rtx);
2029 break;
2030 default:
2031 gcc_unreachable();
2032 }
2033
2034 if (!pat)
2035 return NULL_RTX;
2036
2037 emit_insn (pat);
2038 return target;
2039}
2040
0d7e5fa6
AC
2041/* Expand an expression EXP as fpsr or cpsr setter (depending on
2042 UNSPEC) using MODE. */
2043static void
2044aarch64_expand_fpsr_fpcr_setter (int unspec, machine_mode mode, tree exp)
2045{
2046 tree arg = CALL_EXPR_ARG (exp, 0);
2047 rtx op = force_reg (mode, expand_normal (arg));
2048 emit_insn (gen_aarch64_set (unspec, mode, op));
2049}
2050
6d4d616a 2051/* Expand an expression EXP that calls built-in function FCODE,
c5dc215d
KT
2052 with result going to TARGET if that's convenient. IGNORE is true
2053 if the result of the builtin is ignored. */
342be7f7 2054rtx
c5dc215d
KT
2055aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
2056 int ignore)
342be7f7 2057{
aa87aced 2058 int icode;
0d7e5fa6 2059 rtx op0;
aa87aced
KV
2060 tree arg0;
2061
2062 switch (fcode)
2063 {
2064 case AARCH64_BUILTIN_GET_FPCR:
0d7e5fa6
AC
2065 emit_insn (gen_aarch64_get (UNSPECV_GET_FPCR, SImode, target));
2066 return target;
aa87aced 2067 case AARCH64_BUILTIN_SET_FPCR:
0d7e5fa6
AC
2068 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR, SImode, exp);
2069 return target;
aa87aced 2070 case AARCH64_BUILTIN_GET_FPSR:
0d7e5fa6
AC
2071 emit_insn (gen_aarch64_get (UNSPECV_GET_FPSR, SImode, target));
2072 return target;
aa87aced 2073 case AARCH64_BUILTIN_SET_FPSR:
0d7e5fa6
AC
2074 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR, SImode, exp);
2075 return target;
2076 case AARCH64_BUILTIN_GET_FPCR64:
2077 emit_insn (gen_aarch64_get (UNSPECV_GET_FPCR, DImode, target));
2078 return target;
2079 case AARCH64_BUILTIN_SET_FPCR64:
2080 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR, DImode, exp);
2081 return target;
2082 case AARCH64_BUILTIN_GET_FPSR64:
2083 emit_insn (gen_aarch64_get (UNSPECV_GET_FPSR, DImode, target));
2084 return target;
2085 case AARCH64_BUILTIN_SET_FPSR64:
2086 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR, DImode, exp);
aa87aced 2087 return target;
312492bd
JW
2088 case AARCH64_PAUTH_BUILTIN_AUTIA1716:
2089 case AARCH64_PAUTH_BUILTIN_PACIA1716:
8fc16d72
ST
2090 case AARCH64_PAUTH_BUILTIN_AUTIB1716:
2091 case AARCH64_PAUTH_BUILTIN_PACIB1716:
312492bd
JW
2092 case AARCH64_PAUTH_BUILTIN_XPACLRI:
2093 arg0 = CALL_EXPR_ARG (exp, 0);
2094 op0 = force_reg (Pmode, expand_normal (arg0));
2095
2096 if (!target)
2097 target = gen_reg_rtx (Pmode);
2098 else
2099 target = force_reg (Pmode, target);
2100
2101 emit_move_insn (target, op0);
2102
2103 if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
2104 {
2105 rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
2106 icode = CODE_FOR_xpaclri;
2107 emit_move_insn (lr, op0);
2108 emit_insn (GEN_FCN (icode) ());
2109 emit_move_insn (target, lr);
2110 }
2111 else
2112 {
2113 tree arg1 = CALL_EXPR_ARG (exp, 1);
2114 rtx op1 = force_reg (Pmode, expand_normal (arg1));
8fc16d72
ST
2115 switch (fcode)
2116 {
2117 case AARCH64_PAUTH_BUILTIN_AUTIA1716:
2118 icode = CODE_FOR_autia1716;
2119 break;
2120 case AARCH64_PAUTH_BUILTIN_AUTIB1716:
2121 icode = CODE_FOR_autib1716;
2122 break;
2123 case AARCH64_PAUTH_BUILTIN_PACIA1716:
2124 icode = CODE_FOR_pacia1716;
2125 break;
2126 case AARCH64_PAUTH_BUILTIN_PACIB1716:
2127 icode = CODE_FOR_pacib1716;
2128 break;
2129 default:
2130 icode = 0;
2131 gcc_unreachable ();
2132 }
312492bd
JW
2133
2134 rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
2135 rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
2136 emit_move_insn (x17_reg, op0);
2137 emit_move_insn (x16_reg, op1);
2138 emit_insn (GEN_FCN (icode) ());
2139 emit_move_insn (target, x17_reg);
2140 }
2141
2142 return target;
9d63f43b 2143
e1d5d19e
KT
2144 case AARCH64_JSCVT:
2145 arg0 = CALL_EXPR_ARG (exp, 0);
2146 op0 = force_reg (DFmode, expand_normal (arg0));
2147 if (!target)
2148 target = gen_reg_rtx (SImode);
2149 else
2150 target = force_reg (SImode, target);
2151 emit_insn (GEN_FCN (CODE_FOR_aarch64_fjcvtzs) (target, op0));
2152 return target;
2153
9d63f43b
TC
2154 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V2SF:
2155 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V2SF:
2156 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V2SF:
2157 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V2SF:
2158 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V4HF:
2159 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V4HF:
2160 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V4HF:
2161 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V4HF:
2162 return aarch64_expand_fcmla_builtin (exp, target, fcode);
c5dc215d
KT
2163 case AARCH64_BUILTIN_RNG_RNDR:
2164 case AARCH64_BUILTIN_RNG_RNDRRS:
2165 return aarch64_expand_rng_builtin (exp, target, fcode, ignore);
aa87aced 2166 }
342be7f7 2167
5d357f26 2168 if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
342be7f7 2169 return aarch64_simd_expand_builtin (fcode, exp, target);
5d357f26
KT
2170 else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX)
2171 return aarch64_crc32_expand_builtin (fcode, exp, target);
342be7f7 2172
a6fc00da
BH
2173 if (fcode == AARCH64_BUILTIN_RSQRT_DF
2174 || fcode == AARCH64_BUILTIN_RSQRT_SF
2175 || fcode == AARCH64_BUILTIN_RSQRT_V2DF
2176 || fcode == AARCH64_BUILTIN_RSQRT_V2SF
2177 || fcode == AARCH64_BUILTIN_RSQRT_V4SF)
2178 return aarch64_expand_builtin_rsqrt (fcode, exp, target);
2179
89626179
SD
2180 if (fcode == AARCH64_TME_BUILTIN_TSTART
2181 || fcode == AARCH64_TME_BUILTIN_TCOMMIT
2182 || fcode == AARCH64_TME_BUILTIN_TTEST
2183 || fcode == AARCH64_TME_BUILTIN_TCANCEL)
2184 return aarch64_expand_builtin_tme (fcode, exp, target);
2185
ef01e6bb
DZ
2186 if (fcode >= AARCH64_MEMTAG_BUILTIN_START
2187 && fcode <= AARCH64_MEMTAG_BUILTIN_END)
2188 return aarch64_expand_builtin_memtag (fcode, exp, target);
2189
d5a29419 2190 gcc_unreachable ();
342be7f7 2191}
42fc9a7f
JG
2192
2193tree
10766209
RS
2194aarch64_builtin_vectorized_function (unsigned int fn, tree type_out,
2195 tree type_in)
42fc9a7f 2196{
ef4bddc2 2197 machine_mode in_mode, out_mode;
42fc9a7f
JG
2198
2199 if (TREE_CODE (type_out) != VECTOR_TYPE
2200 || TREE_CODE (type_in) != VECTOR_TYPE)
2201 return NULL_TREE;
2202
7cee9637
RS
2203 out_mode = TYPE_MODE (type_out);
2204 in_mode = TYPE_MODE (type_in);
42fc9a7f
JG
2205
2206#undef AARCH64_CHECK_BUILTIN_MODE
2207#define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
2208#define AARCH64_FIND_FRINT_VARIANT(N) \
2209 (AARCH64_CHECK_BUILTIN_MODE (2, D) \
e993fea1 2210 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
42fc9a7f 2211 : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
e993fea1 2212 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
42fc9a7f 2213 : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
e993fea1 2214 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
42fc9a7f 2215 : NULL_TREE)))
10766209 2216 switch (fn)
42fc9a7f 2217 {
42fc9a7f
JG
2218#undef AARCH64_CHECK_BUILTIN_MODE
2219#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
7cee9637 2220 (out_mode == V##C##N##Fmode && in_mode == V##C##N##Fmode)
10766209
RS
2221 CASE_CFN_FLOOR:
2222 return AARCH64_FIND_FRINT_VARIANT (floor);
2223 CASE_CFN_CEIL:
2224 return AARCH64_FIND_FRINT_VARIANT (ceil);
2225 CASE_CFN_TRUNC:
2226 return AARCH64_FIND_FRINT_VARIANT (btrunc);
2227 CASE_CFN_ROUND:
2228 return AARCH64_FIND_FRINT_VARIANT (round);
2229 CASE_CFN_NEARBYINT:
2230 return AARCH64_FIND_FRINT_VARIANT (nearbyint);
2231 CASE_CFN_SQRT:
2232 return AARCH64_FIND_FRINT_VARIANT (sqrt);
42fc9a7f 2233#undef AARCH64_CHECK_BUILTIN_MODE
b5574232 2234#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
7cee9637 2235 (out_mode == V##C##SImode && in_mode == V##C##N##Imode)
10766209
RS
2236 CASE_CFN_CLZ:
2237 {
2238 if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2239 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_clzv4si];
2240 return NULL_TREE;
2241 }
2242 CASE_CFN_CTZ:
2243 {
2244 if (AARCH64_CHECK_BUILTIN_MODE (2, S))
2245 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si];
2246 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2247 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si];
2248 return NULL_TREE;
2249 }
b5574232 2250#undef AARCH64_CHECK_BUILTIN_MODE
42fc9a7f 2251#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
7cee9637 2252 (out_mode == V##C##N##Imode && in_mode == V##C##N##Fmode)
10766209
RS
2253 CASE_CFN_IFLOOR:
2254 CASE_CFN_LFLOOR:
2255 CASE_CFN_LLFLOOR:
2256 {
2257 enum aarch64_builtins builtin;
2258 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
2259 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di;
2260 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2261 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si;
2262 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
2263 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si;
2264 else
2265 return NULL_TREE;
2266
2267 return aarch64_builtin_decls[builtin];
2268 }
2269 CASE_CFN_ICEIL:
2270 CASE_CFN_LCEIL:
2271 CASE_CFN_LLCEIL:
2272 {
2273 enum aarch64_builtins builtin;
2274 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
2275 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di;
2276 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2277 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si;
2278 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
2279 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si;
2280 else
2281 return NULL_TREE;
2282
2283 return aarch64_builtin_decls[builtin];
2284 }
2285 CASE_CFN_IROUND:
2286 CASE_CFN_LROUND:
2287 CASE_CFN_LLROUND:
2288 {
2289 enum aarch64_builtins builtin;
2290 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
2291 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di;
2292 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2293 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si;
2294 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
2295 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si;
2296 else
2297 return NULL_TREE;
2298
2299 return aarch64_builtin_decls[builtin];
2300 }
10766209
RS
2301 default:
2302 return NULL_TREE;
42fc9a7f
JG
2303 }
2304
2305 return NULL_TREE;
2306}
0ac198d3 2307
a6fc00da
BH
2308/* Return builtin for reciprocal square root. */
2309
2310tree
6d4d616a 2311aarch64_general_builtin_rsqrt (unsigned int fn)
a6fc00da 2312{
ee62a5a6
RS
2313 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df)
2314 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2DF];
2315 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf)
2316 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2SF];
2317 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf)
2318 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V4SF];
a6fc00da
BH
2319 return NULL_TREE;
2320}
2321
0ac198d3 2322#undef VAR1
bf592b2f 2323#define VAR1(T, N, MAP, FLAG, A) \
e993fea1 2324 case AARCH64_SIMD_BUILTIN_##T##_##N##A:
0ac198d3 2325
6d4d616a
RS
2326/* Try to fold a call to the built-in function with subcode FCODE. The
2327 function is passed the N_ARGS arguments in ARGS and it returns a value
2328 of type TYPE. Return the new expression on success and NULL_TREE on
2329 failure. */
9697e620 2330tree
6d4d616a
RS
2331aarch64_general_fold_builtin (unsigned int fcode, tree type,
2332 unsigned int n_args ATTRIBUTE_UNUSED, tree *args)
9697e620 2333{
9697e620
JG
2334 switch (fcode)
2335 {
bf592b2f 2336 BUILTIN_VDQF (UNOP, abs, 2, ALL)
9697e620 2337 return fold_build1 (ABS_EXPR, type, args[0]);
bf592b2f 2338 VAR1 (UNOP, floatv2si, 2, ALL, v2sf)
2339 VAR1 (UNOP, floatv4si, 2, ALL, v4sf)
2340 VAR1 (UNOP, floatv2di, 2, ALL, v2df)
1709ff9b 2341 return fold_build1 (FLOAT_EXPR, type, args[0]);
9697e620
JG
2342 default:
2343 break;
2344 }
2345
2346 return NULL_TREE;
2347}
2348
6d4d616a
RS
2349/* Try to fold STMT, given that it's a call to the built-in function with
2350 subcode FCODE. Return the new statement on success and null on
2351 failure. */
2352gimple *
2353aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt)
0ac198d3 2354{
355fe088 2355 gimple *new_stmt = NULL;
6d4d616a
RS
2356 unsigned nargs = gimple_call_num_args (stmt);
2357 tree *args = (nargs > 0
2358 ? gimple_call_arg_ptr (stmt, 0)
2359 : &error_mark_node);
2360
2361 /* We use gimple's IFN_REDUC_(PLUS|MIN|MAX)s for float, signed int
2362 and unsigned int; it will distinguish according to the types of
2363 the arguments to the __builtin. */
2364 switch (fcode)
0ac198d3 2365 {
bf592b2f 2366 BUILTIN_VALL (UNOP, reduc_plus_scal_, 10, ALL)
6d4d616a
RS
2367 new_stmt = gimple_build_call_internal (IFN_REDUC_PLUS,
2368 1, args[0]);
2369 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
2370 break;
bf592b2f 2371 BUILTIN_VDQIF (UNOP, reduc_smax_scal_, 10, ALL)
2372 BUILTIN_VDQ_BHSI (UNOPU, reduc_umax_scal_, 10, ALL)
6d4d616a
RS
2373 new_stmt = gimple_build_call_internal (IFN_REDUC_MAX,
2374 1, args[0]);
2375 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
2376 break;
bf592b2f 2377 BUILTIN_VDQIF (UNOP, reduc_smin_scal_, 10, ALL)
2378 BUILTIN_VDQ_BHSI (UNOPU, reduc_umin_scal_, 10, ALL)
6d4d616a
RS
2379 new_stmt = gimple_build_call_internal (IFN_REDUC_MIN,
2380 1, args[0]);
2381 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
2382 break;
bf592b2f 2383 BUILTIN_GPF (BINOP, fmulx, 0, ALL)
0ac198d3 2384 {
6d4d616a
RS
2385 gcc_assert (nargs == 2);
2386 bool a0_cst_p = TREE_CODE (args[0]) == REAL_CST;
2387 bool a1_cst_p = TREE_CODE (args[1]) == REAL_CST;
2388 if (a0_cst_p || a1_cst_p)
0ac198d3 2389 {
6d4d616a 2390 if (a0_cst_p && a1_cst_p)
546e500c 2391 {
6d4d616a
RS
2392 tree t0 = TREE_TYPE (args[0]);
2393 real_value a0 = (TREE_REAL_CST (args[0]));
2394 real_value a1 = (TREE_REAL_CST (args[1]));
2395 if (real_equal (&a1, &dconst0))
2396 std::swap (a0, a1);
2397 /* According to real_equal (), +0 equals -0. */
2398 if (real_equal (&a0, &dconst0) && real_isinf (&a1))
546e500c 2399 {
6d4d616a
RS
2400 real_value res = dconst2;
2401 res.sign = a0.sign ^ a1.sign;
2402 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
2403 REAL_CST,
2404 build_real (t0, res));
546e500c 2405 }
6d4d616a
RS
2406 else
2407 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
2408 MULT_EXPR,
2409 args[0], args[1]);
546e500c 2410 }
6d4d616a
RS
2411 else /* a0_cst_p ^ a1_cst_p. */
2412 {
2413 real_value const_part = a0_cst_p
2414 ? TREE_REAL_CST (args[0]) : TREE_REAL_CST (args[1]);
2415 if (!real_equal (&const_part, &dconst0)
2416 && !real_isinf (&const_part))
2417 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
2418 MULT_EXPR, args[0],
2419 args[1]);
2420 }
2421 }
2422 if (new_stmt)
2423 {
2424 gimple_set_vuse (new_stmt, gimple_vuse (stmt));
2425 gimple_set_vdef (new_stmt, gimple_vdef (stmt));
0ac198d3 2426 }
6d4d616a 2427 break;
0ac198d3 2428 }
6d4d616a
RS
2429 default:
2430 break;
0ac198d3 2431 }
6d4d616a 2432 return new_stmt;
0ac198d3
JG
2433}
2434
aa87aced
KV
2435void
2436aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
2437{
2438 const unsigned AARCH64_FE_INVALID = 1;
2439 const unsigned AARCH64_FE_DIVBYZERO = 2;
2440 const unsigned AARCH64_FE_OVERFLOW = 4;
2441 const unsigned AARCH64_FE_UNDERFLOW = 8;
2442 const unsigned AARCH64_FE_INEXACT = 16;
2443 const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID
2444 | AARCH64_FE_DIVBYZERO
2445 | AARCH64_FE_OVERFLOW
2446 | AARCH64_FE_UNDERFLOW
2447 | AARCH64_FE_INEXACT);
2448 const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8;
2449 tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr;
2450 tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr;
2451 tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr;
2452 tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv;
2453
2454 /* Generate the equivalence of :
2455 unsigned int fenv_cr;
2456 fenv_cr = __builtin_aarch64_get_fpcr ();
2457
2458 unsigned int fenv_sr;
2459 fenv_sr = __builtin_aarch64_get_fpsr ();
2460
2461 Now set all exceptions to non-stop
2462 unsigned int mask_cr
2463 = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
2464 unsigned int masked_cr;
2465 masked_cr = fenv_cr & mask_cr;
2466
2467 And clear all exception flags
2468 unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
2469 unsigned int masked_cr;
2470 masked_sr = fenv_sr & mask_sr;
2471
2472 __builtin_aarch64_set_cr (masked_cr);
2473 __builtin_aarch64_set_sr (masked_sr); */
2474
09ba9ef7
RR
2475 fenv_cr = create_tmp_var_raw (unsigned_type_node);
2476 fenv_sr = create_tmp_var_raw (unsigned_type_node);
aa87aced
KV
2477
2478 get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR];
2479 set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR];
2480 get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR];
2481 set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR];
2482
2483 mask_cr = build_int_cst (unsigned_type_node,
2484 ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT));
2485 mask_sr = build_int_cst (unsigned_type_node,
2486 ~(AARCH64_FE_ALL_EXCEPT));
2487
d81bc2af
HZ
2488 ld_fenv_cr = build4 (TARGET_EXPR, unsigned_type_node,
2489 fenv_cr, build_call_expr (get_fpcr, 0),
2490 NULL_TREE, NULL_TREE);
2491 ld_fenv_sr = build4 (TARGET_EXPR, unsigned_type_node,
2492 fenv_sr, build_call_expr (get_fpsr, 0),
2493 NULL_TREE, NULL_TREE);
aa87aced
KV
2494
2495 masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr);
2496 masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr);
2497
2498 hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr);
2499 hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr);
2500
2501 hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr,
2502 hold_fnclex_sr);
2503 masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr,
2504 masked_fenv_sr);
2505 ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr);
2506
2507 *hold = build2 (COMPOUND_EXPR, void_type_node,
2508 build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
2509 hold_fnclex);
2510
2511 /* Store the value of masked_fenv to clear the exceptions:
2512 __builtin_aarch64_set_fpsr (masked_fenv_sr); */
2513
2514 *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr);
2515
2516 /* Generate the equivalent of :
2517 unsigned int new_fenv_var;
2518 new_fenv_var = __builtin_aarch64_get_fpsr ();
2519
2520 __builtin_aarch64_set_fpsr (fenv_sr);
2521
2522 __atomic_feraiseexcept (new_fenv_var); */
2523
09ba9ef7 2524 new_fenv_var = create_tmp_var_raw (unsigned_type_node);
d81bc2af
HZ
2525 reload_fenv = build4 (TARGET_EXPR, unsigned_type_node,
2526 new_fenv_var, build_call_expr (get_fpsr, 0),
2527 NULL_TREE, NULL_TREE);
aa87aced
KV
2528 restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr);
2529 atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
2530 update_call = build_call_expr (atomic_feraiseexcept, 1,
2531 fold_convert (integer_type_node, new_fenv_var));
2532 *update = build2 (COMPOUND_EXPR, void_type_node,
2533 build2 (COMPOUND_EXPR, void_type_node,
2534 reload_fenv, restore_fnenv), update_call);
2535}
2536
ef01e6bb
DZ
2537/* Resolve overloaded MEMTAG build-in functions. */
2538#define AARCH64_BUILTIN_SUBCODE(F) \
2539 (DECL_MD_FUNCTION_CODE (F) >> AARCH64_BUILTIN_SHIFT)
2540
2541static tree
2542aarch64_resolve_overloaded_memtag (location_t loc,
2543 tree fndecl, void *pass_params)
2544{
2545 vec<tree, va_gc> *params = static_cast<vec<tree, va_gc> *> (pass_params);
2546 unsigned param_num = params ? params->length() : 0;
2547 unsigned int fcode = AARCH64_BUILTIN_SUBCODE (fndecl);
2548 tree inittype = aarch64_memtag_builtin_data[
2549 fcode - AARCH64_MEMTAG_BUILTIN_START - 1].ftype;
2550 unsigned arg_num = list_length (TYPE_ARG_TYPES (inittype)) - 1;
2551
2552 if (param_num != arg_num)
2553 {
2554 TREE_TYPE (fndecl) = inittype;
2555 return NULL_TREE;
2556 }
2557 tree retype = NULL;
2558
2559 if (fcode == AARCH64_MEMTAG_BUILTIN_SUBP)
2560 {
2561 tree t0 = TREE_TYPE ((*params)[0]);
2562 tree t1 = TREE_TYPE ((*params)[1]);
2563
2564 if (t0 == error_mark_node || TREE_CODE (t0) != POINTER_TYPE)
2565 t0 = ptr_type_node;
2566 if (t1 == error_mark_node || TREE_CODE (t1) != POINTER_TYPE)
2567 t1 = ptr_type_node;
2568
2569 if (TYPE_MODE (t0) != DImode)
2570 warning_at (loc, 1, "expected 64-bit address but argument 1 is %d-bit",
2571 (int)tree_to_shwi (DECL_SIZE ((*params)[0])));
2572
2573 if (TYPE_MODE (t1) != DImode)
2574 warning_at (loc, 1, "expected 64-bit address but argument 2 is %d-bit",
2575 (int)tree_to_shwi (DECL_SIZE ((*params)[1])));
2576
2577 retype = build_function_type_list (ptrdiff_type_node, t0, t1, NULL);
2578 }
2579 else
2580 {
2581 tree t0 = TREE_TYPE ((*params)[0]);
2582
2583 if (t0 == error_mark_node || TREE_CODE (t0) != POINTER_TYPE)
2584 {
2585 TREE_TYPE (fndecl) = inittype;
2586 return NULL_TREE;
2587 }
2588
2589 if (TYPE_MODE (t0) != DImode)
2590 warning_at (loc, 1, "expected 64-bit address but argument 1 is %d-bit",
2591 (int)tree_to_shwi (DECL_SIZE ((*params)[0])));
2592
2593 switch (fcode)
2594 {
2595 case AARCH64_MEMTAG_BUILTIN_IRG:
2596 retype = build_function_type_list (t0, t0, uint64_type_node, NULL);
2597 break;
2598 case AARCH64_MEMTAG_BUILTIN_GMI:
2599 retype = build_function_type_list (uint64_type_node, t0,
2600 uint64_type_node, NULL);
2601 break;
2602 case AARCH64_MEMTAG_BUILTIN_INC_TAG:
2603 retype = build_function_type_list (t0, t0, unsigned_type_node, NULL);
2604 break;
2605 case AARCH64_MEMTAG_BUILTIN_SET_TAG:
2606 retype = build_function_type_list (void_type_node, t0, NULL);
2607 break;
2608 case AARCH64_MEMTAG_BUILTIN_GET_TAG:
2609 retype = build_function_type_list (t0, t0, NULL);
2610 break;
2611 default:
2612 return NULL_TREE;
2613 }
2614 }
2615
2616 if (!retype || retype == error_mark_node)
2617 TREE_TYPE (fndecl) = inittype;
2618 else
2619 TREE_TYPE (fndecl) = retype;
2620
2621 return NULL_TREE;
2622}
2623
2624/* Called at aarch64_resolve_overloaded_builtin in aarch64-c.c. */
2625tree
2626aarch64_resolve_overloaded_builtin_general (location_t loc, tree function,
2627 void *pass_params)
2628{
2629 unsigned int fcode = AARCH64_BUILTIN_SUBCODE (function);
2630
2631 if (fcode >= AARCH64_MEMTAG_BUILTIN_START
2632 && fcode <= AARCH64_MEMTAG_BUILTIN_END)
2633 return aarch64_resolve_overloaded_memtag(loc, function, pass_params);
2634
2635 return NULL_TREE;
2636}
aa87aced 2637
42fc9a7f
JG
2638#undef AARCH64_CHECK_BUILTIN_MODE
2639#undef AARCH64_FIND_FRINT_VARIANT
0ddec79f
JG
2640#undef CF0
2641#undef CF1
2642#undef CF2
2643#undef CF3
2644#undef CF4
2645#undef CF10
2646#undef VAR1
2647#undef VAR2
2648#undef VAR3
2649#undef VAR4
2650#undef VAR5
2651#undef VAR6
2652#undef VAR7
2653#undef VAR8
2654#undef VAR9
2655#undef VAR10
2656#undef VAR11
2657
3c03d39d 2658#include "gt-aarch64-builtins.h"