]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/aarch64/aarch64-builtins.cc
range: Workaround different type precision between _Float128 and long double [PR112788]
[thirdparty/gcc.git] / gcc / config / aarch64 / aarch64-builtins.cc
CommitLineData
43e9d192 1/* Builtins' description for AArch64 SIMD architecture.
83ffe9cd 2 Copyright (C) 2011-2023 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"
03312cbd 32#include "ssa.h"
4d0cdd0c 33#include "memmodel.h"
e11c4407
AM
34#include "tm_p.h"
35#include "expmed.h"
36#include "optabs.h"
37#include "recog.h"
38#include "diagnostic-core.h"
40e23961 39#include "fold-const.h"
d8a2d370 40#include "stor-layout.h"
36566b39 41#include "explow.h"
43e9d192 42#include "expr.h"
43e9d192 43#include "langhooks.h"
5be5c238 44#include "gimple-iterator.h"
10766209 45#include "case-cfn-macros.h"
9d63f43b 46#include "emit-rtl.h"
31427b97
RS
47#include "stringpool.h"
48#include "attribs.h"
ad44c6a5 49#include "gimple-fold.h"
fc42900d 50#include "builtins.h"
43e9d192 51
0d4a1197 52#define v8qi_UP E_V8QImode
fdcddba8 53#define v8di_UP E_V8DImode
0d4a1197
RS
54#define v4hi_UP E_V4HImode
55#define v4hf_UP E_V4HFmode
56#define v2si_UP E_V2SImode
57#define v2sf_UP E_V2SFmode
58#define v1df_UP E_V1DFmode
5ba864c5 59#define v1di_UP E_V1DImode
0d4a1197
RS
60#define di_UP E_DImode
61#define df_UP E_DFmode
62#define v16qi_UP E_V16QImode
63#define v8hi_UP E_V8HImode
64#define v8hf_UP E_V8HFmode
65#define v4si_UP E_V4SImode
66#define v4sf_UP E_V4SFmode
67#define v2di_UP E_V2DImode
68#define v2df_UP E_V2DFmode
69#define ti_UP E_TImode
70#define oi_UP E_OImode
71#define ci_UP E_CImode
72#define xi_UP E_XImode
73#define si_UP E_SImode
74#define sf_UP E_SFmode
75#define hi_UP E_HImode
76#define hf_UP E_HFmode
77#define qi_UP E_QImode
abbe1ed2
SMW
78#define bf_UP E_BFmode
79#define v4bf_UP E_V4BFmode
80#define v8bf_UP E_V8BFmode
66f206b8
JW
81#define v2x8qi_UP E_V2x8QImode
82#define v2x4hi_UP E_V2x4HImode
83#define v2x4hf_UP E_V2x4HFmode
84#define v2x4bf_UP E_V2x4BFmode
85#define v2x2si_UP E_V2x2SImode
86#define v2x2sf_UP E_V2x2SFmode
87#define v2x1di_UP E_V2x1DImode
88#define v2x1df_UP E_V2x1DFmode
89#define v2x16qi_UP E_V2x16QImode
90#define v2x8hi_UP E_V2x8HImode
91#define v2x8hf_UP E_V2x8HFmode
92#define v2x8bf_UP E_V2x8BFmode
93#define v2x4si_UP E_V2x4SImode
94#define v2x4sf_UP E_V2x4SFmode
95#define v2x2di_UP E_V2x2DImode
96#define v2x2df_UP E_V2x2DFmode
97#define v3x8qi_UP E_V3x8QImode
98#define v3x4hi_UP E_V3x4HImode
99#define v3x4hf_UP E_V3x4HFmode
100#define v3x4bf_UP E_V3x4BFmode
101#define v3x2si_UP E_V3x2SImode
102#define v3x2sf_UP E_V3x2SFmode
103#define v3x1di_UP E_V3x1DImode
104#define v3x1df_UP E_V3x1DFmode
105#define v3x16qi_UP E_V3x16QImode
106#define v3x8hi_UP E_V3x8HImode
107#define v3x8hf_UP E_V3x8HFmode
108#define v3x8bf_UP E_V3x8BFmode
109#define v3x4si_UP E_V3x4SImode
110#define v3x4sf_UP E_V3x4SFmode
111#define v3x2di_UP E_V3x2DImode
112#define v3x2df_UP E_V3x2DFmode
113#define v4x8qi_UP E_V4x8QImode
114#define v4x4hi_UP E_V4x4HImode
115#define v4x4hf_UP E_V4x4HFmode
116#define v4x4bf_UP E_V4x4BFmode
117#define v4x2si_UP E_V4x2SImode
118#define v4x2sf_UP E_V4x2SFmode
119#define v4x1di_UP E_V4x1DImode
120#define v4x1df_UP E_V4x1DFmode
121#define v4x16qi_UP E_V4x16QImode
122#define v4x8hi_UP E_V4x8HImode
123#define v4x8hf_UP E_V4x8HFmode
124#define v4x8bf_UP E_V4x8BFmode
125#define v4x4si_UP E_V4x4SImode
126#define v4x4sf_UP E_V4x4SFmode
127#define v4x2di_UP E_V4x2DImode
128#define v4x2df_UP E_V4x2DFmode
43e9d192
IB
129#define UP(X) X##_UP
130
c906efc7
AC
131#define MODE_d_bf16 E_V4BFmode
132#define MODE_d_f16 E_V4HFmode
133#define MODE_d_f32 E_V2SFmode
134#define MODE_d_f64 E_V1DFmode
135#define MODE_d_s8 E_V8QImode
136#define MODE_d_s16 E_V4HImode
137#define MODE_d_s32 E_V2SImode
138#define MODE_d_s64 E_V1DImode
139#define MODE_d_u8 E_V8QImode
140#define MODE_d_u16 E_V4HImode
141#define MODE_d_u32 E_V2SImode
142#define MODE_d_u64 E_V1DImode
143#define MODE_d_p8 E_V8QImode
144#define MODE_d_p16 E_V4HImode
145#define MODE_d_p64 E_V1DImode
146#define MODE_q_bf16 E_V8BFmode
147#define MODE_q_f16 E_V8HFmode
148#define MODE_q_f32 E_V4SFmode
149#define MODE_q_f64 E_V2DFmode
150#define MODE_q_s8 E_V16QImode
151#define MODE_q_s16 E_V8HImode
152#define MODE_q_s32 E_V4SImode
153#define MODE_q_s64 E_V2DImode
154#define MODE_q_u8 E_V16QImode
155#define MODE_q_u16 E_V8HImode
156#define MODE_q_u32 E_V4SImode
157#define MODE_q_u64 E_V2DImode
158#define MODE_q_p8 E_V16QImode
159#define MODE_q_p16 E_V8HImode
160#define MODE_q_p64 E_V2DImode
161#define MODE_q_p128 E_TImode
162
163#define QUAL_bf16 qualifier_none
164#define QUAL_f16 qualifier_none
165#define QUAL_f32 qualifier_none
166#define QUAL_f64 qualifier_none
167#define QUAL_s8 qualifier_none
168#define QUAL_s16 qualifier_none
169#define QUAL_s32 qualifier_none
170#define QUAL_s64 qualifier_none
171#define QUAL_u8 qualifier_unsigned
172#define QUAL_u16 qualifier_unsigned
173#define QUAL_u32 qualifier_unsigned
174#define QUAL_u64 qualifier_unsigned
175#define QUAL_p8 qualifier_poly
176#define QUAL_p16 qualifier_poly
177#define QUAL_p64 qualifier_poly
178#define QUAL_p128 qualifier_poly
179
180#define LENGTH_d ""
181#define LENGTH_q "q"
182
183#define SIMD_INTR_MODE(suffix, length) MODE_##length##_##suffix
184#define SIMD_INTR_QUAL(suffix) QUAL_##suffix
185#define SIMD_INTR_LENGTH_CHAR(length) LENGTH_##length
186
187
b5828b4b
JG
188#define SIMD_MAX_BUILTIN_ARGS 5
189
190enum aarch64_type_qualifiers
43e9d192 191{
b5828b4b
JG
192 /* T foo. */
193 qualifier_none = 0x0,
194 /* unsigned T foo. */
195 qualifier_unsigned = 0x1, /* 1 << 0 */
196 /* const T foo. */
197 qualifier_const = 0x2, /* 1 << 1 */
198 /* T *foo. */
199 qualifier_pointer = 0x4, /* 1 << 2 */
b5828b4b
JG
200 /* Used when expanding arguments if an operand could
201 be an immediate. */
202 qualifier_immediate = 0x8, /* 1 << 3 */
203 qualifier_maybe_immediate = 0x10, /* 1 << 4 */
204 /* void foo (...). */
205 qualifier_void = 0x20, /* 1 << 5 */
91259dd8 206 /* 1 << 6 is now unused */
b5828b4b
JG
207 /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
208 rather than using the type of the operand. */
209 qualifier_map_mode = 0x80, /* 1 << 7 */
210 /* qualifier_pointer | qualifier_map_mode */
211 qualifier_pointer_map_mode = 0x84,
e625e715 212 /* qualifier_const | qualifier_pointer | qualifier_map_mode */
6db1ec94
JG
213 qualifier_const_pointer_map_mode = 0x86,
214 /* Polynomial types. */
2a49c16d
AL
215 qualifier_poly = 0x100,
216 /* Lane indices - must be in range, and flipped for bigendian. */
4d0a0237
CB
217 qualifier_lane_index = 0x200,
218 /* Lane indices for single lane structure loads and stores. */
9d63f43b
TC
219 qualifier_struct_load_store_lane_index = 0x400,
220 /* Lane indices selected in pairs. - must be in range, and flipped for
221 bigendian. */
222 qualifier_lane_pair_index = 0x800,
8c197c85
SMW
223 /* Lane indices selected in quadtuplets. - must be in range, and flipped for
224 bigendian. */
225 qualifier_lane_quadtup_index = 0x1000,
b5828b4b 226};
43e9d192 227
bf592b2f 228/* Flags that describe what a function might do. */
229const unsigned int FLAG_NONE = 0U;
230const unsigned int FLAG_READ_FPCR = 1U << 0;
231const unsigned int FLAG_RAISE_FP_EXCEPTIONS = 1U << 1;
232const unsigned int FLAG_READ_MEMORY = 1U << 2;
233const unsigned int FLAG_PREFETCH_MEMORY = 1U << 3;
234const unsigned int FLAG_WRITE_MEMORY = 1U << 4;
235
35ffd4d1 236/* Not all FP intrinsics raise FP exceptions or read FPCR register,
237 use this flag to suppress it. */
238const unsigned int FLAG_AUTO_FP = 1U << 5;
239
bf592b2f 240const unsigned int FLAG_FP = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS;
241const unsigned int FLAG_ALL = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS
242 | FLAG_READ_MEMORY | FLAG_PREFETCH_MEMORY | FLAG_WRITE_MEMORY;
2d5aad69 243const unsigned int FLAG_STORE = FLAG_WRITE_MEMORY | FLAG_AUTO_FP;
e8062ad4 244const unsigned int FLAG_LOAD = FLAG_READ_MEMORY | FLAG_AUTO_FP;
bf592b2f 245
43e9d192
IB
246typedef struct
247{
248 const char *name;
ef4bddc2 249 machine_mode mode;
342be7f7
JG
250 const enum insn_code code;
251 unsigned int fcode;
b5828b4b 252 enum aarch64_type_qualifiers *qualifiers;
bf592b2f 253 unsigned int flags;
43e9d192
IB
254} aarch64_simd_builtin_datum;
255
b5828b4b
JG
256static enum aarch64_type_qualifiers
257aarch64_types_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
8f905d69 258 = { qualifier_none, qualifier_none };
b5828b4b 259#define TYPES_UNOP (aarch64_types_unop_qualifiers)
5a7a4e80
TB
260static enum aarch64_type_qualifiers
261aarch64_types_unopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
262 = { qualifier_unsigned, qualifier_unsigned };
263#define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
b5828b4b 264static enum aarch64_type_qualifiers
a579f4c7
JW
265aarch64_types_unopus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
266 = { qualifier_unsigned, qualifier_none };
267#define TYPES_UNOPUS (aarch64_types_unopus_qualifiers)
268static enum aarch64_type_qualifiers
b5828b4b
JG
269aarch64_types_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
270 = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
271#define TYPES_BINOP (aarch64_types_binop_qualifiers)
272static enum aarch64_type_qualifiers
5a7a4e80
TB
273aarch64_types_binopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
274 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
275#define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
7baa225d 276static enum aarch64_type_qualifiers
de10bcce
AL
277aarch64_types_binop_uus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
278 = { qualifier_unsigned, qualifier_unsigned, qualifier_none };
279#define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
280static enum aarch64_type_qualifiers
918621d3
AL
281aarch64_types_binop_ssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
282 = { qualifier_none, qualifier_none, qualifier_unsigned };
283#define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
284static enum aarch64_type_qualifiers
daef0a8c
JW
285aarch64_types_binop_uss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
286 = { qualifier_unsigned, qualifier_none, qualifier_none };
287#define TYPES_BINOP_USS (aarch64_types_binop_uss_qualifiers)
288static enum aarch64_type_qualifiers
7baa225d
TB
289aarch64_types_binopp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
290 = { qualifier_poly, qualifier_poly, qualifier_poly };
291#define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
3caf7f87
JW
292static enum aarch64_type_qualifiers
293aarch64_types_binop_ppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
294 = { qualifier_poly, qualifier_poly, qualifier_unsigned };
295#define TYPES_BINOP_PPU (aarch64_types_binop_ppu_qualifiers)
7baa225d 296
5a7a4e80 297static enum aarch64_type_qualifiers
b5828b4b
JG
298aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
299 = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
300#define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
30442682 301static enum aarch64_type_qualifiers
2a49c16d
AL
302aarch64_types_ternop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
303 = { qualifier_none, qualifier_none, qualifier_none, qualifier_lane_index };
304#define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
305static enum aarch64_type_qualifiers
30442682
TB
306aarch64_types_ternopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
307 = { qualifier_unsigned, qualifier_unsigned,
308 qualifier_unsigned, qualifier_unsigned };
309#define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
27086ea3 310static enum aarch64_type_qualifiers
0b839322
WD
311aarch64_types_ternopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
312 = { qualifier_unsigned, qualifier_unsigned,
313 qualifier_unsigned, qualifier_lane_index };
314#define TYPES_TERNOPU_LANE (aarch64_types_ternopu_lane_qualifiers)
315static enum aarch64_type_qualifiers
27086ea3
MC
316aarch64_types_ternopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
317 = { qualifier_unsigned, qualifier_unsigned,
318 qualifier_unsigned, qualifier_immediate };
319#define TYPES_TERNOPUI (aarch64_types_ternopu_imm_qualifiers)
8c197c85 320static enum aarch64_type_qualifiers
3caf7f87
JW
321aarch64_types_ternop_sssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
322 = { qualifier_none, qualifier_none, qualifier_none, qualifier_unsigned };
323#define TYPES_TERNOP_SSSU (aarch64_types_ternop_sssu_qualifiers)
324static enum aarch64_type_qualifiers
8c197c85
SMW
325aarch64_types_ternop_ssus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
326 = { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_none };
327#define TYPES_TERNOP_SSUS (aarch64_types_ternop_ssus_qualifiers)
2050ac1a
TC
328static enum aarch64_type_qualifiers
329aarch64_types_ternop_suss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
330 = { qualifier_none, qualifier_unsigned, qualifier_none, qualifier_none };
331#define TYPES_TERNOP_SUSS (aarch64_types_ternop_suss_qualifiers)
3caf7f87
JW
332static enum aarch64_type_qualifiers
333aarch64_types_binop_pppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
334 = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_unsigned };
335#define TYPES_TERNOP_PPPU (aarch64_types_binop_pppu_qualifiers)
27086ea3 336
9d63f43b
TC
337static enum aarch64_type_qualifiers
338aarch64_types_quadop_lane_pair_qualifiers[SIMD_MAX_BUILTIN_ARGS]
339 = { qualifier_none, qualifier_none, qualifier_none,
340 qualifier_none, qualifier_lane_pair_index };
341#define TYPES_QUADOP_LANE_PAIR (aarch64_types_quadop_lane_pair_qualifiers)
b5828b4b 342static enum aarch64_type_qualifiers
2a49c16d 343aarch64_types_quadop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
b5828b4b 344 = { qualifier_none, qualifier_none, qualifier_none,
2a49c16d
AL
345 qualifier_none, qualifier_lane_index };
346#define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
7a08d813
TC
347static enum aarch64_type_qualifiers
348aarch64_types_quadopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
349 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
350 qualifier_unsigned, qualifier_lane_index };
351#define TYPES_QUADOPU_LANE (aarch64_types_quadopu_lane_qualifiers)
b5828b4b 352
8c197c85
SMW
353static enum aarch64_type_qualifiers
354aarch64_types_quadopssus_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
355 = { qualifier_none, qualifier_none, qualifier_unsigned,
356 qualifier_none, qualifier_lane_quadtup_index };
357#define TYPES_QUADOPSSUS_LANE_QUADTUP \
358 (aarch64_types_quadopssus_lane_quadtup_qualifiers)
359static enum aarch64_type_qualifiers
360aarch64_types_quadopsssu_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
361 = { qualifier_none, qualifier_none, qualifier_none,
362 qualifier_unsigned, qualifier_lane_quadtup_index };
363#define TYPES_QUADOPSSSU_LANE_QUADTUP \
364 (aarch64_types_quadopsssu_lane_quadtup_qualifiers)
365
27086ea3
MC
366static enum aarch64_type_qualifiers
367aarch64_types_quadopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
368 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
369 qualifier_unsigned, qualifier_immediate };
370#define TYPES_QUADOPUI (aarch64_types_quadopu_imm_qualifiers)
371
b5828b4b 372static enum aarch64_type_qualifiers
2a49c16d 373aarch64_types_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
b5828b4b 374 = { qualifier_none, qualifier_none, qualifier_immediate };
2a49c16d
AL
375#define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
376#define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
b5828b4b 377static enum aarch64_type_qualifiers
de10bcce
AL
378aarch64_types_shift_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
379 = { qualifier_unsigned, qualifier_none, qualifier_immediate };
380#define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
381static enum aarch64_type_qualifiers
1f0e9e34
JG
382aarch64_types_fcvt_from_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
383 = { qualifier_none, qualifier_unsigned, qualifier_immediate };
384#define TYPES_FCVTIMM_SUS (aarch64_types_fcvt_from_unsigned_qualifiers)
385static enum aarch64_type_qualifiers
252c7556
AV
386aarch64_types_unsigned_shift_qualifiers[SIMD_MAX_BUILTIN_ARGS]
387 = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate };
388#define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
05f1883c
DC
389#define TYPES_USHIFT2IMM (aarch64_types_ternopu_imm_qualifiers)
390static enum aarch64_type_qualifiers
391aarch64_types_shift2_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
392 = { qualifier_unsigned, qualifier_unsigned, qualifier_none, qualifier_immediate };
393#define TYPES_SHIFT2IMM_UUSS (aarch64_types_shift2_to_unsigned_qualifiers)
de10bcce 394
159b8724
TC
395static enum aarch64_type_qualifiers
396aarch64_types_ternop_s_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
397 = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate};
398#define TYPES_SETREG (aarch64_types_ternop_s_imm_qualifiers)
399#define TYPES_SHIFTINSERT (aarch64_types_ternop_s_imm_qualifiers)
400#define TYPES_SHIFTACC (aarch64_types_ternop_s_imm_qualifiers)
05f1883c 401#define TYPES_SHIFT2IMM (aarch64_types_ternop_s_imm_qualifiers)
159b8724
TC
402
403static enum aarch64_type_qualifiers
404aarch64_types_ternop_p_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
405 = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_immediate};
406#define TYPES_SHIFTINSERTP (aarch64_types_ternop_p_imm_qualifiers)
b5828b4b 407
de10bcce
AL
408static enum aarch64_type_qualifiers
409aarch64_types_unsigned_shiftacc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
410 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
411 qualifier_immediate };
412#define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
413
b5828b4b
JG
414static enum aarch64_type_qualifiers
415aarch64_types_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
416 = { qualifier_none, qualifier_const_pointer_map_mode };
417#define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
418#define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
66f206b8
JW
419static enum aarch64_type_qualifiers
420aarch64_types_load1_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
421 = { qualifier_unsigned, qualifier_const_pointer_map_mode };
1716ddd1 422#define TYPES_LOAD1_U (aarch64_types_load1_u_qualifiers)
66f206b8
JW
423#define TYPES_LOADSTRUCT_U (aarch64_types_load1_u_qualifiers)
424static enum aarch64_type_qualifiers
425aarch64_types_load1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
426 = { qualifier_poly, qualifier_const_pointer_map_mode };
1716ddd1 427#define TYPES_LOAD1_P (aarch64_types_load1_p_qualifiers)
66f206b8
JW
428#define TYPES_LOADSTRUCT_P (aarch64_types_load1_p_qualifiers)
429
3ec1be97
CB
430static enum aarch64_type_qualifiers
431aarch64_types_loadstruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
432 = { qualifier_none, qualifier_const_pointer_map_mode,
4d0a0237 433 qualifier_none, qualifier_struct_load_store_lane_index };
3ec1be97 434#define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
66f206b8
JW
435static enum aarch64_type_qualifiers
436aarch64_types_loadstruct_lane_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
437 = { qualifier_unsigned, qualifier_const_pointer_map_mode,
438 qualifier_unsigned, qualifier_struct_load_store_lane_index };
439#define TYPES_LOADSTRUCT_LANE_U (aarch64_types_loadstruct_lane_u_qualifiers)
440static enum aarch64_type_qualifiers
441aarch64_types_loadstruct_lane_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
442 = { qualifier_poly, qualifier_const_pointer_map_mode,
443 qualifier_poly, qualifier_struct_load_store_lane_index };
444#define TYPES_LOADSTRUCT_LANE_P (aarch64_types_loadstruct_lane_p_qualifiers)
b5828b4b 445
46e778c4
JG
446static enum aarch64_type_qualifiers
447aarch64_types_bsl_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
448 = { qualifier_poly, qualifier_unsigned,
449 qualifier_poly, qualifier_poly };
450#define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
451static enum aarch64_type_qualifiers
452aarch64_types_bsl_s_qualifiers[SIMD_MAX_BUILTIN_ARGS]
453 = { qualifier_none, qualifier_unsigned,
454 qualifier_none, qualifier_none };
455#define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
456static enum aarch64_type_qualifiers
457aarch64_types_bsl_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
458 = { qualifier_unsigned, qualifier_unsigned,
459 qualifier_unsigned, qualifier_unsigned };
460#define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
461
b5828b4b
JG
462/* The first argument (return type) of a store should be void type,
463 which we represent with qualifier_void. Their first operand will be
464 a DImode pointer to the location to store to, so we must use
465 qualifier_map_mode | qualifier_pointer to build a pointer to the
466 element type of the vector. */
467static enum aarch64_type_qualifiers
468aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
469 = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
470#define TYPES_STORE1 (aarch64_types_store1_qualifiers)
471#define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
66f206b8
JW
472static enum aarch64_type_qualifiers
473aarch64_types_store1_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
474 = { qualifier_void, qualifier_pointer_map_mode, qualifier_unsigned };
1716ddd1 475#define TYPES_STORE1_U (aarch64_types_store1_u_qualifiers)
66f206b8
JW
476#define TYPES_STORESTRUCT_U (aarch64_types_store1_u_qualifiers)
477static enum aarch64_type_qualifiers
478aarch64_types_store1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
479 = { qualifier_void, qualifier_pointer_map_mode, qualifier_poly };
1716ddd1 480#define TYPES_STORE1_P (aarch64_types_store1_p_qualifiers)
66f206b8
JW
481#define TYPES_STORESTRUCT_P (aarch64_types_store1_p_qualifiers)
482
ba081b77
JG
483static enum aarch64_type_qualifiers
484aarch64_types_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
485 = { qualifier_void, qualifier_pointer_map_mode,
4d0a0237 486 qualifier_none, qualifier_struct_load_store_lane_index };
ba081b77 487#define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
66f206b8
JW
488static enum aarch64_type_qualifiers
489aarch64_types_storestruct_lane_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
490 = { qualifier_void, qualifier_pointer_map_mode,
491 qualifier_unsigned, qualifier_struct_load_store_lane_index };
492#define TYPES_STORESTRUCT_LANE_U (aarch64_types_storestruct_lane_u_qualifiers)
493static enum aarch64_type_qualifiers
494aarch64_types_storestruct_lane_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
495 = { qualifier_void, qualifier_pointer_map_mode,
496 qualifier_poly, qualifier_struct_load_store_lane_index };
497#define TYPES_STORESTRUCT_LANE_P (aarch64_types_storestruct_lane_p_qualifiers)
b5828b4b 498
0ddec79f
JG
499#define CF0(N, X) CODE_FOR_aarch64_##N##X
500#define CF1(N, X) CODE_FOR_##N##X##1
501#define CF2(N, X) CODE_FOR_##N##X##2
502#define CF3(N, X) CODE_FOR_##N##X##3
503#define CF4(N, X) CODE_FOR_##N##X##4
504#define CF10(N, X) CODE_FOR_##N##X
505
a4dae58a
KT
506/* Define cascading VAR<N> macros that are used from
507 aarch64-builtin-iterators.h to iterate over modes. These definitions
508 will end up generating a number of VAR1 expansions and code later on in the
509 file should redefine VAR1 to whatever it needs to process on a per-mode
510 basis. */
bf592b2f 511#define VAR2(T, N, MAP, FLAG, A, B) \
512 VAR1 (T, N, MAP, FLAG, A) \
513 VAR1 (T, N, MAP, FLAG, B)
514#define VAR3(T, N, MAP, FLAG, A, B, C) \
515 VAR2 (T, N, MAP, FLAG, A, B) \
516 VAR1 (T, N, MAP, FLAG, C)
517#define VAR4(T, N, MAP, FLAG, A, B, C, D) \
518 VAR3 (T, N, MAP, FLAG, A, B, C) \
519 VAR1 (T, N, MAP, FLAG, D)
520#define VAR5(T, N, MAP, FLAG, A, B, C, D, E) \
521 VAR4 (T, N, MAP, FLAG, A, B, C, D) \
522 VAR1 (T, N, MAP, FLAG, E)
523#define VAR6(T, N, MAP, FLAG, A, B, C, D, E, F) \
524 VAR5 (T, N, MAP, FLAG, A, B, C, D, E) \
525 VAR1 (T, N, MAP, FLAG, F)
526#define VAR7(T, N, MAP, FLAG, A, B, C, D, E, F, G) \
527 VAR6 (T, N, MAP, FLAG, A, B, C, D, E, F) \
528 VAR1 (T, N, MAP, FLAG, G)
529#define VAR8(T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
530 VAR7 (T, N, MAP, FLAG, A, B, C, D, E, F, G) \
531 VAR1 (T, N, MAP, FLAG, H)
532#define VAR9(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
533 VAR8 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
534 VAR1 (T, N, MAP, FLAG, I)
535#define VAR10(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
536 VAR9 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
537 VAR1 (T, N, MAP, FLAG, J)
538#define VAR11(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
539 VAR10 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
540 VAR1 (T, N, MAP, FLAG, K)
541#define VAR12(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
542 VAR11 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
543 VAR1 (T, N, MAP, FLAG, L)
544#define VAR13(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
545 VAR12 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
546 VAR1 (T, N, MAP, FLAG, M)
547#define VAR14(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
548 VAR13 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
549 VAR1 (T, X, MAP, FLAG, N)
550#define VAR15(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
551 VAR14 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
552 VAR1 (T, X, MAP, FLAG, O)
553#define VAR16(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
554 VAR15 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
555 VAR1 (T, X, MAP, FLAG, P)
342be7f7 556
f421c516 557#include "aarch64-builtin-iterators.h"
43e9d192 558
a4dae58a
KT
559/* The builtins below should be expanded through the standard optabs
560 CODE_FOR_[u]avg<mode>3_[floor,ceil]. However the mapping scheme in
561 aarch64-simd-builtins.def does not easily allow us to have a pre-mode
562 ("uavg") and post-mode string ("_ceil") in the CODE_FOR_* construction.
563 So the builtins use a name that is natural for AArch64 instructions
564 e.g. "aarch64_srhadd<mode>" and we re-map these to the optab-related
565 CODE_FOR_ here. */
566#undef VAR1
567#define VAR1(F,T1,T2,I,M) \
568constexpr insn_code CODE_FOR_aarch64_##F##M = CODE_FOR_##T1##M##3##T2;
569
570BUILTIN_VDQ_BHSI (srhadd, avg, _ceil, 0)
571BUILTIN_VDQ_BHSI (urhadd, uavg, _ceil, 0)
572BUILTIN_VDQ_BHSI (shadd, avg, _floor, 0)
573BUILTIN_VDQ_BHSI (uhadd, uavg, _floor, 0)
574
575#undef VAR1
576#define VAR1(T, N, MAP, FLAG, A) \
577 {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T, FLAG_##FLAG},
578
43e9d192 579static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
342be7f7
JG
580#include "aarch64-simd-builtins.def"
581};
582
5d357f26
KT
583/* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
584#define AARCH64_CRC32_BUILTINS \
585 CRC32_BUILTIN (crc32b, QI) \
586 CRC32_BUILTIN (crc32h, HI) \
587 CRC32_BUILTIN (crc32w, SI) \
588 CRC32_BUILTIN (crc32x, DI) \
589 CRC32_BUILTIN (crc32cb, QI) \
590 CRC32_BUILTIN (crc32ch, HI) \
591 CRC32_BUILTIN (crc32cw, SI) \
592 CRC32_BUILTIN (crc32cx, DI)
593
9d63f43b
TC
594/* The next 8 FCMLA instrinsics require some special handling compared the
595 normal simd intrinsics. */
596#define AARCH64_SIMD_FCMLA_LANEQ_BUILTINS \
597 FCMLA_LANEQ_BUILTIN (0, v2sf, fcmla, V2SF, false) \
598 FCMLA_LANEQ_BUILTIN (90, v2sf, fcmla, V2SF, false) \
599 FCMLA_LANEQ_BUILTIN (180, v2sf, fcmla, V2SF, false) \
600 FCMLA_LANEQ_BUILTIN (270, v2sf, fcmla, V2SF, false) \
601 FCMLA_LANEQ_BUILTIN (0, v4hf, fcmla_laneq, V4HF, true) \
602 FCMLA_LANEQ_BUILTIN (90, v4hf, fcmla_laneq, V4HF, true) \
603 FCMLA_LANEQ_BUILTIN (180, v4hf, fcmla_laneq, V4HF, true) \
604 FCMLA_LANEQ_BUILTIN (270, v4hf, fcmla_laneq, V4HF, true) \
605
c906efc7
AC
606
607/* vreinterpret intrinsics are defined for any pair of element types.
608 { _bf16 } { _bf16 }
609 { _f16 _f32 _f64 } { _f16 _f32 _f64 }
610 { _s8 _s16 _s32 _s64 } x { _s8 _s16 _s32 _s64 }
611 { _u8 _u16 _u32 _u64 } { _u8 _u16 _u32 _u64 }
612 { _p8 _p16 _p64 } { _p8 _p16 _p64 }. */
613#define VREINTERPRET_BUILTIN2(A, B) \
614 VREINTERPRET_BUILTIN (A, B, d)
615
616#define VREINTERPRET_BUILTINS1(A) \
617 VREINTERPRET_BUILTIN2 (A, bf16) \
618 VREINTERPRET_BUILTIN2 (A, f16) \
619 VREINTERPRET_BUILTIN2 (A, f32) \
620 VREINTERPRET_BUILTIN2 (A, f64) \
621 VREINTERPRET_BUILTIN2 (A, s8) \
622 VREINTERPRET_BUILTIN2 (A, s16) \
623 VREINTERPRET_BUILTIN2 (A, s32) \
624 VREINTERPRET_BUILTIN2 (A, s64) \
625 VREINTERPRET_BUILTIN2 (A, u8) \
626 VREINTERPRET_BUILTIN2 (A, u16) \
627 VREINTERPRET_BUILTIN2 (A, u32) \
628 VREINTERPRET_BUILTIN2 (A, u64) \
629 VREINTERPRET_BUILTIN2 (A, p8) \
630 VREINTERPRET_BUILTIN2 (A, p16) \
631 VREINTERPRET_BUILTIN2 (A, p64)
632
633#define VREINTERPRET_BUILTINS \
634 VREINTERPRET_BUILTINS1 (bf16) \
635 VREINTERPRET_BUILTINS1 (f16) \
636 VREINTERPRET_BUILTINS1 (f32) \
637 VREINTERPRET_BUILTINS1 (f64) \
638 VREINTERPRET_BUILTINS1 (s8) \
639 VREINTERPRET_BUILTINS1 (s16) \
640 VREINTERPRET_BUILTINS1 (s32) \
641 VREINTERPRET_BUILTINS1 (s64) \
642 VREINTERPRET_BUILTINS1 (u8) \
643 VREINTERPRET_BUILTINS1 (u16) \
644 VREINTERPRET_BUILTINS1 (u32) \
645 VREINTERPRET_BUILTINS1 (u64) \
646 VREINTERPRET_BUILTINS1 (p8) \
647 VREINTERPRET_BUILTINS1 (p16) \
648 VREINTERPRET_BUILTINS1 (p64)
649
650/* vreinterpretq intrinsics are additionally defined for p128.
651 { _bf16 } { _bf16 }
652 { _f16 _f32 _f64 } { _f16 _f32 _f64 }
653 { _s8 _s16 _s32 _s64 } x { _s8 _s16 _s32 _s64 }
654 { _u8 _u16 _u32 _u64 } { _u8 _u16 _u32 _u64 }
655 { _p8 _p16 _p64 _p128 } { _p8 _p16 _p64 _p128 }. */
656#define VREINTERPRETQ_BUILTIN2(A, B) \
657 VREINTERPRET_BUILTIN (A, B, q)
658
659#define VREINTERPRETQ_BUILTINS1(A) \
660 VREINTERPRETQ_BUILTIN2 (A, bf16) \
661 VREINTERPRETQ_BUILTIN2 (A, f16) \
662 VREINTERPRETQ_BUILTIN2 (A, f32) \
663 VREINTERPRETQ_BUILTIN2 (A, f64) \
664 VREINTERPRETQ_BUILTIN2 (A, s8) \
665 VREINTERPRETQ_BUILTIN2 (A, s16) \
666 VREINTERPRETQ_BUILTIN2 (A, s32) \
667 VREINTERPRETQ_BUILTIN2 (A, s64) \
668 VREINTERPRETQ_BUILTIN2 (A, u8) \
669 VREINTERPRETQ_BUILTIN2 (A, u16) \
670 VREINTERPRETQ_BUILTIN2 (A, u32) \
671 VREINTERPRETQ_BUILTIN2 (A, u64) \
672 VREINTERPRETQ_BUILTIN2 (A, p8) \
673 VREINTERPRETQ_BUILTIN2 (A, p16) \
674 VREINTERPRETQ_BUILTIN2 (A, p64) \
675 VREINTERPRETQ_BUILTIN2 (A, p128)
676
677#define VREINTERPRETQ_BUILTINS \
678 VREINTERPRETQ_BUILTINS1 (bf16) \
679 VREINTERPRETQ_BUILTINS1 (f16) \
680 VREINTERPRETQ_BUILTINS1 (f32) \
681 VREINTERPRETQ_BUILTINS1 (f64) \
682 VREINTERPRETQ_BUILTINS1 (s8) \
683 VREINTERPRETQ_BUILTINS1 (s16) \
684 VREINTERPRETQ_BUILTINS1 (s32) \
685 VREINTERPRETQ_BUILTINS1 (s64) \
686 VREINTERPRETQ_BUILTINS1 (u8) \
687 VREINTERPRETQ_BUILTINS1 (u16) \
688 VREINTERPRETQ_BUILTINS1 (u32) \
689 VREINTERPRETQ_BUILTINS1 (u64) \
690 VREINTERPRETQ_BUILTINS1 (p8) \
691 VREINTERPRETQ_BUILTINS1 (p16) \
692 VREINTERPRETQ_BUILTINS1 (p64) \
693 VREINTERPRETQ_BUILTINS1 (p128)
694
695#define AARCH64_SIMD_VREINTERPRET_BUILTINS \
696 VREINTERPRET_BUILTINS \
697 VREINTERPRETQ_BUILTINS
698
5d357f26
KT
699typedef struct
700{
701 const char *name;
ef4bddc2 702 machine_mode mode;
5d357f26
KT
703 const enum insn_code icode;
704 unsigned int fcode;
705} aarch64_crc_builtin_datum;
706
9d63f43b
TC
707/* Hold information about how to expand the FCMLA_LANEQ builtins. */
708typedef struct
709{
710 const char *name;
711 machine_mode mode;
712 const enum insn_code icode;
713 unsigned int fcode;
714 bool lane;
715} aarch64_fcmla_laneq_builtin_datum;
716
c906efc7
AC
717/* Hold information about how to declare SIMD intrinsics. */
718typedef struct
719{
720 const char *name;
721 unsigned int fcode;
722 unsigned int op_count;
723 machine_mode op_modes[SIMD_MAX_BUILTIN_ARGS];
724 enum aarch64_type_qualifiers qualifiers[SIMD_MAX_BUILTIN_ARGS];
725 unsigned int flags;
726 bool skip;
727} aarch64_simd_intrinsic_datum;
728
5d357f26
KT
729#define CRC32_BUILTIN(N, M) \
730 AARCH64_BUILTIN_##N,
731
9d63f43b
TC
732#define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
733 AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M,
734
c906efc7
AC
735#define VREINTERPRET_BUILTIN(A, B, L) \
736 AARCH64_SIMD_BUILTIN_VREINTERPRET##L##_##A##_##B,
737
342be7f7 738#undef VAR1
bf592b2f 739#define VAR1(T, N, MAP, FLAG, A) \
e993fea1 740 AARCH64_SIMD_BUILTIN_##T##_##N##A,
342be7f7
JG
741
742enum aarch64_builtins
743{
744 AARCH64_BUILTIN_MIN,
aa87aced
KV
745
746 AARCH64_BUILTIN_GET_FPCR,
747 AARCH64_BUILTIN_SET_FPCR,
748 AARCH64_BUILTIN_GET_FPSR,
749 AARCH64_BUILTIN_SET_FPSR,
750
0d7e5fa6
AC
751 AARCH64_BUILTIN_GET_FPCR64,
752 AARCH64_BUILTIN_SET_FPCR64,
753 AARCH64_BUILTIN_GET_FPSR64,
754 AARCH64_BUILTIN_SET_FPSR64,
755
a6fc00da
BH
756 AARCH64_BUILTIN_RSQRT_DF,
757 AARCH64_BUILTIN_RSQRT_SF,
758 AARCH64_BUILTIN_RSQRT_V2DF,
759 AARCH64_BUILTIN_RSQRT_V2SF,
760 AARCH64_BUILTIN_RSQRT_V4SF,
342be7f7 761 AARCH64_SIMD_BUILTIN_BASE,
661fce82 762 AARCH64_SIMD_BUILTIN_LANE_CHECK,
342be7f7 763#include "aarch64-simd-builtins.def"
661fce82
AL
764 /* The first enum element which is based on an insn_data pattern. */
765 AARCH64_SIMD_PATTERN_START = AARCH64_SIMD_BUILTIN_LANE_CHECK + 1,
766 AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_PATTERN_START
767 + ARRAY_SIZE (aarch64_simd_builtin_data) - 1,
5d357f26
KT
768 AARCH64_CRC32_BUILTIN_BASE,
769 AARCH64_CRC32_BUILTINS
770 AARCH64_CRC32_BUILTIN_MAX,
c906efc7
AC
771 /* SIMD intrinsic builtins. */
772 AARCH64_SIMD_VREINTERPRET_BUILTINS
312492bd
JW
773 /* ARMv8.3-A Pointer Authentication Builtins. */
774 AARCH64_PAUTH_BUILTIN_AUTIA1716,
775 AARCH64_PAUTH_BUILTIN_PACIA1716,
8fc16d72
ST
776 AARCH64_PAUTH_BUILTIN_AUTIB1716,
777 AARCH64_PAUTH_BUILTIN_PACIB1716,
312492bd 778 AARCH64_PAUTH_BUILTIN_XPACLRI,
9d63f43b
TC
779 /* Special cased Armv8.3-A Complex FMA by Lane quad Builtins. */
780 AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE,
781 AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
e1d5d19e
KT
782 /* Builtin for Arm8.3-a Javascript conversion instruction. */
783 AARCH64_JSCVT,
89626179
SD
784 /* TME builtins. */
785 AARCH64_TME_BUILTIN_TSTART,
786 AARCH64_TME_BUILTIN_TCOMMIT,
787 AARCH64_TME_BUILTIN_TTEST,
788 AARCH64_TME_BUILTIN_TCANCEL,
c5dc215d
KT
789 /* Armv8.5-a RNG instruction builtins. */
790 AARCH64_BUILTIN_RNG_RNDR,
791 AARCH64_BUILTIN_RNG_RNDRRS,
ef01e6bb
DZ
792 /* MEMTAG builtins. */
793 AARCH64_MEMTAG_BUILTIN_START,
794 AARCH64_MEMTAG_BUILTIN_IRG,
795 AARCH64_MEMTAG_BUILTIN_GMI,
796 AARCH64_MEMTAG_BUILTIN_SUBP,
797 AARCH64_MEMTAG_BUILTIN_INC_TAG,
798 AARCH64_MEMTAG_BUILTIN_SET_TAG,
799 AARCH64_MEMTAG_BUILTIN_GET_TAG,
800 AARCH64_MEMTAG_BUILTIN_END,
fdcddba8
PW
801 /* LS64 builtins. */
802 AARCH64_LS64_BUILTIN_LD64B,
803 AARCH64_LS64_BUILTIN_ST64B,
804 AARCH64_LS64_BUILTIN_ST64BV,
805 AARCH64_LS64_BUILTIN_ST64BV0,
eb966d39
ASDV
806 AARCH64_REV16,
807 AARCH64_REV16L,
808 AARCH64_REV16LL,
809 AARCH64_RBIT,
810 AARCH64_RBITL,
811 AARCH64_RBITLL,
fc42900d
VDN
812 /* System register builtins. */
813 AARCH64_RSR,
814 AARCH64_RSRP,
815 AARCH64_RSR64,
816 AARCH64_RSRF,
817 AARCH64_RSRF64,
88157c88 818 AARCH64_RSR128,
fc42900d
VDN
819 AARCH64_WSR,
820 AARCH64_WSRP,
821 AARCH64_WSR64,
822 AARCH64_WSRF,
823 AARCH64_WSRF64,
88157c88 824 AARCH64_WSR128,
342be7f7 825 AARCH64_BUILTIN_MAX
43e9d192
IB
826};
827
5d357f26
KT
828#undef CRC32_BUILTIN
829#define CRC32_BUILTIN(N, M) \
0d4a1197 830 {"__builtin_aarch64_"#N, E_##M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
5d357f26
KT
831
832static aarch64_crc_builtin_datum aarch64_crc_builtin_data[] = {
833 AARCH64_CRC32_BUILTINS
834};
835
9d63f43b
TC
836
837#undef FCMLA_LANEQ_BUILTIN
838#define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
839 {"__builtin_aarch64_fcmla_laneq"#I#N, E_##M##mode, CODE_FOR_aarch64_##X##I##N, \
840 AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M, T},
841
842/* This structure contains how to manage the mapping form the builtin to the
843 instruction to generate in the backend and how to invoke the instruction. */
5eb9ac1e 844static aarch64_fcmla_laneq_builtin_datum aarch64_fcmla_lane_builtin_data[] = {
9d63f43b
TC
845 AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
846};
847
c906efc7
AC
848#undef VREINTERPRET_BUILTIN
849#define VREINTERPRET_BUILTIN(A, B, L) \
850 {"vreinterpret" SIMD_INTR_LENGTH_CHAR(L) "_" #A "_" #B, \
851 AARCH64_SIMD_BUILTIN_VREINTERPRET##L##_##A##_##B, \
852 2, \
853 { SIMD_INTR_MODE(A, L), SIMD_INTR_MODE(B, L) }, \
854 { SIMD_INTR_QUAL(A), SIMD_INTR_QUAL(B) }, \
855 FLAG_AUTO_FP, \
856 SIMD_INTR_MODE(A, L) == SIMD_INTR_MODE(B, L) \
857 && SIMD_INTR_QUAL(A) == SIMD_INTR_QUAL(B) \
858 },
859
860static const aarch64_simd_intrinsic_datum aarch64_simd_intrinsic_data[] = {
861 AARCH64_SIMD_VREINTERPRET_BUILTINS
862};
863
864
5d357f26
KT
865#undef CRC32_BUILTIN
866
119103ca
JG
867static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX];
868
43e9d192
IB
869#define NUM_DREG_TYPES 6
870#define NUM_QREG_TYPES 6
871
f9d53c27
TB
872/* Internal scalar builtin types. These types are used to support
873 neon intrinsic builtins. They are _not_ user-visible types. Therefore
874 the mangling for these types are implementation defined. */
875const char *aarch64_scalar_builtin_types[] = {
876 "__builtin_aarch64_simd_qi",
877 "__builtin_aarch64_simd_hi",
878 "__builtin_aarch64_simd_si",
7c369485 879 "__builtin_aarch64_simd_hf",
f9d53c27
TB
880 "__builtin_aarch64_simd_sf",
881 "__builtin_aarch64_simd_di",
882 "__builtin_aarch64_simd_df",
883 "__builtin_aarch64_simd_poly8",
884 "__builtin_aarch64_simd_poly16",
885 "__builtin_aarch64_simd_poly64",
886 "__builtin_aarch64_simd_poly128",
887 "__builtin_aarch64_simd_ti",
888 "__builtin_aarch64_simd_uqi",
889 "__builtin_aarch64_simd_uhi",
890 "__builtin_aarch64_simd_usi",
891 "__builtin_aarch64_simd_udi",
892 "__builtin_aarch64_simd_ei",
893 "__builtin_aarch64_simd_oi",
894 "__builtin_aarch64_simd_ci",
895 "__builtin_aarch64_simd_xi",
e603cd43 896 "__builtin_aarch64_simd_bf",
f9d53c27
TB
897 NULL
898};
b5828b4b 899
f9d53c27
TB
900#define ENTRY(E, M, Q, G) E,
901enum aarch64_simd_type
902{
903#include "aarch64-simd-builtin-types.def"
904 ARM_NEON_H_TYPES_LAST
905};
906#undef ENTRY
b5828b4b 907
98f1dd02 908struct GTY(()) aarch64_simd_type_info
b5828b4b 909{
f9d53c27
TB
910 enum aarch64_simd_type type;
911
912 /* Internal type name. */
913 const char *name;
914
915 /* Internal type name(mangled). The mangled names conform to the
916 AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
917 Appendix A). To qualify for emission with the mangled names defined in
918 that document, a vector type must not only be of the correct mode but also
919 be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
920 types are registered by aarch64_init_simd_builtin_types (). In other
921 words, vector types defined in other ways e.g. via vector_size attribute
922 will get default mangled names. */
923 const char *mangle;
924
925 /* Internal type. */
926 tree itype;
927
928 /* Element type. */
b5828b4b
JG
929 tree eltype;
930
f9d53c27
TB
931 /* Machine mode the internal type maps to. */
932 enum machine_mode mode;
b5828b4b 933
f9d53c27
TB
934 /* Qualifiers. */
935 enum aarch64_type_qualifiers q;
936};
937
938#define ENTRY(E, M, Q, G) \
0d4a1197 939 {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, E_##M##mode, qualifier_##Q},
98f1dd02 940static GTY(()) struct aarch64_simd_type_info aarch64_simd_types [] = {
f9d53c27
TB
941#include "aarch64-simd-builtin-types.def"
942};
943#undef ENTRY
944
14814e20 945static machine_mode aarch64_simd_tuple_modes[ARM_NEON_H_TYPES_LAST][3];
66f206b8
JW
946static GTY(()) tree aarch64_simd_tuple_types[ARM_NEON_H_TYPES_LAST][3];
947
98f1dd02
AP
948static GTY(()) tree aarch64_simd_intOI_type_node = NULL_TREE;
949static GTY(()) tree aarch64_simd_intCI_type_node = NULL_TREE;
950static GTY(()) tree aarch64_simd_intXI_type_node = NULL_TREE;
f9d53c27 951
1b62ed4f
JG
952/* The user-visible __fp16 type, and a pointer to that type. Used
953 across the back-end. */
954tree aarch64_fp16_type_node = NULL_TREE;
955tree aarch64_fp16_ptr_type_node = NULL_TREE;
956
abbe1ed2 957/* Back-end node type for brain float (bfloat) types. */
abbe1ed2
SMW
958tree aarch64_bf16_ptr_type_node = NULL_TREE;
959
6d4d616a 960/* Wrapper around add_builtin_function. NAME is the name of the built-in
072a8b8f 961 function, TYPE is the function type, CODE is the function subcode
962 (relative to AARCH64_BUILTIN_GENERAL), and ATTRS is the function
963 attributes. */
6d4d616a 964static tree
072a8b8f 965aarch64_general_add_builtin (const char *name, tree type, unsigned int code,
966 tree attrs = NULL_TREE)
6d4d616a
RS
967{
968 code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
969 return add_builtin_function (name, type, code, BUILT_IN_MD,
072a8b8f 970 NULL, attrs);
6d4d616a
RS
971}
972
9963029a
AC
973static tree
974aarch64_general_simulate_builtin (const char *name, tree fntype,
975 unsigned int code,
976 tree attrs = NULL_TREE)
977{
978 code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
979 return simulate_builtin_function_decl (input_location, name, fntype,
980 code, NULL, attrs);
981}
982
f9d53c27
TB
983static const char *
984aarch64_mangle_builtin_scalar_type (const_tree type)
985{
986 int i = 0;
987
988 while (aarch64_scalar_builtin_types[i] != NULL)
b5828b4b 989 {
f9d53c27
TB
990 const char *name = aarch64_scalar_builtin_types[i];
991
992 if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
993 && DECL_NAME (TYPE_NAME (type))
994 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), name))
995 return aarch64_scalar_builtin_types[i];
996 i++;
997 }
998 return NULL;
b5828b4b
JG
999}
1000
f9d53c27
TB
1001static const char *
1002aarch64_mangle_builtin_vector_type (const_tree type)
b5828b4b 1003{
31427b97
RS
1004 tree attrs = TYPE_ATTRIBUTES (type);
1005 if (tree attr = lookup_attribute ("Advanced SIMD type", attrs))
1006 {
1007 tree mangled_name = TREE_VALUE (TREE_VALUE (attr));
1008 return IDENTIFIER_POINTER (mangled_name);
1009 }
f9d53c27
TB
1010
1011 return NULL;
6db1ec94
JG
1012}
1013
f9d53c27 1014const char *
6d4d616a 1015aarch64_general_mangle_builtin_type (const_tree type)
6db1ec94 1016{
f9d53c27
TB
1017 const char *mangle;
1018 /* Walk through all the AArch64 builtins types tables to filter out the
1019 incoming type. */
1020 if ((mangle = aarch64_mangle_builtin_vector_type (type))
1021 || (mangle = aarch64_mangle_builtin_scalar_type (type)))
1022 return mangle;
1023
1024 return NULL;
6db1ec94
JG
1025}
1026
f023cc54 1027/* Helper function for aarch64_simd_builtin_type. */
f9d53c27 1028static tree
f023cc54
AC
1029aarch64_int_or_fp_type (machine_mode mode,
1030 enum aarch64_type_qualifiers qualifiers)
6db1ec94 1031{
f023cc54
AC
1032#define QUAL_TYPE(M) ((qualifiers & qualifier_unsigned) \
1033 ? unsigned_int##M##_type_node : int##M##_type_node);
f9d53c27
TB
1034 switch (mode)
1035 {
4e10a5a7 1036 case E_QImode:
f9d53c27 1037 return QUAL_TYPE (QI);
4e10a5a7 1038 case E_HImode:
f9d53c27 1039 return QUAL_TYPE (HI);
4e10a5a7 1040 case E_SImode:
f9d53c27 1041 return QUAL_TYPE (SI);
4e10a5a7 1042 case E_DImode:
f9d53c27 1043 return QUAL_TYPE (DI);
4e10a5a7 1044 case E_TImode:
f9d53c27 1045 return QUAL_TYPE (TI);
4e10a5a7 1046 case E_OImode:
f9d53c27 1047 return aarch64_simd_intOI_type_node;
4e10a5a7 1048 case E_CImode:
f9d53c27 1049 return aarch64_simd_intCI_type_node;
4e10a5a7 1050 case E_XImode:
f9d53c27 1051 return aarch64_simd_intXI_type_node;
4e10a5a7 1052 case E_HFmode:
71a11456 1053 return aarch64_fp16_type_node;
4e10a5a7 1054 case E_SFmode:
f9d53c27 1055 return float_type_node;
4e10a5a7 1056 case E_DFmode:
f9d53c27 1057 return double_type_node;
abbe1ed2 1058 case E_BFmode:
13071c3c 1059 return bfloat16_type_node;
f9d53c27
TB
1060 default:
1061 gcc_unreachable ();
1062 }
1063#undef QUAL_TYPE
6db1ec94
JG
1064}
1065
f023cc54 1066/* Helper function for aarch64_simd_builtin_type. */
f9d53c27 1067static tree
f023cc54
AC
1068aarch64_lookup_simd_type_in_table (machine_mode mode,
1069 enum aarch64_type_qualifiers qualifiers)
6db1ec94 1070{
f9d53c27 1071 int i;
ca32b29e 1072 int nelts = ARRAY_SIZE (aarch64_simd_types);
f023cc54 1073 int q = qualifiers & (qualifier_poly | qualifier_unsigned);
f9d53c27
TB
1074
1075 for (i = 0; i < nelts; i++)
66f206b8
JW
1076 {
1077 if (aarch64_simd_types[i].mode == mode
1078 && aarch64_simd_types[i].q == q)
1079 return aarch64_simd_types[i].itype;
1080 if (aarch64_simd_tuple_types[i][0] != NULL_TREE)
1081 for (int j = 0; j < 3; j++)
14814e20 1082 if (aarch64_simd_tuple_modes[i][j] == mode
66f206b8
JW
1083 && aarch64_simd_types[i].q == q)
1084 return aarch64_simd_tuple_types[i][j];
1085 }
f9d53c27
TB
1086
1087 return NULL_TREE;
b5828b4b
JG
1088}
1089
f023cc54 1090/* Return a type for an operand with specified mode and qualifiers. */
f9d53c27 1091static tree
b8506a8a 1092aarch64_simd_builtin_type (machine_mode mode,
f023cc54 1093 enum aarch64_type_qualifiers qualifiers)
f9d53c27 1094{
f023cc54
AC
1095 tree type = NULL_TREE;
1096
1097 /* For pointers, we want a pointer to the basic type of the vector. */
1098 if ((qualifiers & qualifier_pointer) && VECTOR_MODE_P (mode))
1099 mode = GET_MODE_INNER (mode);
1100
1101 /* Non-poly scalar modes map to standard types not in the table. */
1102 if ((qualifiers & qualifier_poly) || VECTOR_MODE_P (mode))
1103 type = aarch64_lookup_simd_type_in_table (mode, qualifiers);
f9d53c27 1104 else
f023cc54
AC
1105 type = aarch64_int_or_fp_type (mode, qualifiers);
1106
1107 gcc_assert (type != NULL_TREE);
1108
1109 /* Add qualifiers. */
1110 if (qualifiers & qualifier_const)
1111 type = build_qualified_type (type, TYPE_QUAL_CONST);
1112 if (qualifiers & qualifier_pointer)
1113 type = build_pointer_type (type);
1114
1115 return type;
f9d53c27
TB
1116}
1117
af55e82d 1118static void
f9d53c27 1119aarch64_init_simd_builtin_types (void)
43e9d192 1120{
f9d53c27 1121 int i;
ca32b29e 1122 int nelts = ARRAY_SIZE (aarch64_simd_types);
f9d53c27
TB
1123 tree tdecl;
1124
1125 /* Init all the element types built by the front-end. */
1126 aarch64_simd_types[Int8x8_t].eltype = intQI_type_node;
1127 aarch64_simd_types[Int8x16_t].eltype = intQI_type_node;
1128 aarch64_simd_types[Int16x4_t].eltype = intHI_type_node;
1129 aarch64_simd_types[Int16x8_t].eltype = intHI_type_node;
1130 aarch64_simd_types[Int32x2_t].eltype = intSI_type_node;
1131 aarch64_simd_types[Int32x4_t].eltype = intSI_type_node;
1132 aarch64_simd_types[Int64x1_t].eltype = intDI_type_node;
1133 aarch64_simd_types[Int64x2_t].eltype = intDI_type_node;
1134 aarch64_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node;
1135 aarch64_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node;
1136 aarch64_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node;
1137 aarch64_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node;
1138 aarch64_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node;
1139 aarch64_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
1140 aarch64_simd_types[Uint64x1_t].eltype = unsigned_intDI_type_node;
1141 aarch64_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
1142
1143 /* Poly types are a world of their own. */
1144 aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
1145 build_distinct_type_copy (unsigned_intQI_type_node);
bcee52c4
MS
1146 /* Prevent front-ends from transforming Poly8_t arrays into string
1147 literals. */
1148 TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
1149
f9d53c27
TB
1150 aarch64_simd_types[Poly16_t].eltype = aarch64_simd_types[Poly16_t].itype =
1151 build_distinct_type_copy (unsigned_intHI_type_node);
1152 aarch64_simd_types[Poly64_t].eltype = aarch64_simd_types[Poly64_t].itype =
1153 build_distinct_type_copy (unsigned_intDI_type_node);
1154 aarch64_simd_types[Poly128_t].eltype = aarch64_simd_types[Poly128_t].itype =
1155 build_distinct_type_copy (unsigned_intTI_type_node);
1156 /* Init poly vector element types with scalar poly types. */
1157 aarch64_simd_types[Poly8x8_t].eltype = aarch64_simd_types[Poly8_t].itype;
1158 aarch64_simd_types[Poly8x16_t].eltype = aarch64_simd_types[Poly8_t].itype;
1159 aarch64_simd_types[Poly16x4_t].eltype = aarch64_simd_types[Poly16_t].itype;
1160 aarch64_simd_types[Poly16x8_t].eltype = aarch64_simd_types[Poly16_t].itype;
1161 aarch64_simd_types[Poly64x1_t].eltype = aarch64_simd_types[Poly64_t].itype;
1162 aarch64_simd_types[Poly64x2_t].eltype = aarch64_simd_types[Poly64_t].itype;
1163
1164 /* Continue with standard types. */
71a11456
AL
1165 aarch64_simd_types[Float16x4_t].eltype = aarch64_fp16_type_node;
1166 aarch64_simd_types[Float16x8_t].eltype = aarch64_fp16_type_node;
f9d53c27
TB
1167 aarch64_simd_types[Float32x2_t].eltype = float_type_node;
1168 aarch64_simd_types[Float32x4_t].eltype = float_type_node;
1169 aarch64_simd_types[Float64x1_t].eltype = double_type_node;
1170 aarch64_simd_types[Float64x2_t].eltype = double_type_node;
1171
abbe1ed2 1172 /* Init Bfloat vector types with underlying __bf16 type. */
13071c3c
JJ
1173 aarch64_simd_types[Bfloat16x4_t].eltype = bfloat16_type_node;
1174 aarch64_simd_types[Bfloat16x8_t].eltype = bfloat16_type_node;
abbe1ed2 1175
f9d53c27
TB
1176 for (i = 0; i < nelts; i++)
1177 {
1178 tree eltype = aarch64_simd_types[i].eltype;
b8506a8a 1179 machine_mode mode = aarch64_simd_types[i].mode;
f9d53c27
TB
1180
1181 if (aarch64_simd_types[i].itype == NULL)
b96824c4 1182 {
31427b97
RS
1183 tree type = build_vector_type (eltype, GET_MODE_NUNITS (mode));
1184 type = build_distinct_type_copy (type);
1185 SET_TYPE_STRUCTURAL_EQUALITY (type);
1186
1187 tree mangled_name = get_identifier (aarch64_simd_types[i].mangle);
1188 tree value = tree_cons (NULL_TREE, mangled_name, NULL_TREE);
1189 TYPE_ATTRIBUTES (type)
1190 = tree_cons (get_identifier ("Advanced SIMD type"), value,
1191 TYPE_ATTRIBUTES (type));
1192 aarch64_simd_types[i].itype = type;
b96824c4 1193 }
f9d53c27
TB
1194
1195 tdecl = add_builtin_type (aarch64_simd_types[i].name,
1196 aarch64_simd_types[i].itype);
1197 TYPE_NAME (aarch64_simd_types[i].itype) = tdecl;
f9d53c27 1198 }
43e9d192 1199
f9d53c27
TB
1200#define AARCH64_BUILD_SIGNED_TYPE(mode) \
1201 make_signed_type (GET_MODE_PRECISION (mode));
1202 aarch64_simd_intOI_type_node = AARCH64_BUILD_SIGNED_TYPE (OImode);
f9d53c27
TB
1203 aarch64_simd_intCI_type_node = AARCH64_BUILD_SIGNED_TYPE (CImode);
1204 aarch64_simd_intXI_type_node = AARCH64_BUILD_SIGNED_TYPE (XImode);
1205#undef AARCH64_BUILD_SIGNED_TYPE
1206
f9d53c27
TB
1207 tdecl = add_builtin_type
1208 ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node);
1209 TYPE_NAME (aarch64_simd_intOI_type_node) = tdecl;
1210 tdecl = add_builtin_type
1211 ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node);
1212 TYPE_NAME (aarch64_simd_intCI_type_node) = tdecl;
1213 tdecl = add_builtin_type
1214 ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node);
1215 TYPE_NAME (aarch64_simd_intXI_type_node) = tdecl;
1216}
1217
1218static void
1219aarch64_init_simd_builtin_scalar_types (void)
1220{
1221 /* Define typedefs for all the standard scalar types. */
1222 (*lang_hooks.types.register_builtin_type) (intQI_type_node,
43e9d192 1223 "__builtin_aarch64_simd_qi");
f9d53c27 1224 (*lang_hooks.types.register_builtin_type) (intHI_type_node,
43e9d192 1225 "__builtin_aarch64_simd_hi");
7c369485
AL
1226 (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node,
1227 "__builtin_aarch64_simd_hf");
f9d53c27 1228 (*lang_hooks.types.register_builtin_type) (intSI_type_node,
43e9d192 1229 "__builtin_aarch64_simd_si");
f9d53c27 1230 (*lang_hooks.types.register_builtin_type) (float_type_node,
43e9d192 1231 "__builtin_aarch64_simd_sf");
f9d53c27 1232 (*lang_hooks.types.register_builtin_type) (intDI_type_node,
43e9d192 1233 "__builtin_aarch64_simd_di");
f9d53c27 1234 (*lang_hooks.types.register_builtin_type) (double_type_node,
43e9d192 1235 "__builtin_aarch64_simd_df");
f9d53c27 1236 (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
43e9d192 1237 "__builtin_aarch64_simd_poly8");
f9d53c27 1238 (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
43e9d192 1239 "__builtin_aarch64_simd_poly16");
f9d53c27 1240 (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
7baa225d 1241 "__builtin_aarch64_simd_poly64");
f9d53c27 1242 (*lang_hooks.types.register_builtin_type) (unsigned_intTI_type_node,
7baa225d 1243 "__builtin_aarch64_simd_poly128");
f9d53c27 1244 (*lang_hooks.types.register_builtin_type) (intTI_type_node,
43e9d192 1245 "__builtin_aarch64_simd_ti");
13071c3c 1246 (*lang_hooks.types.register_builtin_type) (bfloat16_type_node,
e603cd43 1247 "__builtin_aarch64_simd_bf");
b5828b4b 1248 /* Unsigned integer types for various mode sizes. */
f9d53c27 1249 (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
b5828b4b 1250 "__builtin_aarch64_simd_uqi");
f9d53c27 1251 (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
b5828b4b 1252 "__builtin_aarch64_simd_uhi");
f9d53c27 1253 (*lang_hooks.types.register_builtin_type) (unsigned_intSI_type_node,
b5828b4b 1254 "__builtin_aarch64_simd_usi");
f9d53c27 1255 (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
b5828b4b 1256 "__builtin_aarch64_simd_udi");
f9d53c27
TB
1257}
1258
079c23cf
KT
1259/* Return a set of FLAG_* flags derived from FLAGS
1260 that describe what a function with result MODE could do,
072a8b8f 1261 taking the command-line flags into account. */
1262static unsigned int
079c23cf 1263aarch64_call_properties (unsigned int flags, machine_mode mode)
072a8b8f 1264{
079c23cf 1265 if (!(flags & FLAG_AUTO_FP) && FLOAT_MODE_P (mode))
35ffd4d1 1266 flags |= FLAG_FP;
072a8b8f 1267
1268 /* -fno-trapping-math means that we can assume any FP exceptions
1269 are not user-visible. */
1270 if (!flag_trapping_math)
1271 flags &= ~FLAG_RAISE_FP_EXCEPTIONS;
1272
1273 return flags;
1274}
1275
079c23cf
KT
1276/* Return true if calls to a function with flags F and mode MODE
1277 could modify some form of global state. */
072a8b8f 1278static bool
079c23cf 1279aarch64_modifies_global_state_p (unsigned int f, machine_mode mode)
072a8b8f 1280{
079c23cf 1281 unsigned int flags = aarch64_call_properties (f, mode);
072a8b8f 1282
1283 if (flags & FLAG_RAISE_FP_EXCEPTIONS)
1284 return true;
1285
1286 if (flags & FLAG_PREFETCH_MEMORY)
1287 return true;
1288
1289 return flags & FLAG_WRITE_MEMORY;
1290}
1291
079c23cf
KT
1292/* Return true if calls to a function with flags F and mode MODE
1293 could read some form of global state. */
072a8b8f 1294static bool
079c23cf 1295aarch64_reads_global_state_p (unsigned int f, machine_mode mode)
072a8b8f 1296{
079c23cf 1297 unsigned int flags = aarch64_call_properties (f, mode);
072a8b8f 1298
1299 if (flags & FLAG_READ_FPCR)
1300 return true;
1301
1302 return flags & FLAG_READ_MEMORY;
1303}
1304
079c23cf
KT
1305/* Return true if calls to a function with flags F and mode MODE
1306 could raise a signal. */
072a8b8f 1307static bool
079c23cf 1308aarch64_could_trap_p (unsigned int f, machine_mode mode)
072a8b8f 1309{
079c23cf 1310 unsigned int flags = aarch64_call_properties (f, mode);
072a8b8f 1311
1312 if (flags & FLAG_RAISE_FP_EXCEPTIONS)
1313 return true;
1314
1315 if (flags & (FLAG_READ_MEMORY | FLAG_WRITE_MEMORY))
1316 return true;
1317
1318 return false;
1319}
1320
1321/* Add attribute NAME to ATTRS. */
1322static tree
1323aarch64_add_attribute (const char *name, tree attrs)
1324{
1325 return tree_cons (get_identifier (name), NULL_TREE, attrs);
1326}
1327
079c23cf
KT
1328/* Return the appropriate attributes for a function that has
1329 flags F and mode MODE. */
072a8b8f 1330static tree
079c23cf 1331aarch64_get_attributes (unsigned int f, machine_mode mode)
072a8b8f 1332{
1333 tree attrs = NULL_TREE;
1334
079c23cf 1335 if (!aarch64_modifies_global_state_p (f, mode))
072a8b8f 1336 {
079c23cf 1337 if (aarch64_reads_global_state_p (f, mode))
072a8b8f 1338 attrs = aarch64_add_attribute ("pure", attrs);
1339 else
1340 attrs = aarch64_add_attribute ("const", attrs);
1341 }
1342
079c23cf 1343 if (!flag_non_call_exceptions || !aarch64_could_trap_p (f, mode))
072a8b8f 1344 attrs = aarch64_add_attribute ("nothrow", attrs);
1345
1346 return aarch64_add_attribute ("leaf", attrs);
1347}
1348
9d63f43b
TC
1349/* Due to the architecture not providing lane variant of the lane instructions
1350 for fcmla we can't use the standard simd builtin expansion code, but we
1351 still want the majority of the validation that would normally be done. */
1352
1353void
1354aarch64_init_fcmla_laneq_builtins (void)
1355{
1356 unsigned int i = 0;
1357
1358 for (i = 0; i < ARRAY_SIZE (aarch64_fcmla_lane_builtin_data); ++i)
1359 {
1360 aarch64_fcmla_laneq_builtin_datum* d
1361 = &aarch64_fcmla_lane_builtin_data[i];
f023cc54 1362 tree argtype = aarch64_simd_builtin_type (d->mode, qualifier_none);
9d63f43b 1363 machine_mode quadmode = GET_MODE_2XWIDER_MODE (d->mode).require ();
f023cc54 1364 tree quadtype = aarch64_simd_builtin_type (quadmode, qualifier_none);
9d63f43b 1365 tree lanetype
f023cc54 1366 = aarch64_simd_builtin_type (SImode, qualifier_lane_pair_index);
9d63f43b
TC
1367 tree ftype = build_function_type_list (argtype, argtype, argtype,
1368 quadtype, lanetype, NULL_TREE);
079c23cf
KT
1369 tree attrs = aarch64_get_attributes (FLAG_FP, d->mode);
1370 tree fndecl
1371 = aarch64_general_add_builtin (d->name, ftype, d->fcode, attrs);
9d63f43b
TC
1372
1373 aarch64_builtin_decls[d->fcode] = fndecl;
1374 }
1375}
1376
c906efc7
AC
1377void
1378aarch64_init_simd_intrinsics (void)
1379{
1380 unsigned int i = 0;
1381
1382 for (i = 0; i < ARRAY_SIZE (aarch64_simd_intrinsic_data); ++i)
1383 {
1384 auto d = &aarch64_simd_intrinsic_data[i];
1385
1386 if (d->skip)
1387 continue;
1388
1389 tree return_type = void_type_node;
1390 tree args = void_list_node;
1391
1392 for (int op_num = d->op_count - 1; op_num >= 0; op_num--)
1393 {
1394 machine_mode op_mode = d->op_modes[op_num];
1395 enum aarch64_type_qualifiers qualifiers = d->qualifiers[op_num];
1396
1397 tree eltype = aarch64_simd_builtin_type (op_mode, qualifiers);
1398
1399 if (op_num == 0)
1400 return_type = eltype;
1401 else
1402 args = tree_cons (NULL_TREE, eltype, args);
1403 }
1404
1405 tree ftype = build_function_type (return_type, args);
8b271f60 1406 tree attrs = aarch64_get_attributes (d->flags, d->op_modes[0]);
c906efc7
AC
1407 unsigned int code
1408 = (d->fcode << AARCH64_BUILTIN_SHIFT | AARCH64_BUILTIN_GENERAL);
1409 tree fndecl = simulate_builtin_function_decl (input_location, d->name,
1410 ftype, code, NULL, attrs);
1411 aarch64_builtin_decls[d->fcode] = fndecl;
1412 }
1413}
1414
e95a988a 1415void
8197ab94 1416aarch64_init_simd_builtin_functions (bool called_from_pragma)
f9d53c27 1417{
661fce82 1418 unsigned int i, fcode = AARCH64_SIMD_PATTERN_START;
f9d53c27 1419
8197ab94
JW
1420 if (!called_from_pragma)
1421 {
1422 tree lane_check_fpr = build_function_type_list (void_type_node,
1423 size_type_node,
1424 size_type_node,
1425 intSI_type_node,
1426 NULL);
1427 aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_LANE_CHECK]
1428 = aarch64_general_add_builtin ("__builtin_aarch64_im_lane_boundsi",
1429 lane_check_fpr,
1430 AARCH64_SIMD_BUILTIN_LANE_CHECK);
1431 }
661fce82 1432
342be7f7 1433 for (i = 0; i < ARRAY_SIZE (aarch64_simd_builtin_data); i++, fcode++)
43e9d192 1434 {
b5828b4b 1435 bool print_type_signature_p = false;
cae83731 1436 char type_signature[SIMD_MAX_BUILTIN_ARGS + 1] = { 0 };
43e9d192 1437 aarch64_simd_builtin_datum *d = &aarch64_simd_builtin_data[i];
342be7f7
JG
1438 char namebuf[60];
1439 tree ftype = NULL;
119103ca 1440 tree fndecl = NULL;
342be7f7 1441
342be7f7 1442 d->fcode = fcode;
43e9d192 1443
b5828b4b
JG
1444 /* We must track two variables here. op_num is
1445 the operand number as in the RTL pattern. This is
1446 required to access the mode (e.g. V4SF mode) of the
1447 argument, from which the base type can be derived.
1448 arg_num is an index in to the qualifiers data, which
1449 gives qualifiers to the type (e.g. const unsigned).
1450 The reason these two variables may differ by one is the
1451 void return type. While all return types take the 0th entry
1452 in the qualifiers array, there is no operand for them in the
1453 RTL pattern. */
1454 int op_num = insn_data[d->code].n_operands - 1;
1455 int arg_num = d->qualifiers[0] & qualifier_void
1456 ? op_num + 1
1457 : op_num;
1458 tree return_type = void_type_node, args = void_list_node;
1459 tree eltype;
1460
8197ab94
JW
1461 int struct_mode_args = 0;
1462 for (int j = op_num; j >= 0; j--)
1463 {
1464 machine_mode op_mode = insn_data[d->code].operand[j].mode;
1465 if (aarch64_advsimd_struct_mode_p (op_mode))
1466 struct_mode_args++;
1467 }
1468
1469 if ((called_from_pragma && struct_mode_args == 0)
1470 || (!called_from_pragma && struct_mode_args > 0))
1471 continue;
1472
b5828b4b
JG
1473 /* Build a function type directly from the insn_data for this
1474 builtin. The build_function_type () function takes care of
1475 removing duplicates for us. */
1476 for (; op_num >= 0; arg_num--, op_num--)
43e9d192 1477 {
ef4bddc2 1478 machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
b5828b4b 1479 enum aarch64_type_qualifiers qualifiers = d->qualifiers[arg_num];
43e9d192 1480
b5828b4b
JG
1481 if (qualifiers & qualifier_unsigned)
1482 {
9fd2074d 1483 type_signature[op_num] = 'u';
b5828b4b
JG
1484 print_type_signature_p = true;
1485 }
6db1ec94
JG
1486 else if (qualifiers & qualifier_poly)
1487 {
9fd2074d 1488 type_signature[op_num] = 'p';
6db1ec94
JG
1489 print_type_signature_p = true;
1490 }
b5828b4b 1491 else
9fd2074d 1492 type_signature[op_num] = 's';
b5828b4b 1493
b5828b4b
JG
1494 /* Some builtins have different user-facing types
1495 for certain arguments, encoded in d->mode. */
1496 if (qualifiers & qualifier_map_mode)
bc5e395d 1497 op_mode = d->mode;
b5828b4b 1498
f023cc54 1499 eltype = aarch64_simd_builtin_type (op_mode, qualifiers);
b5828b4b
JG
1500
1501 /* If we have reached arg_num == 0, we are at a non-void
1502 return type. Otherwise, we are still processing
1503 arguments. */
1504 if (arg_num == 0)
1505 return_type = eltype;
1506 else
1507 args = tree_cons (NULL_TREE, eltype, args);
1508 }
342be7f7 1509
b5828b4b 1510 ftype = build_function_type (return_type, args);
43e9d192 1511
342be7f7 1512 gcc_assert (ftype != NULL);
43e9d192 1513
b5828b4b 1514 if (print_type_signature_p)
bc5e395d
JG
1515 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s_%s",
1516 d->name, type_signature);
b5828b4b 1517 else
bc5e395d
JG
1518 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s",
1519 d->name);
43e9d192 1520
079c23cf 1521 tree attrs = aarch64_get_attributes (d->flags, d->mode);
072a8b8f 1522
66f206b8
JW
1523 if (called_from_pragma)
1524 {
1525 unsigned int raw_code
1526 = (fcode << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
1527 fndecl = simulate_builtin_function_decl (input_location, namebuf,
1528 ftype, raw_code, NULL,
1529 attrs);
1530 }
1531 else
1532 fndecl = aarch64_general_add_builtin (namebuf, ftype, fcode, attrs);
1533
119103ca 1534 aarch64_builtin_decls[fcode] = fndecl;
43e9d192 1535 }
8197ab94
JW
1536}
1537
1538/* Register the tuple type that contains NUM_VECTORS of the AdvSIMD type
1539 indexed by TYPE_INDEX. */
1540static void
1541register_tuple_type (unsigned int num_vectors, unsigned int type_index)
1542{
1543 aarch64_simd_type_info *type = &aarch64_simd_types[type_index];
1544
1545 /* Synthesize the name of the user-visible vector tuple type. */
1546 const char *vector_type_name = type->name;
1547 char tuple_type_name[sizeof ("bfloat16x4x2_t")];
1548 snprintf (tuple_type_name, sizeof (tuple_type_name), "%.*sx%d_t",
1549 (int) strlen (vector_type_name) - 4, vector_type_name + 2,
1550 num_vectors);
1551 tuple_type_name[0] = TOLOWER (tuple_type_name[0]);
1552
1553 tree vector_type = type->itype;
1554 tree array_type = build_array_type_nelts (vector_type, num_vectors);
66f206b8
JW
1555 if (type->mode == DImode)
1556 {
1557 if (num_vectors == 2)
1558 SET_TYPE_MODE (array_type, V2x1DImode);
1559 else if (num_vectors == 3)
1560 SET_TYPE_MODE (array_type, V3x1DImode);
1561 else if (num_vectors == 4)
1562 SET_TYPE_MODE (array_type, V4x1DImode);
1563 }
1564
8197ab94 1565 unsigned int alignment
14814e20
RS
1566 = known_eq (GET_MODE_SIZE (type->mode), 16) ? 128 : 64;
1567 machine_mode tuple_mode = TYPE_MODE_RAW (array_type);
1568 gcc_assert (VECTOR_MODE_P (tuple_mode)
1569 && TYPE_MODE (array_type) == tuple_mode
8197ab94
JW
1570 && TYPE_ALIGN (array_type) == alignment);
1571
1572 tree field = build_decl (input_location, FIELD_DECL,
1573 get_identifier ("val"), array_type);
1574
1575 tree t = lang_hooks.types.simulate_record_decl (input_location,
1576 tuple_type_name,
1577 make_array_slice (&field,
1578 1));
1579 gcc_assert (TYPE_MODE_RAW (t) == TYPE_MODE (t)
14814e20
RS
1580 && (flag_pack_struct
1581 || maximum_field_alignment
1582 || (TYPE_MODE_RAW (t) == tuple_mode
1583 && TYPE_ALIGN (t) == alignment)));
1584
1585 aarch64_simd_tuple_modes[type_index][num_vectors - 2] = tuple_mode;
1586 aarch64_simd_tuple_types[type_index][num_vectors - 2] = t;
8197ab94
JW
1587}
1588
1589static bool
1590aarch64_scalar_builtin_type_p (aarch64_simd_type t)
1591{
1592 return (t == Poly8_t || t == Poly16_t || t == Poly64_t || t == Poly128_t);
1593}
1594
14814e20
RS
1595/* Enable AARCH64_FL_* flags EXTRA_FLAGS on top of the base Advanced SIMD
1596 set. */
a1a9ce24 1597aarch64_simd_switcher::aarch64_simd_switcher (aarch64_feature_flags extra_flags)
2a269bda 1598 : m_old_asm_isa_flags (aarch64_asm_isa_flags),
14814e20
RS
1599 m_old_general_regs_only (TARGET_GENERAL_REGS_ONLY)
1600{
1601 /* Changing the ISA flags should be enough here. We shouldn't need to
1602 pay the compile-time cost of a full target switch. */
14814e20 1603 global_options.x_target_flags &= ~MASK_GENERAL_REGS_ONLY;
2a269bda 1604 aarch64_set_asm_isa_flags (AARCH64_FL_FP | AARCH64_FL_SIMD | extra_flags);
14814e20
RS
1605}
1606
1607aarch64_simd_switcher::~aarch64_simd_switcher ()
1608{
1609 if (m_old_general_regs_only)
1610 global_options.x_target_flags |= MASK_GENERAL_REGS_ONLY;
2a269bda 1611 aarch64_set_asm_isa_flags (m_old_asm_isa_flags);
14814e20
RS
1612}
1613
c906efc7
AC
1614/* Implement #pragma GCC aarch64 "arm_neon.h".
1615
1616 The types and functions defined here need to be available internally
1617 during LTO as well. */
8197ab94
JW
1618void
1619handle_arm_neon_h (void)
1620{
14814e20
RS
1621 aarch64_simd_switcher simd;
1622
8197ab94
JW
1623 /* Register the AdvSIMD vector tuple types. */
1624 for (unsigned int i = 0; i < ARM_NEON_H_TYPES_LAST; i++)
1625 for (unsigned int count = 2; count <= 4; ++count)
1626 if (!aarch64_scalar_builtin_type_p (aarch64_simd_types[i].type))
1627 register_tuple_type (count, i);
1628
1629 aarch64_init_simd_builtin_functions (true);
c906efc7 1630 aarch64_init_simd_intrinsics ();
8197ab94
JW
1631}
1632
d29ecf23 1633static void
8197ab94
JW
1634aarch64_init_simd_builtins (void)
1635{
8197ab94
JW
1636 aarch64_init_simd_builtin_types ();
1637
1638 /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
1639 Therefore we need to preserve the old __builtin scalar types. It can be
1640 removed once all the intrinsics become strongly typed using the qualifier
1641 system. */
1642 aarch64_init_simd_builtin_scalar_types ();
1643
1644 aarch64_init_simd_builtin_functions (false);
1645 if (in_lto_p)
1646 handle_arm_neon_h ();
280d970b 1647
8197ab94
JW
1648 /* Initialize the remaining fcmla_laneq intrinsics. */
1649 aarch64_init_fcmla_laneq_builtins ();
43e9d192
IB
1650}
1651
5d357f26
KT
1652static void
1653aarch64_init_crc32_builtins ()
1654{
f023cc54 1655 tree usi_type = aarch64_simd_builtin_type (SImode, qualifier_unsigned);
5d357f26
KT
1656 unsigned int i = 0;
1657
1658 for (i = 0; i < ARRAY_SIZE (aarch64_crc_builtin_data); ++i)
1659 {
1660 aarch64_crc_builtin_datum* d = &aarch64_crc_builtin_data[i];
f023cc54 1661 tree argtype = aarch64_simd_builtin_type (d->mode, qualifier_unsigned);
5d357f26 1662 tree ftype = build_function_type_list (usi_type, usi_type, argtype, NULL_TREE);
079c23cf
KT
1663 tree attrs = aarch64_get_attributes (FLAG_NONE, d->mode);
1664 tree fndecl
1665 = aarch64_general_add_builtin (d->name, ftype, d->fcode, attrs);
5d357f26
KT
1666
1667 aarch64_builtin_decls[d->fcode] = fndecl;
1668 }
1669}
1670
a6fc00da
BH
1671/* Add builtins for reciprocal square root. */
1672
1673void
1674aarch64_init_builtin_rsqrt (void)
1675{
1676 tree fndecl = NULL;
1677 tree ftype = NULL;
1678
1679 tree V2SF_type_node = build_vector_type (float_type_node, 2);
1680 tree V2DF_type_node = build_vector_type (double_type_node, 2);
1681 tree V4SF_type_node = build_vector_type (float_type_node, 4);
1682
1683 struct builtin_decls_data
1684 {
1685 tree type_node;
1686 const char *builtin_name;
1687 int function_code;
1688 };
1689
1690 builtin_decls_data bdda[] =
1691 {
1692 { double_type_node, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF },
1693 { float_type_node, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF },
1694 { V2DF_type_node, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF },
1695 { V2SF_type_node, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF },
1696 { V4SF_type_node, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF }
1697 };
1698
1699 builtin_decls_data *bdd = bdda;
ca32b29e 1700 builtin_decls_data *bdd_end = bdd + (ARRAY_SIZE (bdda));
a6fc00da
BH
1701
1702 for (; bdd < bdd_end; bdd++)
1703 {
1704 ftype = build_function_type_list (bdd->type_node, bdd->type_node, NULL_TREE);
079c23cf 1705 tree attrs = aarch64_get_attributes (FLAG_FP, TYPE_MODE (bdd->type_node));
6d4d616a 1706 fndecl = aarch64_general_add_builtin (bdd->builtin_name,
079c23cf 1707 ftype, bdd->function_code, attrs);
a6fc00da
BH
1708 aarch64_builtin_decls[bdd->function_code] = fndecl;
1709 }
1710}
1711
1b62ed4f
JG
1712/* Initialize the backend types that support the user-visible __fp16
1713 type, also initialize a pointer to that type, to be used when
1714 forming HFAs. */
1715
1716static void
1717aarch64_init_fp16_types (void)
1718{
1719 aarch64_fp16_type_node = make_node (REAL_TYPE);
1720 TYPE_PRECISION (aarch64_fp16_type_node) = 16;
1721 layout_type (aarch64_fp16_type_node);
1722
1723 (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node, "__fp16");
1724 aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
1725}
1726
abbe1ed2
SMW
1727/* Initialize the backend REAL_TYPE type supporting bfloat types. */
1728static void
1729aarch64_init_bf16_types (void)
1730{
13071c3c
JJ
1731 lang_hooks.types.register_builtin_type (bfloat16_type_node, "__bf16");
1732 aarch64_bf16_ptr_type_node = build_pointer_type (bfloat16_type_node);
abbe1ed2
SMW
1733}
1734
312492bd
JW
1735/* Pointer authentication builtins that will become NOP on legacy platform.
1736 Currently, these builtins are for internal use only (libgcc EH unwinder). */
1737
1738void
1739aarch64_init_pauth_hint_builtins (void)
1740{
1741 /* Pointer Authentication builtins. */
1742 tree ftype_pointer_auth
1743 = build_function_type_list (ptr_type_node, ptr_type_node,
1744 unsigned_intDI_type_node, NULL_TREE);
1745 tree ftype_pointer_strip
1746 = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
1747
1748 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
6d4d616a
RS
1749 = aarch64_general_add_builtin ("__builtin_aarch64_autia1716",
1750 ftype_pointer_auth,
1751 AARCH64_PAUTH_BUILTIN_AUTIA1716);
312492bd 1752 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIA1716]
6d4d616a
RS
1753 = aarch64_general_add_builtin ("__builtin_aarch64_pacia1716",
1754 ftype_pointer_auth,
1755 AARCH64_PAUTH_BUILTIN_PACIA1716);
8fc16d72 1756 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIB1716]
6d4d616a
RS
1757 = aarch64_general_add_builtin ("__builtin_aarch64_autib1716",
1758 ftype_pointer_auth,
1759 AARCH64_PAUTH_BUILTIN_AUTIB1716);
8fc16d72 1760 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIB1716]
6d4d616a
RS
1761 = aarch64_general_add_builtin ("__builtin_aarch64_pacib1716",
1762 ftype_pointer_auth,
1763 AARCH64_PAUTH_BUILTIN_PACIB1716);
312492bd 1764 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
6d4d616a
RS
1765 = aarch64_general_add_builtin ("__builtin_aarch64_xpaclri",
1766 ftype_pointer_strip,
1767 AARCH64_PAUTH_BUILTIN_XPACLRI);
312492bd
JW
1768}
1769
89626179
SD
1770/* Initialize the transactional memory extension (TME) builtins. */
1771static void
1772aarch64_init_tme_builtins (void)
1773{
1774 tree ftype_uint64_void
1775 = build_function_type_list (uint64_type_node, NULL);
1776 tree ftype_void_void
1777 = build_function_type_list (void_type_node, NULL);
1778 tree ftype_void_uint64
1779 = build_function_type_list (void_type_node, uint64_type_node, NULL);
1780
1781 aarch64_builtin_decls[AARCH64_TME_BUILTIN_TSTART]
6d4d616a
RS
1782 = aarch64_general_add_builtin ("__builtin_aarch64_tstart",
1783 ftype_uint64_void,
1784 AARCH64_TME_BUILTIN_TSTART);
89626179 1785 aarch64_builtin_decls[AARCH64_TME_BUILTIN_TTEST]
6d4d616a
RS
1786 = aarch64_general_add_builtin ("__builtin_aarch64_ttest",
1787 ftype_uint64_void,
1788 AARCH64_TME_BUILTIN_TTEST);
89626179 1789 aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCOMMIT]
6d4d616a
RS
1790 = aarch64_general_add_builtin ("__builtin_aarch64_tcommit",
1791 ftype_void_void,
1792 AARCH64_TME_BUILTIN_TCOMMIT);
89626179 1793 aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCANCEL]
6d4d616a
RS
1794 = aarch64_general_add_builtin ("__builtin_aarch64_tcancel",
1795 ftype_void_uint64,
1796 AARCH64_TME_BUILTIN_TCANCEL);
89626179
SD
1797}
1798
c5dc215d
KT
1799/* Add builtins for Random Number instructions. */
1800
1801static void
1802aarch64_init_rng_builtins (void)
1803{
1804 tree unsigned_ptr_type = build_pointer_type (unsigned_intDI_type_node);
1805 tree ftype
1806 = build_function_type_list (integer_type_node, unsigned_ptr_type, NULL);
1807 aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDR]
1808 = aarch64_general_add_builtin ("__builtin_aarch64_rndr", ftype,
1809 AARCH64_BUILTIN_RNG_RNDR);
1810 aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDRRS]
1811 = aarch64_general_add_builtin ("__builtin_aarch64_rndrrs", ftype,
1812 AARCH64_BUILTIN_RNG_RNDRRS);
1813}
1814
fc42900d
VDN
1815/* Add builtins for reading system register. */
1816static void
1817aarch64_init_rwsr_builtins (void)
1818{
1819 tree fntype = NULL;
1820 tree const_char_ptr_type
1821 = build_pointer_type (build_type_variant (char_type_node, true, false));
1822
1823#define AARCH64_INIT_RWSR_BUILTINS_DECL(F, N, T) \
1824 aarch64_builtin_decls[AARCH64_##F] \
1825 = aarch64_general_add_builtin ("__builtin_aarch64_"#N, T, AARCH64_##F);
1826
1827 fntype
1828 = build_function_type_list (uint32_type_node, const_char_ptr_type, NULL);
1829 AARCH64_INIT_RWSR_BUILTINS_DECL (RSR, rsr, fntype);
1830
1831 fntype
1832 = build_function_type_list (ptr_type_node, const_char_ptr_type, NULL);
1833 AARCH64_INIT_RWSR_BUILTINS_DECL (RSRP, rsrp, fntype);
1834
1835 fntype
1836 = build_function_type_list (uint64_type_node, const_char_ptr_type, NULL);
1837 AARCH64_INIT_RWSR_BUILTINS_DECL (RSR64, rsr64, fntype);
1838
1839 fntype
1840 = build_function_type_list (float_type_node, const_char_ptr_type, NULL);
1841 AARCH64_INIT_RWSR_BUILTINS_DECL (RSRF, rsrf, fntype);
1842
1843 fntype
1844 = build_function_type_list (double_type_node, const_char_ptr_type, NULL);
1845 AARCH64_INIT_RWSR_BUILTINS_DECL (RSRF64, rsrf64, fntype);
1846
88157c88
VDN
1847 fntype
1848 = build_function_type_list (uint128_type_node, const_char_ptr_type, NULL);
1849 AARCH64_INIT_RWSR_BUILTINS_DECL (RSR128, rsr128, fntype);
1850
fc42900d
VDN
1851 fntype
1852 = build_function_type_list (void_type_node, const_char_ptr_type,
1853 uint32_type_node, NULL);
1854
1855 AARCH64_INIT_RWSR_BUILTINS_DECL (WSR, wsr, fntype);
1856
1857 fntype
1858 = build_function_type_list (void_type_node, const_char_ptr_type,
1859 const_ptr_type_node, NULL);
1860 AARCH64_INIT_RWSR_BUILTINS_DECL (WSRP, wsrp, fntype);
1861
1862 fntype
1863 = build_function_type_list (void_type_node, const_char_ptr_type,
1864 uint64_type_node, NULL);
1865 AARCH64_INIT_RWSR_BUILTINS_DECL (WSR64, wsr64, fntype);
1866
1867 fntype
1868 = build_function_type_list (void_type_node, const_char_ptr_type,
1869 float_type_node, NULL);
1870 AARCH64_INIT_RWSR_BUILTINS_DECL (WSRF, wsrf, fntype);
1871
1872 fntype
1873 = build_function_type_list (void_type_node, const_char_ptr_type,
1874 double_type_node, NULL);
1875 AARCH64_INIT_RWSR_BUILTINS_DECL (WSRF64, wsrf64, fntype);
88157c88
VDN
1876
1877 fntype
1878 = build_function_type_list (void_type_node, const_char_ptr_type,
1879 uint128_type_node, NULL);
1880 AARCH64_INIT_RWSR_BUILTINS_DECL (WSR128, wsr128, fntype);
1881
fc42900d
VDN
1882}
1883
ef01e6bb
DZ
1884/* Initialize the memory tagging extension (MTE) builtins. */
1885struct
1886{
1887 tree ftype;
1888 enum insn_code icode;
1889} aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_END -
1890 AARCH64_MEMTAG_BUILTIN_START - 1];
1891
1892static void
1893aarch64_init_memtag_builtins (void)
1894{
1895 tree fntype = NULL;
1896
1897#define AARCH64_INIT_MEMTAG_BUILTINS_DECL(F, N, I, T) \
1898 aarch64_builtin_decls[AARCH64_MEMTAG_BUILTIN_##F] \
1899 = aarch64_general_add_builtin ("__builtin_aarch64_memtag_"#N, \
1900 T, AARCH64_MEMTAG_BUILTIN_##F); \
1901 aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_##F - \
1902 AARCH64_MEMTAG_BUILTIN_START - 1] = \
1903 {T, CODE_FOR_##I};
1904
1905 fntype = build_function_type_list (ptr_type_node, ptr_type_node,
1906 uint64_type_node, NULL);
1907 AARCH64_INIT_MEMTAG_BUILTINS_DECL (IRG, irg, irg, fntype);
1908
1909 fntype = build_function_type_list (uint64_type_node, ptr_type_node,
1910 uint64_type_node, NULL);
1911 AARCH64_INIT_MEMTAG_BUILTINS_DECL (GMI, gmi, gmi, fntype);
1912
1913 fntype = build_function_type_list (ptrdiff_type_node, ptr_type_node,
1914 ptr_type_node, NULL);
1915 AARCH64_INIT_MEMTAG_BUILTINS_DECL (SUBP, subp, subp, fntype);
1916
1917 fntype = build_function_type_list (ptr_type_node, ptr_type_node,
1918 unsigned_type_node, NULL);
1919 AARCH64_INIT_MEMTAG_BUILTINS_DECL (INC_TAG, inc_tag, addg, fntype);
1920
1921 fntype = build_function_type_list (void_type_node, ptr_type_node, NULL);
1922 AARCH64_INIT_MEMTAG_BUILTINS_DECL (SET_TAG, set_tag, stg, fntype);
1923
1924 fntype = build_function_type_list (ptr_type_node, ptr_type_node, NULL);
1925 AARCH64_INIT_MEMTAG_BUILTINS_DECL (GET_TAG, get_tag, ldg, fntype);
1926
1927#undef AARCH64_INIT_MEMTAG_BUILTINS_DECL
1928}
c5dc215d 1929
fdcddba8
PW
1930/* Add builtins for Load/store 64 Byte instructions. */
1931
1932typedef struct
1933{
1934 const char *name;
1935 unsigned int code;
1936 tree type;
1937} ls64_builtins_data;
1938
1939static GTY(()) tree ls64_arm_data_t = NULL_TREE;
1940
1941static void
1942aarch64_init_ls64_builtins_types (void)
1943{
1944 /* Synthesize:
1945
1946 typedef struct {
1947 uint64_t val[8];
1948 } __arm_data512_t; */
1949 const char *tuple_type_name = "__arm_data512_t";
1950 tree node_type = get_typenode_from_name (UINT64_TYPE);
1951 tree array_type = build_array_type_nelts (node_type, 8);
1952 SET_TYPE_MODE (array_type, V8DImode);
1953
1954 gcc_assert (TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type));
1955 gcc_assert (TYPE_ALIGN (array_type) == 64);
1956
1957 tree field = build_decl (input_location, FIELD_DECL,
71361354 1958 get_identifier ("val"), array_type);
fdcddba8
PW
1959
1960 ls64_arm_data_t = lang_hooks.types.simulate_record_decl (input_location,
71361354
AC
1961 tuple_type_name,
1962 make_array_slice (&field, 1));
fdcddba8
PW
1963
1964 gcc_assert (TYPE_MODE (ls64_arm_data_t) == V8DImode);
1965 gcc_assert (TYPE_MODE_RAW (ls64_arm_data_t) == TYPE_MODE (ls64_arm_data_t));
1966 gcc_assert (TYPE_ALIGN (ls64_arm_data_t) == 64);
1967}
1968
1969static void
1970aarch64_init_ls64_builtins (void)
1971{
1972 aarch64_init_ls64_builtins_types ();
1973
1974 ls64_builtins_data data[4] = {
9963029a 1975 {"__arm_ld64b", AARCH64_LS64_BUILTIN_LD64B,
fdcddba8 1976 build_function_type_list (ls64_arm_data_t,
71361354 1977 const_ptr_type_node, NULL_TREE)},
9963029a 1978 {"__arm_st64b", AARCH64_LS64_BUILTIN_ST64B,
fdcddba8 1979 build_function_type_list (void_type_node, ptr_type_node,
71361354 1980 ls64_arm_data_t, NULL_TREE)},
9963029a 1981 {"__arm_st64bv", AARCH64_LS64_BUILTIN_ST64BV,
fdcddba8 1982 build_function_type_list (uint64_type_node, ptr_type_node,
71361354 1983 ls64_arm_data_t, NULL_TREE)},
9963029a 1984 {"__arm_st64bv0", AARCH64_LS64_BUILTIN_ST64BV0,
fdcddba8 1985 build_function_type_list (uint64_type_node, ptr_type_node,
71361354 1986 ls64_arm_data_t, NULL_TREE)},
fdcddba8
PW
1987 };
1988
1989 for (size_t i = 0; i < ARRAY_SIZE (data); ++i)
1990 aarch64_builtin_decls[data[i].code]
9963029a
AC
1991 = aarch64_general_simulate_builtin (data[i].name, data[i].type,
1992 data[i].code);
fdcddba8
PW
1993}
1994
eb966d39
ASDV
1995static void
1996aarch64_init_data_intrinsics (void)
1997{
1998 tree uint32_fntype = build_function_type_list (uint32_type_node,
1999 uint32_type_node, NULL_TREE);
2000 tree ulong_fntype = build_function_type_list (long_unsigned_type_node,
2001 long_unsigned_type_node,
2002 NULL_TREE);
2003 tree uint64_fntype = build_function_type_list (uint64_type_node,
2004 uint64_type_node, NULL_TREE);
2005 aarch64_builtin_decls[AARCH64_REV16]
2006 = aarch64_general_add_builtin ("__builtin_aarch64_rev16", uint32_fntype,
2007 AARCH64_REV16);
2008 aarch64_builtin_decls[AARCH64_REV16L]
2009 = aarch64_general_add_builtin ("__builtin_aarch64_rev16l", ulong_fntype,
2010 AARCH64_REV16L);
2011 aarch64_builtin_decls[AARCH64_REV16LL]
2012 = aarch64_general_add_builtin ("__builtin_aarch64_rev16ll", uint64_fntype,
2013 AARCH64_REV16LL);
2014 aarch64_builtin_decls[AARCH64_RBIT]
2015 = aarch64_general_add_builtin ("__builtin_aarch64_rbit", uint32_fntype,
2016 AARCH64_RBIT);
2017 aarch64_builtin_decls[AARCH64_RBITL]
2018 = aarch64_general_add_builtin ("__builtin_aarch64_rbitl", ulong_fntype,
2019 AARCH64_RBITL);
2020 aarch64_builtin_decls[AARCH64_RBITLL]
2021 = aarch64_general_add_builtin ("__builtin_aarch64_rbitll", uint64_fntype,
2022 AARCH64_RBITLL);
2023}
2024
af3cadb5
TC
2025/* Implement #pragma GCC aarch64 "arm_acle.h". */
2026void
2027handle_arm_acle_h (void)
2028{
2029 if (TARGET_LS64)
2030 aarch64_init_ls64_builtins ();
2031}
2032
0d7e5fa6 2033/* Initialize fpsr fpcr getters and setters. */
c5dc215d 2034
0d7e5fa6
AC
2035static void
2036aarch64_init_fpsr_fpcr_builtins (void)
43e9d192 2037{
0d7e5fa6 2038 tree ftype_set
aa87aced 2039 = build_function_type_list (void_type_node, unsigned_type_node, NULL);
0d7e5fa6 2040 tree ftype_get
aa87aced
KV
2041 = build_function_type_list (unsigned_type_node, NULL);
2042
2043 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
6d4d616a 2044 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr",
0d7e5fa6 2045 ftype_get,
6d4d616a 2046 AARCH64_BUILTIN_GET_FPCR);
aa87aced 2047 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
6d4d616a 2048 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr",
0d7e5fa6 2049 ftype_set,
6d4d616a 2050 AARCH64_BUILTIN_SET_FPCR);
aa87aced 2051 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
6d4d616a 2052 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr",
0d7e5fa6 2053 ftype_get,
6d4d616a 2054 AARCH64_BUILTIN_GET_FPSR);
aa87aced 2055 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
6d4d616a 2056 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr",
0d7e5fa6 2057 ftype_set,
6d4d616a 2058 AARCH64_BUILTIN_SET_FPSR);
aa87aced 2059
0d7e5fa6
AC
2060 ftype_set
2061 = build_function_type_list (void_type_node, long_long_unsigned_type_node,
2062 NULL);
2063 ftype_get
2064 = build_function_type_list (long_long_unsigned_type_node, NULL);
2065
2066 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR64]
2067 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr64",
2068 ftype_get,
2069 AARCH64_BUILTIN_GET_FPCR64);
2070 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR64]
2071 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr64",
2072 ftype_set,
2073 AARCH64_BUILTIN_SET_FPCR64);
2074 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR64]
2075 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr64",
2076 ftype_get,
2077 AARCH64_BUILTIN_GET_FPSR64);
2078 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR64]
2079 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr64",
2080 ftype_set,
2081 AARCH64_BUILTIN_SET_FPSR64);
2082}
2083
2084/* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group. */
2085
2086void
2087aarch64_general_init_builtins (void)
2088{
2089 aarch64_init_fpsr_fpcr_builtins ();
2090
1b62ed4f 2091 aarch64_init_fp16_types ();
c2ec330c 2092
abbe1ed2
SMW
2093 aarch64_init_bf16_types ();
2094
14814e20
RS
2095 {
2096 aarch64_simd_switcher simd;
280d970b 2097 aarch64_init_simd_builtins ();
14814e20 2098 }
e95a988a
KT
2099
2100 aarch64_init_crc32_builtins ();
a6fc00da 2101 aarch64_init_builtin_rsqrt ();
c5dc215d 2102 aarch64_init_rng_builtins ();
eb966d39 2103 aarch64_init_data_intrinsics ();
312492bd 2104
fc42900d
VDN
2105 aarch64_init_rwsr_builtins ();
2106
e1d5d19e
KT
2107 tree ftype_jcvt
2108 = build_function_type_list (intSI_type_node, double_type_node, NULL);
2109 aarch64_builtin_decls[AARCH64_JSCVT]
6d4d616a
RS
2110 = aarch64_general_add_builtin ("__builtin_aarch64_jcvtzs", ftype_jcvt,
2111 AARCH64_JSCVT);
e1d5d19e 2112
a876231c
JW
2113 /* Initialize pointer authentication builtins which are backed by instructions
2114 in NOP encoding space.
2115
2116 NOTE: these builtins are supposed to be used by libgcc unwinder only, as
2117 there is no support on return address signing under ILP32, we don't
2118 register them. */
2119 if (!TARGET_ILP32)
2120 aarch64_init_pauth_hint_builtins ();
89626179
SD
2121
2122 if (TARGET_TME)
2123 aarch64_init_tme_builtins ();
ef01e6bb
DZ
2124
2125 if (TARGET_MEMTAG)
2126 aarch64_init_memtag_builtins ();
9963029a
AC
2127
2128 if (in_lto_p)
2129 handle_arm_acle_h ();
43e9d192
IB
2130}
2131
6d4d616a 2132/* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group. */
119103ca 2133tree
6d4d616a 2134aarch64_general_builtin_decl (unsigned code, bool)
119103ca
JG
2135{
2136 if (code >= AARCH64_BUILTIN_MAX)
2137 return error_mark_node;
2138
2139 return aarch64_builtin_decls[code];
2140}
2141
5af697d7
VDN
2142bool
2143aarch64_general_check_builtin_call (location_t location, vec<location_t>,
2144 unsigned int code, tree fndecl,
2145 unsigned int nargs ATTRIBUTE_UNUSED, tree *args)
2146{
2147 switch (code)
2148 {
2149 case AARCH64_RSR:
2150 case AARCH64_RSRP:
2151 case AARCH64_RSR64:
2152 case AARCH64_RSRF:
2153 case AARCH64_RSRF64:
2154 case AARCH64_WSR:
2155 case AARCH64_WSRP:
2156 case AARCH64_WSR64:
2157 case AARCH64_WSRF:
2158 case AARCH64_WSRF64:
2159 tree addr = STRIP_NOPS (args[0]);
2160 if (TREE_CODE (TREE_TYPE (addr)) != POINTER_TYPE
2161 || TREE_CODE (addr) != ADDR_EXPR
2162 || TREE_CODE (TREE_OPERAND (addr, 0)) != STRING_CST)
2163 {
2164 error_at (location, "first argument to %qD must be a string literal",
2165 fndecl);
2166 return false;
2167 }
2168 }
2169 /* Default behavior. */
2170 return true;
2171}
2172
43e9d192
IB
2173typedef enum
2174{
2175 SIMD_ARG_COPY_TO_REG,
2176 SIMD_ARG_CONSTANT,
2a49c16d 2177 SIMD_ARG_LANE_INDEX,
4d0a0237 2178 SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX,
9d63f43b 2179 SIMD_ARG_LANE_PAIR_INDEX,
8c197c85 2180 SIMD_ARG_LANE_QUADTUP_INDEX,
43e9d192
IB
2181 SIMD_ARG_STOP
2182} builtin_simd_arg;
2183
e95a988a 2184
43e9d192
IB
2185static rtx
2186aarch64_simd_expand_args (rtx target, int icode, int have_retval,
4d0a0237 2187 tree exp, builtin_simd_arg *args,
b8506a8a 2188 machine_mode builtin_mode)
43e9d192 2189{
43e9d192 2190 rtx pat;
d9e80f49
AL
2191 rtx op[SIMD_MAX_BUILTIN_ARGS + 1]; /* First element for result operand. */
2192 int opc = 0;
2193
2194 if (have_retval)
2195 {
2196 machine_mode tmode = insn_data[icode].operand[0].mode;
2197 if (!target
43e9d192 2198 || GET_MODE (target) != tmode
d9e80f49
AL
2199 || !(*insn_data[icode].operand[0].predicate) (target, tmode))
2200 target = gen_reg_rtx (tmode);
2201 op[opc++] = target;
2202 }
43e9d192 2203
43e9d192
IB
2204 for (;;)
2205 {
d9e80f49 2206 builtin_simd_arg thisarg = args[opc - have_retval];
43e9d192
IB
2207
2208 if (thisarg == SIMD_ARG_STOP)
2209 break;
2210 else
2211 {
d9e80f49 2212 tree arg = CALL_EXPR_ARG (exp, opc - have_retval);
b8506a8a 2213 machine_mode mode = insn_data[icode].operand[opc].mode;
d9e80f49 2214 op[opc] = expand_normal (arg);
43e9d192
IB
2215
2216 switch (thisarg)
2217 {
2218 case SIMD_ARG_COPY_TO_REG:
d9e80f49
AL
2219 if (POINTER_TYPE_P (TREE_TYPE (arg)))
2220 op[opc] = convert_memory_address (Pmode, op[opc]);
2221 /*gcc_assert (GET_MODE (op[opc]) == mode); */
2222 if (!(*insn_data[icode].operand[opc].predicate)
2223 (op[opc], mode))
2224 op[opc] = copy_to_mode_reg (mode, op[opc]);
43e9d192
IB
2225 break;
2226
4d0a0237
CB
2227 case SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX:
2228 gcc_assert (opc > 1);
2229 if (CONST_INT_P (op[opc]))
2230 {
6a70badb
RS
2231 unsigned int nunits
2232 = GET_MODE_NUNITS (builtin_mode).to_constant ();
2233 aarch64_simd_lane_bounds (op[opc], 0, nunits, exp);
4d0a0237 2234 /* Keep to GCC-vector-extension lane indices in the RTL. */
7ac29c0f
RS
2235 op[opc] = aarch64_endian_lane_rtx (builtin_mode,
2236 INTVAL (op[opc]));
4d0a0237
CB
2237 }
2238 goto constant_arg;
2239
2a49c16d
AL
2240 case SIMD_ARG_LANE_INDEX:
2241 /* Must be a previous operand into which this is an index. */
d9e80f49
AL
2242 gcc_assert (opc > 0);
2243 if (CONST_INT_P (op[opc]))
2a49c16d 2244 {
d9e80f49 2245 machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
6a70badb
RS
2246 unsigned int nunits
2247 = GET_MODE_NUNITS (vmode).to_constant ();
2248 aarch64_simd_lane_bounds (op[opc], 0, nunits, exp);
2a49c16d 2249 /* Keep to GCC-vector-extension lane indices in the RTL. */
7ac29c0f 2250 op[opc] = aarch64_endian_lane_rtx (vmode, INTVAL (op[opc]));
2a49c16d 2251 }
9d63f43b
TC
2252 /* If the lane index isn't a constant then error out. */
2253 goto constant_arg;
2254
2255 case SIMD_ARG_LANE_PAIR_INDEX:
2256 /* Must be a previous operand into which this is an index and
2257 index is restricted to nunits / 2. */
2258 gcc_assert (opc > 0);
2259 if (CONST_INT_P (op[opc]))
2260 {
2261 machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
2262 unsigned int nunits
2263 = GET_MODE_NUNITS (vmode).to_constant ();
2264 aarch64_simd_lane_bounds (op[opc], 0, nunits / 2, exp);
2265 /* Keep to GCC-vector-extension lane indices in the RTL. */
33b5a38c
TC
2266 int lane = INTVAL (op[opc]);
2267 op[opc] = gen_int_mode (ENDIAN_LANE_N (nunits / 2, lane),
2268 SImode);
9d63f43b 2269 }
8c197c85
SMW
2270 /* If the lane index isn't a constant then error out. */
2271 goto constant_arg;
2272 case SIMD_ARG_LANE_QUADTUP_INDEX:
2273 /* Must be a previous operand into which this is an index and
2274 index is restricted to nunits / 4. */
2275 gcc_assert (opc > 0);
2276 if (CONST_INT_P (op[opc]))
2277 {
2278 machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
2279 unsigned int nunits
2280 = GET_MODE_NUNITS (vmode).to_constant ();
2281 aarch64_simd_lane_bounds (op[opc], 0, nunits / 4, exp);
2282 /* Keep to GCC-vector-extension lane indices in the RTL. */
2283 int lane = INTVAL (op[opc]);
2284 op[opc] = gen_int_mode (ENDIAN_LANE_N (nunits / 4, lane),
2285 SImode);
2286 }
2287 /* If the lane index isn't a constant then error out. */
2288 goto constant_arg;
43e9d192 2289 case SIMD_ARG_CONSTANT:
4d0a0237 2290constant_arg:
d9e80f49
AL
2291 if (!(*insn_data[icode].operand[opc].predicate)
2292 (op[opc], mode))
d5a29419 2293 {
62e43587
MS
2294 error_at (EXPR_LOCATION (exp),
2295 "argument %d must be a constant immediate",
2296 opc + 1 - have_retval);
d5a29419
KT
2297 return const0_rtx;
2298 }
43e9d192
IB
2299 break;
2300
2301 case SIMD_ARG_STOP:
2302 gcc_unreachable ();
2303 }
2304
d9e80f49 2305 opc++;
43e9d192
IB
2306 }
2307 }
2308
d9e80f49
AL
2309 switch (opc)
2310 {
2311 case 1:
2312 pat = GEN_FCN (icode) (op[0]);
2313 break;
43e9d192 2314
d9e80f49
AL
2315 case 2:
2316 pat = GEN_FCN (icode) (op[0], op[1]);
2317 break;
43e9d192 2318
d9e80f49
AL
2319 case 3:
2320 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
2321 break;
43e9d192 2322
d9e80f49
AL
2323 case 4:
2324 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
2325 break;
43e9d192 2326
d9e80f49
AL
2327 case 5:
2328 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
2329 break;
43e9d192 2330
d9e80f49
AL
2331 case 6:
2332 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]);
2333 break;
43e9d192 2334
d9e80f49
AL
2335 default:
2336 gcc_unreachable ();
2337 }
43e9d192
IB
2338
2339 if (!pat)
d5a29419 2340 return NULL_RTX;
43e9d192
IB
2341
2342 emit_insn (pat);
2343
2344 return target;
2345}
2346
2347/* Expand an AArch64 AdvSIMD builtin(intrinsic). */
2348rtx
2349aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
2350{
661fce82
AL
2351 if (fcode == AARCH64_SIMD_BUILTIN_LANE_CHECK)
2352 {
9c4f25cc
AP
2353 rtx totalsize = expand_normal (CALL_EXPR_ARG (exp, 0));
2354 rtx elementsize = expand_normal (CALL_EXPR_ARG (exp, 1));
2355 if (CONST_INT_P (totalsize) && CONST_INT_P (elementsize)
2356 && UINTVAL (elementsize) != 0
2357 && UINTVAL (totalsize) != 0)
2358 {
2359 rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 2));
2360 if (CONST_INT_P (lane_idx))
2361 aarch64_simd_lane_bounds (lane_idx, 0,
2362 UINTVAL (totalsize)
2363 / UINTVAL (elementsize),
2364 exp);
2365 else
62e43587
MS
2366 error_at (EXPR_LOCATION (exp),
2367 "lane index must be a constant immediate");
9c4f25cc 2368 }
661fce82 2369 else
62e43587 2370 error_at (EXPR_LOCATION (exp),
58385f6a 2371 "total size and element size must be a nonzero "
62e43587 2372 "constant immediate");
661fce82
AL
2373 /* Don't generate any RTL. */
2374 return const0_rtx;
2375 }
342be7f7 2376 aarch64_simd_builtin_datum *d =
661fce82 2377 &aarch64_simd_builtin_data[fcode - AARCH64_SIMD_PATTERN_START];
342be7f7 2378 enum insn_code icode = d->code;
0ff2bf46 2379 builtin_simd_arg args[SIMD_MAX_BUILTIN_ARGS + 1];
b5828b4b
JG
2380 int num_args = insn_data[d->code].n_operands;
2381 int is_void = 0;
2382 int k;
43e9d192 2383
b5828b4b 2384 is_void = !!(d->qualifiers[0] & qualifier_void);
43e9d192 2385
b5828b4b
JG
2386 num_args += is_void;
2387
2388 for (k = 1; k < num_args; k++)
2389 {
2390 /* We have four arrays of data, each indexed in a different fashion.
2391 qualifiers - element 0 always describes the function return type.
2392 operands - element 0 is either the operand for return value (if
2393 the function has a non-void return type) or the operand for the
2394 first argument.
2395 expr_args - element 0 always holds the first argument.
2396 args - element 0 is always used for the return type. */
2397 int qualifiers_k = k;
2398 int operands_k = k - is_void;
2399 int expr_args_k = k - 1;
2400
2a49c16d
AL
2401 if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
2402 args[k] = SIMD_ARG_LANE_INDEX;
9d63f43b
TC
2403 else if (d->qualifiers[qualifiers_k] & qualifier_lane_pair_index)
2404 args[k] = SIMD_ARG_LANE_PAIR_INDEX;
8c197c85
SMW
2405 else if (d->qualifiers[qualifiers_k] & qualifier_lane_quadtup_index)
2406 args[k] = SIMD_ARG_LANE_QUADTUP_INDEX;
4d0a0237
CB
2407 else if (d->qualifiers[qualifiers_k] & qualifier_struct_load_store_lane_index)
2408 args[k] = SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX;
2a49c16d 2409 else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
b5828b4b
JG
2410 args[k] = SIMD_ARG_CONSTANT;
2411 else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
2412 {
2413 rtx arg
2414 = expand_normal (CALL_EXPR_ARG (exp,
2415 (expr_args_k)));
2416 /* Handle constants only if the predicate allows it. */
2417 bool op_const_int_p =
2418 (CONST_INT_P (arg)
2419 && (*insn_data[icode].operand[operands_k].predicate)
2420 (arg, insn_data[icode].operand[operands_k].mode));
2421 args[k] = op_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG;
2422 }
2423 else
2424 args[k] = SIMD_ARG_COPY_TO_REG;
43e9d192 2425
43e9d192 2426 }
b5828b4b
JG
2427 args[k] = SIMD_ARG_STOP;
2428
2429 /* The interface to aarch64_simd_expand_args expects a 0 if
2430 the function is void, and a 1 if it is not. */
2431 return aarch64_simd_expand_args
4d0a0237 2432 (target, icode, !is_void, exp, &args[1], d->mode);
43e9d192 2433}
342be7f7 2434
5d357f26
KT
2435rtx
2436aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target)
2437{
2438 rtx pat;
2439 aarch64_crc_builtin_datum *d
2440 = &aarch64_crc_builtin_data[fcode - (AARCH64_CRC32_BUILTIN_BASE + 1)];
2441 enum insn_code icode = d->icode;
2442 tree arg0 = CALL_EXPR_ARG (exp, 0);
2443 tree arg1 = CALL_EXPR_ARG (exp, 1);
2444 rtx op0 = expand_normal (arg0);
2445 rtx op1 = expand_normal (arg1);
ef4bddc2
RS
2446 machine_mode tmode = insn_data[icode].operand[0].mode;
2447 machine_mode mode0 = insn_data[icode].operand[1].mode;
2448 machine_mode mode1 = insn_data[icode].operand[2].mode;
5d357f26
KT
2449
2450 if (! target
2451 || GET_MODE (target) != tmode
2452 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2453 target = gen_reg_rtx (tmode);
2454
2455 gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
2456 && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
2457
2458 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2459 op0 = copy_to_mode_reg (mode0, op0);
2460 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
2461 op1 = copy_to_mode_reg (mode1, op1);
2462
2463 pat = GEN_FCN (icode) (target, op0, op1);
d5a29419
KT
2464 if (!pat)
2465 return NULL_RTX;
2466
5d357f26
KT
2467 emit_insn (pat);
2468 return target;
2469}
2470
a6fc00da
BH
2471/* Function to expand reciprocal square root builtins. */
2472
2473static rtx
2474aarch64_expand_builtin_rsqrt (int fcode, tree exp, rtx target)
2475{
2476 tree arg0 = CALL_EXPR_ARG (exp, 0);
2477 rtx op0 = expand_normal (arg0);
2478
2479 rtx (*gen) (rtx, rtx);
2480
2481 switch (fcode)
2482 {
2483 case AARCH64_BUILTIN_RSQRT_DF:
ee62a5a6 2484 gen = gen_rsqrtdf2;
a6fc00da
BH
2485 break;
2486 case AARCH64_BUILTIN_RSQRT_SF:
ee62a5a6 2487 gen = gen_rsqrtsf2;
a6fc00da
BH
2488 break;
2489 case AARCH64_BUILTIN_RSQRT_V2DF:
ee62a5a6 2490 gen = gen_rsqrtv2df2;
a6fc00da
BH
2491 break;
2492 case AARCH64_BUILTIN_RSQRT_V2SF:
ee62a5a6 2493 gen = gen_rsqrtv2sf2;
a6fc00da
BH
2494 break;
2495 case AARCH64_BUILTIN_RSQRT_V4SF:
ee62a5a6 2496 gen = gen_rsqrtv4sf2;
a6fc00da
BH
2497 break;
2498 default: gcc_unreachable ();
2499 }
2500
2501 if (!target)
2502 target = gen_reg_rtx (GET_MODE (op0));
2503
2504 emit_insn (gen (target, op0));
2505
2506 return target;
2507}
2508
9d63f43b
TC
2509/* Expand a FCMLA lane expression EXP with code FCODE and
2510 result going to TARGET if that is convenient. */
2511
2512rtx
2513aarch64_expand_fcmla_builtin (tree exp, rtx target, int fcode)
2514{
2515 int bcode = fcode - AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE - 1;
2516 aarch64_fcmla_laneq_builtin_datum* d
2517 = &aarch64_fcmla_lane_builtin_data[bcode];
2518 machine_mode quadmode = GET_MODE_2XWIDER_MODE (d->mode).require ();
2519 rtx op0 = force_reg (d->mode, expand_normal (CALL_EXPR_ARG (exp, 0)));
2520 rtx op1 = force_reg (d->mode, expand_normal (CALL_EXPR_ARG (exp, 1)));
2521 rtx op2 = force_reg (quadmode, expand_normal (CALL_EXPR_ARG (exp, 2)));
2522 tree tmp = CALL_EXPR_ARG (exp, 3);
2523 rtx lane_idx = expand_expr (tmp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
2524
2525 /* Validate that the lane index is a constant. */
2526 if (!CONST_INT_P (lane_idx))
2527 {
62e43587
MS
2528 error_at (EXPR_LOCATION (exp),
2529 "argument %d must be a constant immediate", 4);
9d63f43b
TC
2530 return const0_rtx;
2531 }
2532
2533 /* Validate that the index is within the expected range. */
2534 int nunits = GET_MODE_NUNITS (quadmode).to_constant ();
2535 aarch64_simd_lane_bounds (lane_idx, 0, nunits / 2, exp);
2536
9d63f43b
TC
2537 /* Generate the correct register and mode. */
2538 int lane = INTVAL (lane_idx);
2539
2540 if (lane < nunits / 4)
33b5a38c
TC
2541 op2 = simplify_gen_subreg (d->mode, op2, quadmode,
2542 subreg_lowpart_offset (d->mode, quadmode));
9d63f43b
TC
2543 else
2544 {
2545 /* Select the upper 64 bits, either a V2SF or V4HF, this however
2546 is quite messy, as the operation required even though simple
2547 doesn't have a simple RTL pattern, and seems it's quite hard to
2548 define using a single RTL pattern. The target generic version
2549 gen_highpart_mode generates code that isn't optimal. */
2550 rtx temp1 = gen_reg_rtx (d->mode);
2551 rtx temp2 = gen_reg_rtx (DImode);
33b5a38c
TC
2552 temp1 = simplify_gen_subreg (d->mode, op2, quadmode,
2553 subreg_lowpart_offset (d->mode, quadmode));
9d63f43b 2554 temp1 = simplify_gen_subreg (V2DImode, temp1, d->mode, 0);
33b5a38c
TC
2555 if (BYTES_BIG_ENDIAN)
2556 emit_insn (gen_aarch64_get_lanev2di (temp2, temp1, const0_rtx));
2557 else
2558 emit_insn (gen_aarch64_get_lanev2di (temp2, temp1, const1_rtx));
9d63f43b
TC
2559 op2 = simplify_gen_subreg (d->mode, temp2, GET_MODE (temp2), 0);
2560
2561 /* And recalculate the index. */
2562 lane -= nunits / 4;
2563 }
2564
33b5a38c
TC
2565 /* Keep to GCC-vector-extension lane indices in the RTL, only nunits / 4
2566 (max nunits in range check) are valid. Which means only 0-1, so we
2567 only need to know the order in a V2mode. */
2568 lane_idx = aarch64_endian_lane_rtx (V2DImode, lane);
2569
fa59c8dc
AC
2570 if (!target
2571 || !REG_P (target)
2572 || GET_MODE (target) != d->mode)
9d63f43b 2573 target = gen_reg_rtx (d->mode);
9d63f43b
TC
2574
2575 rtx pat = NULL_RTX;
2576
2577 if (d->lane)
33b5a38c 2578 pat = GEN_FCN (d->icode) (target, op0, op1, op2, lane_idx);
9d63f43b
TC
2579 else
2580 pat = GEN_FCN (d->icode) (target, op0, op1, op2);
2581
2582 if (!pat)
2583 return NULL_RTX;
2584
2585 emit_insn (pat);
2586 return target;
2587}
2588
89626179
SD
2589/* Function to expand an expression EXP which calls one of the Transactional
2590 Memory Extension (TME) builtins FCODE with the result going to TARGET. */
2591static rtx
2592aarch64_expand_builtin_tme (int fcode, tree exp, rtx target)
2593{
2594 switch (fcode)
2595 {
2596 case AARCH64_TME_BUILTIN_TSTART:
2597 target = gen_reg_rtx (DImode);
2598 emit_insn (GEN_FCN (CODE_FOR_tstart) (target));
2599 break;
2600
2601 case AARCH64_TME_BUILTIN_TTEST:
2602 target = gen_reg_rtx (DImode);
2603 emit_insn (GEN_FCN (CODE_FOR_ttest) (target));
2604 break;
2605
2606 case AARCH64_TME_BUILTIN_TCOMMIT:
2607 emit_insn (GEN_FCN (CODE_FOR_tcommit) ());
2608 break;
2609
2610 case AARCH64_TME_BUILTIN_TCANCEL:
2611 {
2612 tree arg0 = CALL_EXPR_ARG (exp, 0);
2613 rtx op0 = expand_normal (arg0);
2614 if (CONST_INT_P (op0) && UINTVAL (op0) <= 65536)
2615 emit_insn (GEN_FCN (CODE_FOR_tcancel) (op0));
2616 else
2617 {
62e43587
MS
2618 error_at (EXPR_LOCATION (exp),
2619 "argument must be a 16-bit constant immediate");
89626179
SD
2620 return const0_rtx;
2621 }
2622 }
2623 break;
2624
2625 default :
2626 gcc_unreachable ();
2627 }
2628 return target;
2629}
2630
fdcddba8
PW
2631/* Function to expand an expression EXP which calls one of the Load/Store
2632 64 Byte extension (LS64) builtins FCODE with the result going to TARGET. */
2633static rtx
2634aarch64_expand_builtin_ls64 (int fcode, tree exp, rtx target)
2635{
2636 expand_operand ops[3];
2637
2638 switch (fcode)
2639 {
2640 case AARCH64_LS64_BUILTIN_LD64B:
2641 {
71361354
AC
2642 rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2643 create_output_operand (&ops[0], target, V8DImode);
2644 create_input_operand (&ops[1], op0, DImode);
2645 expand_insn (CODE_FOR_ld64b, 2, ops);
2646 return ops[0].value;
fdcddba8
PW
2647 }
2648 case AARCH64_LS64_BUILTIN_ST64B:
2649 {
71361354
AC
2650 rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2651 rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
737a0b74 2652 create_input_operand (&ops[0], op0, DImode);
71361354
AC
2653 create_input_operand (&ops[1], op1, V8DImode);
2654 expand_insn (CODE_FOR_st64b, 2, ops);
2655 return const0_rtx;
fdcddba8
PW
2656 }
2657 case AARCH64_LS64_BUILTIN_ST64BV:
2658 {
71361354
AC
2659 rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2660 rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2661 create_output_operand (&ops[0], target, DImode);
2662 create_input_operand (&ops[1], op0, DImode);
2663 create_input_operand (&ops[2], op1, V8DImode);
2664 expand_insn (CODE_FOR_st64bv, 3, ops);
2665 return ops[0].value;
fdcddba8
PW
2666 }
2667 case AARCH64_LS64_BUILTIN_ST64BV0:
2668 {
71361354
AC
2669 rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2670 rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2671 create_output_operand (&ops[0], target, DImode);
2672 create_input_operand (&ops[1], op0, DImode);
2673 create_input_operand (&ops[2], op1, V8DImode);
2674 expand_insn (CODE_FOR_st64bv0, 3, ops);
2675 return ops[0].value;
fdcddba8
PW
2676 }
2677 }
2678
2679 gcc_unreachable ();
2680}
2681
c5dc215d
KT
2682/* Expand a random number builtin EXP with code FCODE, putting the result
2683 int TARGET. If IGNORE is true the return value is ignored. */
2684
2685rtx
2686aarch64_expand_rng_builtin (tree exp, rtx target, int fcode, int ignore)
2687{
2688 rtx pat;
2689 enum insn_code icode;
2690 if (fcode == AARCH64_BUILTIN_RNG_RNDR)
2691 icode = CODE_FOR_aarch64_rndr;
2692 else if (fcode == AARCH64_BUILTIN_RNG_RNDRRS)
2693 icode = CODE_FOR_aarch64_rndrrs;
2694 else
2695 gcc_unreachable ();
2696
2697 rtx rand = gen_reg_rtx (DImode);
2698 pat = GEN_FCN (icode) (rand);
2699 if (!pat)
2700 return NULL_RTX;
2701
2702 tree arg0 = CALL_EXPR_ARG (exp, 0);
2703 rtx res_addr = expand_normal (arg0);
2704 res_addr = convert_memory_address (Pmode, res_addr);
2705 rtx res_mem = gen_rtx_MEM (DImode, res_addr);
2706 emit_insn (pat);
2707 emit_move_insn (res_mem, rand);
2708 /* If the status result is unused don't generate the CSET code. */
2709 if (ignore)
2710 return target;
2711
2712 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
f7581eb3 2713 rtx cmp_rtx = gen_rtx_fmt_ee (EQ, SImode, cc_reg, const0_rtx);
c5dc215d
KT
2714 emit_insn (gen_aarch64_cstoresi (target, cmp_rtx, cc_reg));
2715 return target;
2716}
2717
fc42900d
VDN
2718/* Expand the read/write system register builtin EXPs. */
2719rtx
2720aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
2721{
2722 tree arg0, arg1;
2723 rtx const_str, input_val, subreg;
2724 enum machine_mode mode;
88157c88 2725 enum insn_code icode;
fc42900d
VDN
2726 class expand_operand ops[2];
2727
2728 arg0 = CALL_EXPR_ARG (exp, 0);
2729
2730 bool write_op = (fcode == AARCH64_WSR
2731 || fcode == AARCH64_WSRP
2732 || fcode == AARCH64_WSR64
2733 || fcode == AARCH64_WSRF
88157c88
VDN
2734 || fcode == AARCH64_WSRF64
2735 || fcode == AARCH64_WSR128);
2736
2737 bool op128 = (fcode == AARCH64_RSR128 || fcode == AARCH64_WSR128);
2738 enum machine_mode sysreg_mode = op128 ? TImode : DImode;
2739
2740 if (op128 && !TARGET_D128)
2741 {
2742 error_at (EXPR_LOCATION (exp), "128-bit system register support requires"
2743 " the %<d128%> extension");
2744 return const0_rtx;
2745 }
fc42900d
VDN
2746
2747 /* Argument 0 (system register name) must be a string literal. */
2748 gcc_assert (TREE_CODE (arg0) == ADDR_EXPR
2749 && TREE_CODE (TREE_TYPE (arg0)) == POINTER_TYPE
2750 && TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST);
2751
2752 const char *name_input = TREE_STRING_POINTER (TREE_OPERAND (arg0, 0));
2753
2754 tree len_tree = c_strlen (arg0, 1);
2755 if (len_tree == NULL_TREE)
2756 {
2757 error_at (EXPR_LOCATION (exp), "invalid system register name provided");
2758 return const0_rtx;
2759 }
2760
2761 size_t len = TREE_INT_CST_LOW (len_tree);
2762 char *sysreg_name = xstrdup (name_input);
2763
2764 for (unsigned pos = 0; pos <= len; pos++)
2765 sysreg_name[pos] = TOLOWER (sysreg_name[pos]);
2766
88157c88
VDN
2767 const char* name_output = aarch64_retrieve_sysreg ((const char *) sysreg_name,
2768 write_op, op128);
fc42900d
VDN
2769 if (name_output == NULL)
2770 {
2771 error_at (EXPR_LOCATION (exp), "invalid system register name %qs",
2772 sysreg_name);
2773 return const0_rtx;
2774 }
2775
2776 /* Assign the string corresponding to the system register name to an RTX. */
2777 const_str = rtx_alloc (CONST_STRING);
2778 PUT_CODE (const_str, CONST_STRING);
2779 XSTR (const_str, 0) = ggc_strdup (name_output);
2780
2781 /* Set up expander operands and call instruction expansion. */
2782 if (write_op)
2783 {
2784 arg1 = CALL_EXPR_ARG (exp, 1);
2785 mode = TYPE_MODE (TREE_TYPE (arg1));
2786 input_val = copy_to_mode_reg (mode, expand_normal (arg1));
2787
88157c88
VDN
2788 icode = (op128 ? CODE_FOR_aarch64_write_sysregti
2789 : CODE_FOR_aarch64_write_sysregdi);
2790
fc42900d
VDN
2791 switch (fcode)
2792 {
2793 case AARCH64_WSR:
2794 case AARCH64_WSRP:
2795 case AARCH64_WSR64:
2796 case AARCH64_WSRF64:
88157c88
VDN
2797 case AARCH64_WSR128:
2798 subreg = lowpart_subreg (sysreg_mode, input_val, mode);
fc42900d
VDN
2799 break;
2800 case AARCH64_WSRF:
2801 subreg = gen_lowpart_SUBREG (SImode, input_val);
2802 subreg = gen_lowpart_SUBREG (DImode, subreg);
2803 break;
2804 }
2805
2806 create_fixed_operand (&ops[0], const_str);
88157c88
VDN
2807 create_input_operand (&ops[1], subreg, sysreg_mode);
2808 expand_insn (icode, 2, ops);
fc42900d
VDN
2809
2810 return target;
2811 }
2812
2813 /* Read operations are implied by !write_op. */
2814 gcc_assert (call_expr_nargs (exp) == 1);
2815
88157c88
VDN
2816 icode = (op128 ? CODE_FOR_aarch64_read_sysregti
2817 : CODE_FOR_aarch64_read_sysregdi);
2818
fc42900d 2819 /* Emit the initial read_sysregdi rtx. */
88157c88 2820 create_output_operand (&ops[0], target, sysreg_mode);
fc42900d 2821 create_fixed_operand (&ops[1], const_str);
88157c88 2822 expand_insn (icode, 2, ops);
fc42900d
VDN
2823 target = ops[0].value;
2824
2825 /* Do any necessary post-processing on the result. */
2826 switch (fcode)
2827 {
2828 case AARCH64_RSR:
2829 case AARCH64_RSRP:
2830 case AARCH64_RSR64:
2831 case AARCH64_RSRF64:
88157c88
VDN
2832 case AARCH64_RSR128:
2833 return lowpart_subreg (TYPE_MODE (TREE_TYPE (exp)), target, sysreg_mode);
fc42900d
VDN
2834 case AARCH64_RSRF:
2835 subreg = gen_lowpart_SUBREG (SImode, target);
2836 return gen_lowpart_SUBREG (SFmode, subreg);
2837 default:
2838 gcc_unreachable ();
2839 }
2840}
2841
ef01e6bb
DZ
2842/* Expand an expression EXP that calls a MEMTAG built-in FCODE
2843 with result going to TARGET. */
2844static rtx
2845aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)
2846{
2847 if (TARGET_ILP32)
2848 {
2849 error ("Memory Tagging Extension does not support %<-mabi=ilp32%>");
2850 return const0_rtx;
2851 }
2852
2853 rtx pat = NULL;
2854 enum insn_code icode = aarch64_memtag_builtin_data[fcode -
2855 AARCH64_MEMTAG_BUILTIN_START - 1].icode;
2856
2857 rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2858 machine_mode mode0 = GET_MODE (op0);
2859 op0 = force_reg (mode0 == VOIDmode ? DImode : mode0, op0);
2860 op0 = convert_to_mode (DImode, op0, true);
2861
2862 switch (fcode)
2863 {
2864 case AARCH64_MEMTAG_BUILTIN_IRG:
2865 case AARCH64_MEMTAG_BUILTIN_GMI:
2866 case AARCH64_MEMTAG_BUILTIN_SUBP:
2867 case AARCH64_MEMTAG_BUILTIN_INC_TAG:
2868 {
2869 if (! target
2870 || GET_MODE (target) != DImode
2871 || ! (*insn_data[icode].operand[0].predicate) (target, DImode))
2872 target = gen_reg_rtx (DImode);
2873
2874 if (fcode == AARCH64_MEMTAG_BUILTIN_INC_TAG)
2875 {
2876 rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2877
2878 if ((*insn_data[icode].operand[3].predicate) (op1, QImode))
2879 {
2880 pat = GEN_FCN (icode) (target, op0, const0_rtx, op1);
2881 break;
2882 }
62e43587
MS
2883 error_at (EXPR_LOCATION (exp),
2884 "argument %d must be a constant immediate "
2885 "in range [0,15]", 2);
ef01e6bb
DZ
2886 return const0_rtx;
2887 }
2888 else
2889 {
2890 rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2891 machine_mode mode1 = GET_MODE (op1);
2892 op1 = force_reg (mode1 == VOIDmode ? DImode : mode1, op1);
2893 op1 = convert_to_mode (DImode, op1, true);
2894 pat = GEN_FCN (icode) (target, op0, op1);
2895 }
2896 break;
2897 }
2898 case AARCH64_MEMTAG_BUILTIN_GET_TAG:
2899 target = op0;
2900 pat = GEN_FCN (icode) (target, op0, const0_rtx);
2901 break;
2902 case AARCH64_MEMTAG_BUILTIN_SET_TAG:
2903 pat = GEN_FCN (icode) (op0, op0, const0_rtx);
2904 break;
2905 default:
2906 gcc_unreachable();
2907 }
2908
2909 if (!pat)
2910 return NULL_RTX;
2911
2912 emit_insn (pat);
2913 return target;
2914}
2915
eb966d39
ASDV
2916/* Function to expand an expression EXP which calls one of the ACLE Data
2917 Intrinsic builtins FCODE with the result going to TARGET. */
2918static rtx
2919aarch64_expand_builtin_data_intrinsic (unsigned int fcode, tree exp, rtx target)
2920{
2921 expand_operand ops[2];
98756bcb 2922 machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
eb966d39
ASDV
2923 create_output_operand (&ops[0], target, mode);
2924 create_input_operand (&ops[1], expand_normal (CALL_EXPR_ARG (exp, 0)), mode);
2925 enum insn_code icode;
2926
2927 switch (fcode)
2928 {
2929 case AARCH64_REV16:
2930 case AARCH64_REV16L:
2931 case AARCH64_REV16LL:
2932 icode = code_for_aarch64_rev16 (mode);
2933 break;
2934 case AARCH64_RBIT:
2935 case AARCH64_RBITL:
2936 case AARCH64_RBITLL:
2937 icode = code_for_aarch64_rbit (mode);
2938 break;
2939 default:
2940 gcc_unreachable ();
2941 }
2942
2943 expand_insn (icode, 2, ops);
2944 return ops[0].value;
2945}
2946
f5e73de0 2947/* Expand an expression EXP as fpsr or fpcr setter (depending on
0d7e5fa6
AC
2948 UNSPEC) using MODE. */
2949static void
2950aarch64_expand_fpsr_fpcr_setter (int unspec, machine_mode mode, tree exp)
2951{
2952 tree arg = CALL_EXPR_ARG (exp, 0);
2953 rtx op = force_reg (mode, expand_normal (arg));
2954 emit_insn (gen_aarch64_set (unspec, mode, op));
2955}
2956
f5e73de0
AC
2957/* Expand a fpsr or fpcr getter (depending on UNSPEC) using MODE.
2958 Return the target. */
2959static rtx
2960aarch64_expand_fpsr_fpcr_getter (enum insn_code icode, machine_mode mode,
2961 rtx target)
2962{
2963 expand_operand op;
2964 create_output_operand (&op, target, mode);
2965 expand_insn (icode, 1, &op);
2966 return op.value;
2967}
2968
6d4d616a 2969/* Expand an expression EXP that calls built-in function FCODE,
c5dc215d
KT
2970 with result going to TARGET if that's convenient. IGNORE is true
2971 if the result of the builtin is ignored. */
342be7f7 2972rtx
c5dc215d
KT
2973aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
2974 int ignore)
342be7f7 2975{
aa87aced 2976 int icode;
0d7e5fa6 2977 rtx op0;
aa87aced
KV
2978 tree arg0;
2979
2980 switch (fcode)
2981 {
2982 case AARCH64_BUILTIN_GET_FPCR:
f5e73de0
AC
2983 return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpcrsi,
2984 SImode, target);
aa87aced 2985 case AARCH64_BUILTIN_SET_FPCR:
0d7e5fa6
AC
2986 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR, SImode, exp);
2987 return target;
aa87aced 2988 case AARCH64_BUILTIN_GET_FPSR:
f5e73de0
AC
2989 return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpsrsi,
2990 SImode, target);
aa87aced 2991 case AARCH64_BUILTIN_SET_FPSR:
0d7e5fa6
AC
2992 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR, SImode, exp);
2993 return target;
2994 case AARCH64_BUILTIN_GET_FPCR64:
f5e73de0
AC
2995 return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpcrdi,
2996 DImode, target);
0d7e5fa6
AC
2997 case AARCH64_BUILTIN_SET_FPCR64:
2998 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR, DImode, exp);
2999 return target;
3000 case AARCH64_BUILTIN_GET_FPSR64:
f5e73de0
AC
3001 return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpsrdi,
3002 DImode, target);
0d7e5fa6
AC
3003 case AARCH64_BUILTIN_SET_FPSR64:
3004 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR, DImode, exp);
aa87aced 3005 return target;
312492bd
JW
3006 case AARCH64_PAUTH_BUILTIN_AUTIA1716:
3007 case AARCH64_PAUTH_BUILTIN_PACIA1716:
8fc16d72
ST
3008 case AARCH64_PAUTH_BUILTIN_AUTIB1716:
3009 case AARCH64_PAUTH_BUILTIN_PACIB1716:
312492bd
JW
3010 case AARCH64_PAUTH_BUILTIN_XPACLRI:
3011 arg0 = CALL_EXPR_ARG (exp, 0);
3012 op0 = force_reg (Pmode, expand_normal (arg0));
3013
312492bd
JW
3014 if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
3015 {
3016 rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
3017 icode = CODE_FOR_xpaclri;
3018 emit_move_insn (lr, op0);
3019 emit_insn (GEN_FCN (icode) ());
92f0d3d0 3020 return lr;
312492bd
JW
3021 }
3022 else
3023 {
3024 tree arg1 = CALL_EXPR_ARG (exp, 1);
3025 rtx op1 = force_reg (Pmode, expand_normal (arg1));
8fc16d72
ST
3026 switch (fcode)
3027 {
3028 case AARCH64_PAUTH_BUILTIN_AUTIA1716:
3029 icode = CODE_FOR_autia1716;
3030 break;
3031 case AARCH64_PAUTH_BUILTIN_AUTIB1716:
3032 icode = CODE_FOR_autib1716;
3033 break;
3034 case AARCH64_PAUTH_BUILTIN_PACIA1716:
3035 icode = CODE_FOR_pacia1716;
3036 break;
3037 case AARCH64_PAUTH_BUILTIN_PACIB1716:
3038 icode = CODE_FOR_pacib1716;
3039 break;
3040 default:
3041 icode = 0;
3042 gcc_unreachable ();
3043 }
312492bd
JW
3044
3045 rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
3046 rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
3047 emit_move_insn (x17_reg, op0);
3048 emit_move_insn (x16_reg, op1);
3049 emit_insn (GEN_FCN (icode) ());
92f0d3d0 3050 return x17_reg;
312492bd
JW
3051 }
3052
e1d5d19e 3053 case AARCH64_JSCVT:
2c62952f
AC
3054 {
3055 expand_operand ops[2];
3056 create_output_operand (&ops[0], target, SImode);
3057 op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
3058 create_input_operand (&ops[1], op0, DFmode);
3059 expand_insn (CODE_FOR_aarch64_fjcvtzs, 2, ops);
3060 return ops[0].value;
3061 }
e1d5d19e 3062
9d63f43b
TC
3063 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V2SF:
3064 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V2SF:
3065 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V2SF:
3066 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V2SF:
3067 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V4HF:
3068 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V4HF:
3069 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V4HF:
3070 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V4HF:
3071 return aarch64_expand_fcmla_builtin (exp, target, fcode);
c5dc215d
KT
3072 case AARCH64_BUILTIN_RNG_RNDR:
3073 case AARCH64_BUILTIN_RNG_RNDRRS:
3074 return aarch64_expand_rng_builtin (exp, target, fcode, ignore);
fc42900d
VDN
3075 case AARCH64_RSR:
3076 case AARCH64_RSRP:
3077 case AARCH64_RSR64:
3078 case AARCH64_RSRF:
3079 case AARCH64_RSRF64:
88157c88 3080 case AARCH64_RSR128:
fc42900d
VDN
3081 case AARCH64_WSR:
3082 case AARCH64_WSRP:
3083 case AARCH64_WSR64:
3084 case AARCH64_WSRF:
3085 case AARCH64_WSRF64:
88157c88 3086 case AARCH64_WSR128:
fc42900d 3087 return aarch64_expand_rwsr_builtin (exp, target, fcode);
aa87aced 3088 }
342be7f7 3089
5d357f26 3090 if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
342be7f7 3091 return aarch64_simd_expand_builtin (fcode, exp, target);
5d357f26
KT
3092 else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX)
3093 return aarch64_crc32_expand_builtin (fcode, exp, target);
342be7f7 3094
a6fc00da
BH
3095 if (fcode == AARCH64_BUILTIN_RSQRT_DF
3096 || fcode == AARCH64_BUILTIN_RSQRT_SF
3097 || fcode == AARCH64_BUILTIN_RSQRT_V2DF
3098 || fcode == AARCH64_BUILTIN_RSQRT_V2SF
3099 || fcode == AARCH64_BUILTIN_RSQRT_V4SF)
3100 return aarch64_expand_builtin_rsqrt (fcode, exp, target);
3101
89626179
SD
3102 if (fcode == AARCH64_TME_BUILTIN_TSTART
3103 || fcode == AARCH64_TME_BUILTIN_TCOMMIT
3104 || fcode == AARCH64_TME_BUILTIN_TTEST
3105 || fcode == AARCH64_TME_BUILTIN_TCANCEL)
3106 return aarch64_expand_builtin_tme (fcode, exp, target);
3107
fdcddba8
PW
3108 if (fcode == AARCH64_LS64_BUILTIN_LD64B
3109 || fcode == AARCH64_LS64_BUILTIN_ST64B
3110 || fcode == AARCH64_LS64_BUILTIN_ST64BV
3111 || fcode == AARCH64_LS64_BUILTIN_ST64BV0)
3112 return aarch64_expand_builtin_ls64 (fcode, exp, target);
3113
ef01e6bb
DZ
3114 if (fcode >= AARCH64_MEMTAG_BUILTIN_START
3115 && fcode <= AARCH64_MEMTAG_BUILTIN_END)
3116 return aarch64_expand_builtin_memtag (fcode, exp, target);
eb966d39
ASDV
3117 if (fcode >= AARCH64_REV16
3118 && fcode <= AARCH64_RBITLL)
3119 return aarch64_expand_builtin_data_intrinsic (fcode, exp, target);
ef01e6bb 3120
d5a29419 3121 gcc_unreachable ();
342be7f7 3122}
42fc9a7f 3123
a6fc00da
BH
3124/* Return builtin for reciprocal square root. */
3125
3126tree
6d4d616a 3127aarch64_general_builtin_rsqrt (unsigned int fn)
a6fc00da 3128{
ee62a5a6
RS
3129 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df)
3130 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2DF];
3131 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf)
3132 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2SF];
3133 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf)
3134 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V4SF];
a6fc00da
BH
3135 return NULL_TREE;
3136}
3137
03312cbd
AP
3138/* Return true if the lane check can be removed as there is no
3139 error going to be emitted. */
3140static bool
3141aarch64_fold_builtin_lane_check (tree arg0, tree arg1, tree arg2)
3142{
3143 if (TREE_CODE (arg0) != INTEGER_CST)
3144 return false;
3145 if (TREE_CODE (arg1) != INTEGER_CST)
3146 return false;
3147 if (TREE_CODE (arg2) != INTEGER_CST)
3148 return false;
3149
3150 auto totalsize = wi::to_widest (arg0);
3151 auto elementsize = wi::to_widest (arg1);
3152 if (totalsize == 0 || elementsize == 0)
3153 return false;
3154 auto lane = wi::to_widest (arg2);
3155 auto high = wi::udiv_trunc (totalsize, elementsize);
3156 return wi::ltu_p (lane, high);
3157}
3158
0ac198d3 3159#undef VAR1
bf592b2f 3160#define VAR1(T, N, MAP, FLAG, A) \
e993fea1 3161 case AARCH64_SIMD_BUILTIN_##T##_##N##A:
0ac198d3 3162
c906efc7
AC
3163#undef VREINTERPRET_BUILTIN
3164#define VREINTERPRET_BUILTIN(A, B, L) \
3165 case AARCH64_SIMD_BUILTIN_VREINTERPRET##L##_##A##_##B:
3166
3167
6d4d616a
RS
3168/* Try to fold a call to the built-in function with subcode FCODE. The
3169 function is passed the N_ARGS arguments in ARGS and it returns a value
3170 of type TYPE. Return the new expression on success and NULL_TREE on
3171 failure. */
9697e620 3172tree
6d4d616a
RS
3173aarch64_general_fold_builtin (unsigned int fcode, tree type,
3174 unsigned int n_args ATTRIBUTE_UNUSED, tree *args)
9697e620 3175{
9697e620
JG
3176 switch (fcode)
3177 {
bf592b2f 3178 BUILTIN_VDQF (UNOP, abs, 2, ALL)
9697e620 3179 return fold_build1 (ABS_EXPR, type, args[0]);
bf592b2f 3180 VAR1 (UNOP, floatv2si, 2, ALL, v2sf)
3181 VAR1 (UNOP, floatv4si, 2, ALL, v4sf)
3182 VAR1 (UNOP, floatv2di, 2, ALL, v2df)
1709ff9b 3183 return fold_build1 (FLOAT_EXPR, type, args[0]);
c906efc7
AC
3184 AARCH64_SIMD_VREINTERPRET_BUILTINS
3185 return fold_build1 (VIEW_CONVERT_EXPR, type, args[0]);
03312cbd
AP
3186 case AARCH64_SIMD_BUILTIN_LANE_CHECK:
3187 gcc_assert (n_args == 3);
3188 if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
3189 return void_node;
3190 break;
9697e620
JG
3191 default:
3192 break;
3193 }
3194
3195 return NULL_TREE;
3196}
3197
ad44c6a5
ASDV
3198enum aarch64_simd_type
3199get_mem_type_for_load_store (unsigned int fcode)
3200{
3201 switch (fcode)
3202 {
1716ddd1
JW
3203 VAR1 (LOAD1, ld1, 0, LOAD, v8qi)
3204 VAR1 (STORE1, st1, 0, STORE, v8qi)
ad44c6a5 3205 return Int8x8_t;
1716ddd1
JW
3206 VAR1 (LOAD1, ld1, 0, LOAD, v16qi)
3207 VAR1 (STORE1, st1, 0, STORE, v16qi)
ad44c6a5 3208 return Int8x16_t;
1716ddd1
JW
3209 VAR1 (LOAD1, ld1, 0, LOAD, v4hi)
3210 VAR1 (STORE1, st1, 0, STORE, v4hi)
ad44c6a5 3211 return Int16x4_t;
1716ddd1
JW
3212 VAR1 (LOAD1, ld1, 0, LOAD, v8hi)
3213 VAR1 (STORE1, st1, 0, STORE, v8hi)
ad44c6a5 3214 return Int16x8_t;
1716ddd1
JW
3215 VAR1 (LOAD1, ld1, 0, LOAD, v2si)
3216 VAR1 (STORE1, st1, 0, STORE, v2si)
ad44c6a5 3217 return Int32x2_t;
1716ddd1
JW
3218 VAR1 (LOAD1, ld1, 0, LOAD, v4si)
3219 VAR1 (STORE1, st1, 0, STORE, v4si)
ad44c6a5 3220 return Int32x4_t;
1716ddd1
JW
3221 VAR1 (LOAD1, ld1, 0, LOAD, v2di)
3222 VAR1 (STORE1, st1, 0, STORE, v2di)
ad44c6a5 3223 return Int64x2_t;
1716ddd1
JW
3224 VAR1 (LOAD1_U, ld1, 0, LOAD, v8qi)
3225 VAR1 (STORE1_U, st1, 0, STORE, v8qi)
3226 return Uint8x8_t;
3227 VAR1 (LOAD1_U, ld1, 0, LOAD, v16qi)
3228 VAR1 (STORE1_U, st1, 0, STORE, v16qi)
3229 return Uint8x16_t;
3230 VAR1 (LOAD1_U, ld1, 0, LOAD, v4hi)
3231 VAR1 (STORE1_U, st1, 0, STORE, v4hi)
3232 return Uint16x4_t;
3233 VAR1 (LOAD1_U, ld1, 0, LOAD, v8hi)
3234 VAR1 (STORE1_U, st1, 0, STORE, v8hi)
3235 return Uint16x8_t;
3236 VAR1 (LOAD1_U, ld1, 0, LOAD, v2si)
3237 VAR1 (STORE1_U, st1, 0, STORE, v2si)
3238 return Uint32x2_t;
3239 VAR1 (LOAD1_U, ld1, 0, LOAD, v4si)
3240 VAR1 (STORE1_U, st1, 0, STORE, v4si)
3241 return Uint32x4_t;
3242 VAR1 (LOAD1_U, ld1, 0, LOAD, v2di)
3243 VAR1 (STORE1_U, st1, 0, STORE, v2di)
3244 return Uint64x2_t;
3245 VAR1 (LOAD1_P, ld1, 0, LOAD, v8qi)
3246 VAR1 (STORE1_P, st1, 0, STORE, v8qi)
3247 return Poly8x8_t;
3248 VAR1 (LOAD1_P, ld1, 0, LOAD, v16qi)
3249 VAR1 (STORE1_P, st1, 0, STORE, v16qi)
3250 return Poly8x16_t;
3251 VAR1 (LOAD1_P, ld1, 0, LOAD, v4hi)
3252 VAR1 (STORE1_P, st1, 0, STORE, v4hi)
3253 return Poly16x4_t;
3254 VAR1 (LOAD1_P, ld1, 0, LOAD, v8hi)
3255 VAR1 (STORE1_P, st1, 0, STORE, v8hi)
3256 return Poly16x8_t;
3257 VAR1 (LOAD1_P, ld1, 0, LOAD, v2di)
3258 VAR1 (STORE1_P, st1, 0, STORE, v2di)
3259 return Poly64x2_t;
3260 VAR1 (LOAD1, ld1, 0, LOAD, v4hf)
3261 VAR1 (STORE1, st1, 0, STORE, v4hf)
ad44c6a5 3262 return Float16x4_t;
1716ddd1
JW
3263 VAR1 (LOAD1, ld1, 0, LOAD, v8hf)
3264 VAR1 (STORE1, st1, 0, STORE, v8hf)
ad44c6a5 3265 return Float16x8_t;
1716ddd1
JW
3266 VAR1 (LOAD1, ld1, 0, LOAD, v4bf)
3267 VAR1 (STORE1, st1, 0, STORE, v4bf)
ad44c6a5 3268 return Bfloat16x4_t;
1716ddd1
JW
3269 VAR1 (LOAD1, ld1, 0, LOAD, v8bf)
3270 VAR1 (STORE1, st1, 0, STORE, v8bf)
ad44c6a5 3271 return Bfloat16x8_t;
1716ddd1
JW
3272 VAR1 (LOAD1, ld1, 0, LOAD, v2sf)
3273 VAR1 (STORE1, st1, 0, STORE, v2sf)
ad44c6a5 3274 return Float32x2_t;
1716ddd1
JW
3275 VAR1 (LOAD1, ld1, 0, LOAD, v4sf)
3276 VAR1 (STORE1, st1, 0, STORE, v4sf)
ad44c6a5 3277 return Float32x4_t;
1716ddd1
JW
3278 VAR1 (LOAD1, ld1, 0, LOAD, v2df)
3279 VAR1 (STORE1, st1, 0, STORE, v2df)
ad44c6a5
ASDV
3280 return Float64x2_t;
3281 default:
3282 gcc_unreachable ();
3283 break;
3284 }
3285}
3286
fcb41156
RS
3287/* We've seen a vector load from address ADDR. Record it in
3288 vector_load_decls, if appropriate. */
3289static void
3290aarch64_record_vector_load_arg (tree addr)
3291{
3292 tree decl = aarch64_vector_load_decl (addr);
3293 if (!decl)
3294 return;
3295 if (!cfun->machine->vector_load_decls)
3296 cfun->machine->vector_load_decls = hash_set<tree>::create_ggc (31);
3297 cfun->machine->vector_load_decls->add (decl);
3298}
3299
6d4d616a
RS
3300/* Try to fold STMT, given that it's a call to the built-in function with
3301 subcode FCODE. Return the new statement on success and null on
3302 failure. */
3303gimple *
ad44c6a5 3304aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt,
03f7843c 3305 gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED)
0ac198d3 3306{
355fe088 3307 gimple *new_stmt = NULL;
6d4d616a
RS
3308 unsigned nargs = gimple_call_num_args (stmt);
3309 tree *args = (nargs > 0
3310 ? gimple_call_arg_ptr (stmt, 0)
3311 : &error_mark_node);
3312
3313 /* We use gimple's IFN_REDUC_(PLUS|MIN|MAX)s for float, signed int
3314 and unsigned int; it will distinguish according to the types of
3315 the arguments to the __builtin. */
3316 switch (fcode)
0ac198d3 3317 {
bf592b2f 3318 BUILTIN_VALL (UNOP, reduc_plus_scal_, 10, ALL)
6be5d852 3319 BUILTIN_VDQ_I (UNOPU, reduc_plus_scal_, 10, NONE)
6d4d616a
RS
3320 new_stmt = gimple_build_call_internal (IFN_REDUC_PLUS,
3321 1, args[0]);
3322 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
3323 break;
ad44c6a5 3324
cbcf4a50
AP
3325 /* Lower sqrt builtins to gimple/internal function sqrt. */
3326 BUILTIN_VHSDF_DF (UNOP, sqrt, 2, FP)
3327 new_stmt = gimple_build_call_internal (IFN_SQRT,
3328 1, args[0]);
3329 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
3330 break;
3331
8a1e05b7
AC
3332 BUILTIN_VDC (BINOP, combine, 0, AUTO_FP)
3333 BUILTIN_VD_I (BINOPU, combine, 0, NONE)
3334 BUILTIN_VDC_P (BINOPP, combine, 0, NONE)
3335 {
3336 tree first_part, second_part;
3337 if (BYTES_BIG_ENDIAN)
3338 {
3339 second_part = args[0];
3340 first_part = args[1];
3341 }
3342 else
3343 {
3344 first_part = args[0];
3345 second_part = args[1];
3346 }
3347 tree ret_type = gimple_call_return_type (stmt);
3348 tree ctor = build_constructor_va (ret_type, 2, NULL_TREE, first_part,
3349 NULL_TREE, second_part);
3350 new_stmt = gimple_build_assign (gimple_call_lhs (stmt), ctor);
3351 }
3352 break;
3353
ad44c6a5
ASDV
3354 /*lower store and load neon builtins to gimple. */
3355 BUILTIN_VALL_F16 (LOAD1, ld1, 0, LOAD)
1716ddd1
JW
3356 BUILTIN_VDQ_I (LOAD1_U, ld1, 0, LOAD)
3357 BUILTIN_VALLP_NO_DI (LOAD1_P, ld1, 0, LOAD)
fcb41156
RS
3358 /* Punt until after inlining, so that we stand more chance of
3359 recording something meaningful in vector_load_decls. */
3360 if (!cfun->after_inlining)
3361 break;
3362 aarch64_record_vector_load_arg (args[0]);
ad44c6a5
ASDV
3363 if (!BYTES_BIG_ENDIAN)
3364 {
3365 enum aarch64_simd_type mem_type
3366 = get_mem_type_for_load_store(fcode);
3367 aarch64_simd_type_info simd_type
3368 = aarch64_simd_types[mem_type];
0f685601
AV
3369 tree elt_ptr_type = build_pointer_type_for_mode (simd_type.eltype,
3370 VOIDmode, true);
ad44c6a5 3371 tree zero = build_zero_cst (elt_ptr_type);
0f685601
AV
3372 /* Use element type alignment. */
3373 tree access_type
3374 = build_aligned_type (simd_type.itype,
3375 TYPE_ALIGN (simd_type.eltype));
ad44c6a5
ASDV
3376 new_stmt
3377 = gimple_build_assign (gimple_get_lhs (stmt),
3378 fold_build2 (MEM_REF,
0f685601
AV
3379 access_type,
3380 args[0], zero));
fcb41156
RS
3381 gimple_set_vuse (new_stmt, gimple_vuse (stmt));
3382 gimple_set_vdef (new_stmt, gimple_vdef (stmt));
ad44c6a5
ASDV
3383 }
3384 break;
3385
3386 BUILTIN_VALL_F16 (STORE1, st1, 0, STORE)
1716ddd1
JW
3387 BUILTIN_VDQ_I (STORE1_U, st1, 0, STORE)
3388 BUILTIN_VALLP_NO_DI (STORE1_P, st1, 0, STORE)
ad44c6a5
ASDV
3389 if (!BYTES_BIG_ENDIAN)
3390 {
3391 enum aarch64_simd_type mem_type
3392 = get_mem_type_for_load_store(fcode);
3393 aarch64_simd_type_info simd_type
3394 = aarch64_simd_types[mem_type];
0f685601
AV
3395 tree elt_ptr_type = build_pointer_type_for_mode (simd_type.eltype,
3396 VOIDmode, true);
ad44c6a5 3397 tree zero = build_zero_cst (elt_ptr_type);
0f685601
AV
3398 /* Use element type alignment. */
3399 tree access_type
3400 = build_aligned_type (simd_type.itype,
3401 TYPE_ALIGN (simd_type.eltype));
ad44c6a5 3402 new_stmt
0f685601
AV
3403 = gimple_build_assign (fold_build2 (MEM_REF, access_type,
3404 args[0], zero),
3405 args[1]);
fcb41156
RS
3406 gimple_set_vuse (new_stmt, gimple_vuse (stmt));
3407 gimple_set_vdef (new_stmt, gimple_vdef (stmt));
ad44c6a5
ASDV
3408 }
3409 break;
3410
bf592b2f 3411 BUILTIN_VDQIF (UNOP, reduc_smax_scal_, 10, ALL)
3412 BUILTIN_VDQ_BHSI (UNOPU, reduc_umax_scal_, 10, ALL)
6d4d616a
RS
3413 new_stmt = gimple_build_call_internal (IFN_REDUC_MAX,
3414 1, args[0]);
3415 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
3416 break;
bf592b2f 3417 BUILTIN_VDQIF (UNOP, reduc_smin_scal_, 10, ALL)
3418 BUILTIN_VDQ_BHSI (UNOPU, reduc_umin_scal_, 10, ALL)
6d4d616a
RS
3419 new_stmt = gimple_build_call_internal (IFN_REDUC_MIN,
3420 1, args[0]);
3421 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
3422 break;
1b4a6359
TC
3423 BUILTIN_VSDQ_I_DI (BINOP, ashl, 3, NONE)
3424 if (TREE_CODE (args[1]) == INTEGER_CST
3425 && wi::ltu_p (wi::to_wide (args[1]), element_precision (args[0])))
3426 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3427 LSHIFT_EXPR, args[0], args[1]);
3428 break;
3429 BUILTIN_VSDQ_I_DI (BINOP, sshl, 0, NONE)
3430 BUILTIN_VSDQ_I_DI (BINOP_UUS, ushl, 0, NONE)
3431 {
3432 tree cst = args[1];
3433 tree ctype = TREE_TYPE (cst);
3434 /* Left shifts can be both scalar or vector, e.g. uint64x1_t is
3435 treated as a scalar type not a vector one. */
3436 if ((cst = uniform_integer_cst_p (cst)) != NULL_TREE)
3437 {
3438 wide_int wcst = wi::to_wide (cst);
3439 tree unit_ty = TREE_TYPE (cst);
3440
3441 wide_int abs_cst = wi::abs (wcst);
3442 if (wi::geu_p (abs_cst, element_precision (args[0])))
3443 break;
3444
3445 if (wi::neg_p (wcst, TYPE_SIGN (ctype)))
3446 {
3447 tree final_cst;
3448 final_cst = wide_int_to_tree (unit_ty, abs_cst);
3449 if (TREE_CODE (cst) != INTEGER_CST)
3450 final_cst = build_uniform_cst (ctype, final_cst);
3451
3452 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3453 RSHIFT_EXPR, args[0],
3454 final_cst);
3455 }
3456 else
3457 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3458 LSHIFT_EXPR, args[0], args[1]);
3459 }
3460 }
3461 break;
3462 BUILTIN_VDQ_I (SHIFTIMM, ashr, 3, NONE)
3463 VAR1 (SHIFTIMM, ashr_simd, 0, NONE, di)
3464 BUILTIN_VDQ_I (USHIFTIMM, lshr, 3, NONE)
3465 VAR1 (USHIFTIMM, lshr_simd, 0, NONE, di)
3466 if (TREE_CODE (args[1]) == INTEGER_CST
3467 && wi::ltu_p (wi::to_wide (args[1]), element_precision (args[0])))
3468 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3469 RSHIFT_EXPR, args[0], args[1]);
3470 break;
bf592b2f 3471 BUILTIN_GPF (BINOP, fmulx, 0, ALL)
0ac198d3 3472 {
6d4d616a
RS
3473 gcc_assert (nargs == 2);
3474 bool a0_cst_p = TREE_CODE (args[0]) == REAL_CST;
3475 bool a1_cst_p = TREE_CODE (args[1]) == REAL_CST;
3476 if (a0_cst_p || a1_cst_p)
0ac198d3 3477 {
6d4d616a 3478 if (a0_cst_p && a1_cst_p)
546e500c 3479 {
6d4d616a
RS
3480 tree t0 = TREE_TYPE (args[0]);
3481 real_value a0 = (TREE_REAL_CST (args[0]));
3482 real_value a1 = (TREE_REAL_CST (args[1]));
3483 if (real_equal (&a1, &dconst0))
3484 std::swap (a0, a1);
3485 /* According to real_equal (), +0 equals -0. */
3486 if (real_equal (&a0, &dconst0) && real_isinf (&a1))
546e500c 3487 {
6d4d616a
RS
3488 real_value res = dconst2;
3489 res.sign = a0.sign ^ a1.sign;
3490 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3491 REAL_CST,
3492 build_real (t0, res));
546e500c 3493 }
6d4d616a
RS
3494 else
3495 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3496 MULT_EXPR,
3497 args[0], args[1]);
546e500c 3498 }
6d4d616a
RS
3499 else /* a0_cst_p ^ a1_cst_p. */
3500 {
3501 real_value const_part = a0_cst_p
3502 ? TREE_REAL_CST (args[0]) : TREE_REAL_CST (args[1]);
3503 if (!real_equal (&const_part, &dconst0)
3504 && !real_isinf (&const_part))
3505 new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3506 MULT_EXPR, args[0],
3507 args[1]);
3508 }
3509 }
3510 if (new_stmt)
3511 {
3512 gimple_set_vuse (new_stmt, gimple_vuse (stmt));
3513 gimple_set_vdef (new_stmt, gimple_vdef (stmt));
0ac198d3 3514 }
6d4d616a 3515 break;
0ac198d3 3516 }
03312cbd
AP
3517 case AARCH64_SIMD_BUILTIN_LANE_CHECK:
3518 if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
3519 {
3520 unlink_stmt_vdef (stmt);
3521 release_defs (stmt);
3522 new_stmt = gimple_build_nop ();
3523 }
3524 break;
6d4d616a
RS
3525 default:
3526 break;
0ac198d3 3527 }
e9cad1e5
AC
3528
3529 /* GIMPLE assign statements (unlike calls) require a non-null lhs. If we
3530 created an assign statement with a null lhs, then fix this by assigning
3531 to a new (and subsequently unused) variable. */
3532 if (new_stmt && is_gimple_assign (new_stmt) && !gimple_assign_lhs (new_stmt))
3533 {
3534 tree new_lhs = make_ssa_name (gimple_call_return_type (stmt));
3535 gimple_assign_set_lhs (new_stmt, new_lhs);
3536 }
3537
6d4d616a 3538 return new_stmt;
0ac198d3
JG
3539}
3540
aa87aced
KV
3541void
3542aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
3543{
3544 const unsigned AARCH64_FE_INVALID = 1;
3545 const unsigned AARCH64_FE_DIVBYZERO = 2;
3546 const unsigned AARCH64_FE_OVERFLOW = 4;
3547 const unsigned AARCH64_FE_UNDERFLOW = 8;
3548 const unsigned AARCH64_FE_INEXACT = 16;
3549 const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID
3550 | AARCH64_FE_DIVBYZERO
3551 | AARCH64_FE_OVERFLOW
3552 | AARCH64_FE_UNDERFLOW
3553 | AARCH64_FE_INEXACT);
3554 const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8;
3555 tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr;
3556 tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr;
3557 tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr;
3558 tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv;
3559
3560 /* Generate the equivalence of :
3561 unsigned int fenv_cr;
3562 fenv_cr = __builtin_aarch64_get_fpcr ();
3563
3564 unsigned int fenv_sr;
3565 fenv_sr = __builtin_aarch64_get_fpsr ();
3566
3567 Now set all exceptions to non-stop
3568 unsigned int mask_cr
3569 = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
3570 unsigned int masked_cr;
3571 masked_cr = fenv_cr & mask_cr;
3572
3573 And clear all exception flags
3574 unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
3575 unsigned int masked_cr;
3576 masked_sr = fenv_sr & mask_sr;
3577
3578 __builtin_aarch64_set_cr (masked_cr);
3579 __builtin_aarch64_set_sr (masked_sr); */
3580
09ba9ef7
RR
3581 fenv_cr = create_tmp_var_raw (unsigned_type_node);
3582 fenv_sr = create_tmp_var_raw (unsigned_type_node);
aa87aced
KV
3583
3584 get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR];
3585 set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR];
3586 get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR];
3587 set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR];
3588
3589 mask_cr = build_int_cst (unsigned_type_node,
3590 ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT));
3591 mask_sr = build_int_cst (unsigned_type_node,
3592 ~(AARCH64_FE_ALL_EXCEPT));
3593
d81bc2af
HZ
3594 ld_fenv_cr = build4 (TARGET_EXPR, unsigned_type_node,
3595 fenv_cr, build_call_expr (get_fpcr, 0),
3596 NULL_TREE, NULL_TREE);
3597 ld_fenv_sr = build4 (TARGET_EXPR, unsigned_type_node,
3598 fenv_sr, build_call_expr (get_fpsr, 0),
3599 NULL_TREE, NULL_TREE);
aa87aced
KV
3600
3601 masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr);
3602 masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr);
3603
3604 hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr);
3605 hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr);
3606
3607 hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr,
3608 hold_fnclex_sr);
3609 masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr,
3610 masked_fenv_sr);
3611 ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr);
3612
3613 *hold = build2 (COMPOUND_EXPR, void_type_node,
3614 build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
3615 hold_fnclex);
3616
3617 /* Store the value of masked_fenv to clear the exceptions:
3618 __builtin_aarch64_set_fpsr (masked_fenv_sr); */
3619
3620 *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr);
3621
3622 /* Generate the equivalent of :
3623 unsigned int new_fenv_var;
3624 new_fenv_var = __builtin_aarch64_get_fpsr ();
3625
3626 __builtin_aarch64_set_fpsr (fenv_sr);
3627
3628 __atomic_feraiseexcept (new_fenv_var); */
3629
09ba9ef7 3630 new_fenv_var = create_tmp_var_raw (unsigned_type_node);
d81bc2af
HZ
3631 reload_fenv = build4 (TARGET_EXPR, unsigned_type_node,
3632 new_fenv_var, build_call_expr (get_fpsr, 0),
3633 NULL_TREE, NULL_TREE);
aa87aced
KV
3634 restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr);
3635 atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
3636 update_call = build_call_expr (atomic_feraiseexcept, 1,
3637 fold_convert (integer_type_node, new_fenv_var));
3638 *update = build2 (COMPOUND_EXPR, void_type_node,
3639 build2 (COMPOUND_EXPR, void_type_node,
3640 reload_fenv, restore_fnenv), update_call);
3641}
3642
ef01e6bb
DZ
3643/* Resolve overloaded MEMTAG build-in functions. */
3644#define AARCH64_BUILTIN_SUBCODE(F) \
3645 (DECL_MD_FUNCTION_CODE (F) >> AARCH64_BUILTIN_SHIFT)
3646
3647static tree
3648aarch64_resolve_overloaded_memtag (location_t loc,
3649 tree fndecl, void *pass_params)
3650{
3651 vec<tree, va_gc> *params = static_cast<vec<tree, va_gc> *> (pass_params);
3652 unsigned param_num = params ? params->length() : 0;
3653 unsigned int fcode = AARCH64_BUILTIN_SUBCODE (fndecl);
3654 tree inittype = aarch64_memtag_builtin_data[
3655 fcode - AARCH64_MEMTAG_BUILTIN_START - 1].ftype;
3656 unsigned arg_num = list_length (TYPE_ARG_TYPES (inittype)) - 1;
3657
3658 if (param_num != arg_num)
3659 {
3660 TREE_TYPE (fndecl) = inittype;
3661 return NULL_TREE;
3662 }
3663 tree retype = NULL;
3664
3665 if (fcode == AARCH64_MEMTAG_BUILTIN_SUBP)
3666 {
3667 tree t0 = TREE_TYPE ((*params)[0]);
3668 tree t1 = TREE_TYPE ((*params)[1]);
3669
3670 if (t0 == error_mark_node || TREE_CODE (t0) != POINTER_TYPE)
3671 t0 = ptr_type_node;
3672 if (t1 == error_mark_node || TREE_CODE (t1) != POINTER_TYPE)
3673 t1 = ptr_type_node;
3674
3675 if (TYPE_MODE (t0) != DImode)
3676 warning_at (loc, 1, "expected 64-bit address but argument 1 is %d-bit",
3677 (int)tree_to_shwi (DECL_SIZE ((*params)[0])));
3678
3679 if (TYPE_MODE (t1) != DImode)
3680 warning_at (loc, 1, "expected 64-bit address but argument 2 is %d-bit",
3681 (int)tree_to_shwi (DECL_SIZE ((*params)[1])));
3682
3683 retype = build_function_type_list (ptrdiff_type_node, t0, t1, NULL);
3684 }
3685 else
3686 {
3687 tree t0 = TREE_TYPE ((*params)[0]);
3688
3689 if (t0 == error_mark_node || TREE_CODE (t0) != POINTER_TYPE)
3690 {
3691 TREE_TYPE (fndecl) = inittype;
3692 return NULL_TREE;
3693 }
3694
3695 if (TYPE_MODE (t0) != DImode)
3696 warning_at (loc, 1, "expected 64-bit address but argument 1 is %d-bit",
3697 (int)tree_to_shwi (DECL_SIZE ((*params)[0])));
3698
3699 switch (fcode)
3700 {
3701 case AARCH64_MEMTAG_BUILTIN_IRG:
3702 retype = build_function_type_list (t0, t0, uint64_type_node, NULL);
3703 break;
3704 case AARCH64_MEMTAG_BUILTIN_GMI:
3705 retype = build_function_type_list (uint64_type_node, t0,
3706 uint64_type_node, NULL);
3707 break;
3708 case AARCH64_MEMTAG_BUILTIN_INC_TAG:
3709 retype = build_function_type_list (t0, t0, unsigned_type_node, NULL);
3710 break;
3711 case AARCH64_MEMTAG_BUILTIN_SET_TAG:
3712 retype = build_function_type_list (void_type_node, t0, NULL);
3713 break;
3714 case AARCH64_MEMTAG_BUILTIN_GET_TAG:
3715 retype = build_function_type_list (t0, t0, NULL);
3716 break;
3717 default:
3718 return NULL_TREE;
3719 }
3720 }
3721
3722 if (!retype || retype == error_mark_node)
3723 TREE_TYPE (fndecl) = inittype;
3724 else
3725 TREE_TYPE (fndecl) = retype;
3726
3727 return NULL_TREE;
3728}
3729
e53b6e56 3730/* Called at aarch64_resolve_overloaded_builtin in aarch64-c.cc. */
ef01e6bb
DZ
3731tree
3732aarch64_resolve_overloaded_builtin_general (location_t loc, tree function,
3733 void *pass_params)
3734{
3735 unsigned int fcode = AARCH64_BUILTIN_SUBCODE (function);
3736
3737 if (fcode >= AARCH64_MEMTAG_BUILTIN_START
3738 && fcode <= AARCH64_MEMTAG_BUILTIN_END)
3739 return aarch64_resolve_overloaded_memtag(loc, function, pass_params);
3740
3741 return NULL_TREE;
3742}
aa87aced 3743
42fc9a7f
JG
3744#undef AARCH64_CHECK_BUILTIN_MODE
3745#undef AARCH64_FIND_FRINT_VARIANT
0ddec79f
JG
3746#undef CF0
3747#undef CF1
3748#undef CF2
3749#undef CF3
3750#undef CF4
3751#undef CF10
3752#undef VAR1
3753#undef VAR2
3754#undef VAR3
3755#undef VAR4
3756#undef VAR5
3757#undef VAR6
3758#undef VAR7
3759#undef VAR8
3760#undef VAR9
3761#undef VAR10
3762#undef VAR11
3763
3c03d39d 3764#include "gt-aarch64-builtins.h"