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