]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/aarch64/aarch64-builtins.c
[AArch64] Rework interface to add constant/offset routines
[thirdparty/gcc.git] / gcc / config / aarch64 / aarch64-builtins.c
CommitLineData
43e9d192 1/* Builtins' description for AArch64 SIMD architecture.
85ec4feb 2 Copyright (C) 2011-2018 Free Software Foundation, Inc.
43e9d192
IB
3 Contributed by ARM Ltd.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
8fcc61f8
RS
21#define IN_TARGET_CODE 1
22
43e9d192
IB
23#include "config.h"
24#include "system.h"
25#include "coretypes.h"
26#include "tm.h"
c7131fb2 27#include "function.h"
c7131fb2 28#include "basic-block.h"
e11c4407 29#include "rtl.h"
c7131fb2
AM
30#include "tree.h"
31#include "gimple.h"
4d0cdd0c 32#include "memmodel.h"
e11c4407
AM
33#include "tm_p.h"
34#include "expmed.h"
35#include "optabs.h"
36#include "recog.h"
37#include "diagnostic-core.h"
40e23961 38#include "fold-const.h"
d8a2d370 39#include "stor-layout.h"
36566b39 40#include "explow.h"
43e9d192 41#include "expr.h"
43e9d192 42#include "langhooks.h"
5be5c238 43#include "gimple-iterator.h"
10766209 44#include "case-cfn-macros.h"
43e9d192 45
0d4a1197
RS
46#define v8qi_UP E_V8QImode
47#define v4hi_UP E_V4HImode
48#define v4hf_UP E_V4HFmode
49#define v2si_UP E_V2SImode
50#define v2sf_UP E_V2SFmode
51#define v1df_UP E_V1DFmode
52#define di_UP E_DImode
53#define df_UP E_DFmode
54#define v16qi_UP E_V16QImode
55#define v8hi_UP E_V8HImode
56#define v8hf_UP E_V8HFmode
57#define v4si_UP E_V4SImode
58#define v4sf_UP E_V4SFmode
59#define v2di_UP E_V2DImode
60#define v2df_UP E_V2DFmode
61#define ti_UP E_TImode
62#define oi_UP E_OImode
63#define ci_UP E_CImode
64#define xi_UP E_XImode
65#define si_UP E_SImode
66#define sf_UP E_SFmode
67#define hi_UP E_HImode
68#define hf_UP E_HFmode
69#define qi_UP E_QImode
43e9d192
IB
70#define UP(X) X##_UP
71
b5828b4b
JG
72#define SIMD_MAX_BUILTIN_ARGS 5
73
74enum aarch64_type_qualifiers
43e9d192 75{
b5828b4b
JG
76 /* T foo. */
77 qualifier_none = 0x0,
78 /* unsigned T foo. */
79 qualifier_unsigned = 0x1, /* 1 << 0 */
80 /* const T foo. */
81 qualifier_const = 0x2, /* 1 << 1 */
82 /* T *foo. */
83 qualifier_pointer = 0x4, /* 1 << 2 */
b5828b4b
JG
84 /* Used when expanding arguments if an operand could
85 be an immediate. */
86 qualifier_immediate = 0x8, /* 1 << 3 */
87 qualifier_maybe_immediate = 0x10, /* 1 << 4 */
88 /* void foo (...). */
89 qualifier_void = 0x20, /* 1 << 5 */
90 /* Some patterns may have internal operands, this qualifier is an
91 instruction to the initialisation code to skip this operand. */
92 qualifier_internal = 0x40, /* 1 << 6 */
93 /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
94 rather than using the type of the operand. */
95 qualifier_map_mode = 0x80, /* 1 << 7 */
96 /* qualifier_pointer | qualifier_map_mode */
97 qualifier_pointer_map_mode = 0x84,
e625e715 98 /* qualifier_const | qualifier_pointer | qualifier_map_mode */
6db1ec94
JG
99 qualifier_const_pointer_map_mode = 0x86,
100 /* Polynomial types. */
2a49c16d
AL
101 qualifier_poly = 0x100,
102 /* Lane indices - must be in range, and flipped for bigendian. */
4d0a0237
CB
103 qualifier_lane_index = 0x200,
104 /* Lane indices for single lane structure loads and stores. */
105 qualifier_struct_load_store_lane_index = 0x400
b5828b4b 106};
43e9d192
IB
107
108typedef struct
109{
110 const char *name;
ef4bddc2 111 machine_mode mode;
342be7f7
JG
112 const enum insn_code code;
113 unsigned int fcode;
b5828b4b 114 enum aarch64_type_qualifiers *qualifiers;
43e9d192
IB
115} aarch64_simd_builtin_datum;
116
b5828b4b
JG
117static enum aarch64_type_qualifiers
118aarch64_types_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
8f905d69 119 = { qualifier_none, qualifier_none };
b5828b4b 120#define TYPES_UNOP (aarch64_types_unop_qualifiers)
5a7a4e80
TB
121static enum aarch64_type_qualifiers
122aarch64_types_unopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
123 = { qualifier_unsigned, qualifier_unsigned };
124#define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
b5828b4b 125static enum aarch64_type_qualifiers
a579f4c7
JW
126aarch64_types_unopus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
127 = { qualifier_unsigned, qualifier_none };
128#define TYPES_UNOPUS (aarch64_types_unopus_qualifiers)
129static enum aarch64_type_qualifiers
b5828b4b
JG
130aarch64_types_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
131 = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
132#define TYPES_BINOP (aarch64_types_binop_qualifiers)
133static enum aarch64_type_qualifiers
5a7a4e80
TB
134aarch64_types_binopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
135 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
136#define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
7baa225d 137static enum aarch64_type_qualifiers
de10bcce
AL
138aarch64_types_binop_uus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
139 = { qualifier_unsigned, qualifier_unsigned, qualifier_none };
140#define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
141static enum aarch64_type_qualifiers
918621d3
AL
142aarch64_types_binop_ssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
143 = { qualifier_none, qualifier_none, qualifier_unsigned };
144#define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
145static enum aarch64_type_qualifiers
daef0a8c
JW
146aarch64_types_binop_uss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
147 = { qualifier_unsigned, qualifier_none, qualifier_none };
148#define TYPES_BINOP_USS (aarch64_types_binop_uss_qualifiers)
149static enum aarch64_type_qualifiers
7baa225d
TB
150aarch64_types_binopp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
151 = { qualifier_poly, qualifier_poly, qualifier_poly };
152#define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
153
5a7a4e80 154static enum aarch64_type_qualifiers
b5828b4b
JG
155aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
156 = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
157#define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
30442682 158static enum aarch64_type_qualifiers
2a49c16d
AL
159aarch64_types_ternop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
160 = { qualifier_none, qualifier_none, qualifier_none, qualifier_lane_index };
161#define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
162static enum aarch64_type_qualifiers
30442682
TB
163aarch64_types_ternopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
164 = { qualifier_unsigned, qualifier_unsigned,
165 qualifier_unsigned, qualifier_unsigned };
166#define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
27086ea3
MC
167static enum aarch64_type_qualifiers
168aarch64_types_ternopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
169 = { qualifier_unsigned, qualifier_unsigned,
170 qualifier_unsigned, qualifier_immediate };
171#define TYPES_TERNOPUI (aarch64_types_ternopu_imm_qualifiers)
172
30442682 173
b5828b4b 174static enum aarch64_type_qualifiers
2a49c16d 175aarch64_types_quadop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
b5828b4b 176 = { qualifier_none, qualifier_none, qualifier_none,
2a49c16d
AL
177 qualifier_none, qualifier_lane_index };
178#define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
7a08d813
TC
179static enum aarch64_type_qualifiers
180aarch64_types_quadopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
181 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
182 qualifier_unsigned, qualifier_lane_index };
183#define TYPES_QUADOPU_LANE (aarch64_types_quadopu_lane_qualifiers)
b5828b4b 184
27086ea3
MC
185static enum aarch64_type_qualifiers
186aarch64_types_quadopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
187 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
188 qualifier_unsigned, qualifier_immediate };
189#define TYPES_QUADOPUI (aarch64_types_quadopu_imm_qualifiers)
190
159b8724
TC
191static enum aarch64_type_qualifiers
192aarch64_types_binop_imm_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
193 = { qualifier_poly, qualifier_none, qualifier_immediate };
194#define TYPES_GETREGP (aarch64_types_binop_imm_p_qualifiers)
b5828b4b 195static enum aarch64_type_qualifiers
2a49c16d 196aarch64_types_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
b5828b4b 197 = { qualifier_none, qualifier_none, qualifier_immediate };
2a49c16d
AL
198#define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
199#define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
b5828b4b 200static enum aarch64_type_qualifiers
de10bcce
AL
201aarch64_types_shift_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
202 = { qualifier_unsigned, qualifier_none, qualifier_immediate };
203#define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
204static enum aarch64_type_qualifiers
1f0e9e34
JG
205aarch64_types_fcvt_from_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
206 = { qualifier_none, qualifier_unsigned, qualifier_immediate };
207#define TYPES_FCVTIMM_SUS (aarch64_types_fcvt_from_unsigned_qualifiers)
208static enum aarch64_type_qualifiers
252c7556
AV
209aarch64_types_unsigned_shift_qualifiers[SIMD_MAX_BUILTIN_ARGS]
210 = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate };
211#define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
de10bcce 212
252c7556 213static enum aarch64_type_qualifiers
159b8724
TC
214aarch64_types_ternop_s_imm_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
215 = { qualifier_none, qualifier_none, qualifier_poly, qualifier_immediate};
216#define TYPES_SETREGP (aarch64_types_ternop_s_imm_p_qualifiers)
217static enum aarch64_type_qualifiers
218aarch64_types_ternop_s_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
219 = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate};
220#define TYPES_SETREG (aarch64_types_ternop_s_imm_qualifiers)
221#define TYPES_SHIFTINSERT (aarch64_types_ternop_s_imm_qualifiers)
222#define TYPES_SHIFTACC (aarch64_types_ternop_s_imm_qualifiers)
223
224static enum aarch64_type_qualifiers
225aarch64_types_ternop_p_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
226 = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_immediate};
227#define TYPES_SHIFTINSERTP (aarch64_types_ternop_p_imm_qualifiers)
b5828b4b 228
de10bcce
AL
229static enum aarch64_type_qualifiers
230aarch64_types_unsigned_shiftacc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
231 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
232 qualifier_immediate };
233#define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
234
235
b5828b4b
JG
236static enum aarch64_type_qualifiers
237aarch64_types_combine_qualifiers[SIMD_MAX_BUILTIN_ARGS]
238 = { qualifier_none, qualifier_none, qualifier_none };
239#define TYPES_COMBINE (aarch64_types_combine_qualifiers)
240
159b8724
TC
241static enum aarch64_type_qualifiers
242aarch64_types_combine_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
243 = { qualifier_poly, qualifier_poly, qualifier_poly };
244#define TYPES_COMBINEP (aarch64_types_combine_p_qualifiers)
245
b5828b4b
JG
246static enum aarch64_type_qualifiers
247aarch64_types_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
248 = { qualifier_none, qualifier_const_pointer_map_mode };
249#define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
250#define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
3ec1be97
CB
251static enum aarch64_type_qualifiers
252aarch64_types_loadstruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
253 = { qualifier_none, qualifier_const_pointer_map_mode,
4d0a0237 254 qualifier_none, qualifier_struct_load_store_lane_index };
3ec1be97 255#define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
b5828b4b 256
46e778c4
JG
257static enum aarch64_type_qualifiers
258aarch64_types_bsl_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
259 = { qualifier_poly, qualifier_unsigned,
260 qualifier_poly, qualifier_poly };
261#define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
262static enum aarch64_type_qualifiers
263aarch64_types_bsl_s_qualifiers[SIMD_MAX_BUILTIN_ARGS]
264 = { qualifier_none, qualifier_unsigned,
265 qualifier_none, qualifier_none };
266#define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
267static enum aarch64_type_qualifiers
268aarch64_types_bsl_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
269 = { qualifier_unsigned, qualifier_unsigned,
270 qualifier_unsigned, qualifier_unsigned };
271#define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
272
b5828b4b
JG
273/* The first argument (return type) of a store should be void type,
274 which we represent with qualifier_void. Their first operand will be
275 a DImode pointer to the location to store to, so we must use
276 qualifier_map_mode | qualifier_pointer to build a pointer to the
277 element type of the vector. */
278static enum aarch64_type_qualifiers
159b8724
TC
279aarch64_types_store1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
280 = { qualifier_void, qualifier_pointer_map_mode, qualifier_poly };
281#define TYPES_STORE1P (aarch64_types_store1_p_qualifiers)
282static enum aarch64_type_qualifiers
b5828b4b
JG
283aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
284 = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
285#define TYPES_STORE1 (aarch64_types_store1_qualifiers)
286#define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
ba081b77
JG
287static enum aarch64_type_qualifiers
288aarch64_types_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
289 = { qualifier_void, qualifier_pointer_map_mode,
4d0a0237 290 qualifier_none, qualifier_struct_load_store_lane_index };
ba081b77 291#define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
b5828b4b 292
0ddec79f
JG
293#define CF0(N, X) CODE_FOR_aarch64_##N##X
294#define CF1(N, X) CODE_FOR_##N##X##1
295#define CF2(N, X) CODE_FOR_##N##X##2
296#define CF3(N, X) CODE_FOR_##N##X##3
297#define CF4(N, X) CODE_FOR_##N##X##4
298#define CF10(N, X) CODE_FOR_##N##X
299
300#define VAR1(T, N, MAP, A) \
bc5e395d 301 {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T},
0ddec79f
JG
302#define VAR2(T, N, MAP, A, B) \
303 VAR1 (T, N, MAP, A) \
304 VAR1 (T, N, MAP, B)
305#define VAR3(T, N, MAP, A, B, C) \
306 VAR2 (T, N, MAP, A, B) \
307 VAR1 (T, N, MAP, C)
308#define VAR4(T, N, MAP, A, B, C, D) \
309 VAR3 (T, N, MAP, A, B, C) \
310 VAR1 (T, N, MAP, D)
311#define VAR5(T, N, MAP, A, B, C, D, E) \
312 VAR4 (T, N, MAP, A, B, C, D) \
313 VAR1 (T, N, MAP, E)
314#define VAR6(T, N, MAP, A, B, C, D, E, F) \
315 VAR5 (T, N, MAP, A, B, C, D, E) \
316 VAR1 (T, N, MAP, F)
317#define VAR7(T, N, MAP, A, B, C, D, E, F, G) \
318 VAR6 (T, N, MAP, A, B, C, D, E, F) \
319 VAR1 (T, N, MAP, G)
320#define VAR8(T, N, MAP, A, B, C, D, E, F, G, H) \
321 VAR7 (T, N, MAP, A, B, C, D, E, F, G) \
322 VAR1 (T, N, MAP, H)
323#define VAR9(T, N, MAP, A, B, C, D, E, F, G, H, I) \
324 VAR8 (T, N, MAP, A, B, C, D, E, F, G, H) \
325 VAR1 (T, N, MAP, I)
326#define VAR10(T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
327 VAR9 (T, N, MAP, A, B, C, D, E, F, G, H, I) \
328 VAR1 (T, N, MAP, J)
329#define VAR11(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
330 VAR10 (T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
331 VAR1 (T, N, MAP, K)
332#define VAR12(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L) \
333 VAR11 (T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
334 VAR1 (T, N, MAP, L)
7c369485
AL
335#define VAR13(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L, M) \
336 VAR12 (T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L) \
337 VAR1 (T, N, MAP, M)
338#define VAR14(T, X, MAP, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
339 VAR13 (T, X, MAP, A, B, C, D, E, F, G, H, I, J, K, L, M) \
340 VAR1 (T, X, MAP, N)
342be7f7 341
f421c516 342#include "aarch64-builtin-iterators.h"
43e9d192
IB
343
344static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
342be7f7
JG
345#include "aarch64-simd-builtins.def"
346};
347
5d357f26
KT
348/* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
349#define AARCH64_CRC32_BUILTINS \
350 CRC32_BUILTIN (crc32b, QI) \
351 CRC32_BUILTIN (crc32h, HI) \
352 CRC32_BUILTIN (crc32w, SI) \
353 CRC32_BUILTIN (crc32x, DI) \
354 CRC32_BUILTIN (crc32cb, QI) \
355 CRC32_BUILTIN (crc32ch, HI) \
356 CRC32_BUILTIN (crc32cw, SI) \
357 CRC32_BUILTIN (crc32cx, DI)
358
359typedef struct
360{
361 const char *name;
ef4bddc2 362 machine_mode mode;
5d357f26
KT
363 const enum insn_code icode;
364 unsigned int fcode;
365} aarch64_crc_builtin_datum;
366
367#define CRC32_BUILTIN(N, M) \
368 AARCH64_BUILTIN_##N,
369
342be7f7 370#undef VAR1
0ddec79f 371#define VAR1(T, N, MAP, A) \
e993fea1 372 AARCH64_SIMD_BUILTIN_##T##_##N##A,
342be7f7
JG
373
374enum aarch64_builtins
375{
376 AARCH64_BUILTIN_MIN,
aa87aced
KV
377
378 AARCH64_BUILTIN_GET_FPCR,
379 AARCH64_BUILTIN_SET_FPCR,
380 AARCH64_BUILTIN_GET_FPSR,
381 AARCH64_BUILTIN_SET_FPSR,
382
a6fc00da
BH
383 AARCH64_BUILTIN_RSQRT_DF,
384 AARCH64_BUILTIN_RSQRT_SF,
385 AARCH64_BUILTIN_RSQRT_V2DF,
386 AARCH64_BUILTIN_RSQRT_V2SF,
387 AARCH64_BUILTIN_RSQRT_V4SF,
342be7f7 388 AARCH64_SIMD_BUILTIN_BASE,
661fce82 389 AARCH64_SIMD_BUILTIN_LANE_CHECK,
342be7f7 390#include "aarch64-simd-builtins.def"
661fce82
AL
391 /* The first enum element which is based on an insn_data pattern. */
392 AARCH64_SIMD_PATTERN_START = AARCH64_SIMD_BUILTIN_LANE_CHECK + 1,
393 AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_PATTERN_START
394 + ARRAY_SIZE (aarch64_simd_builtin_data) - 1,
5d357f26
KT
395 AARCH64_CRC32_BUILTIN_BASE,
396 AARCH64_CRC32_BUILTINS
397 AARCH64_CRC32_BUILTIN_MAX,
312492bd
JW
398 /* ARMv8.3-A Pointer Authentication Builtins. */
399 AARCH64_PAUTH_BUILTIN_AUTIA1716,
400 AARCH64_PAUTH_BUILTIN_PACIA1716,
401 AARCH64_PAUTH_BUILTIN_XPACLRI,
342be7f7 402 AARCH64_BUILTIN_MAX
43e9d192
IB
403};
404
5d357f26
KT
405#undef CRC32_BUILTIN
406#define CRC32_BUILTIN(N, M) \
0d4a1197 407 {"__builtin_aarch64_"#N, E_##M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
5d357f26
KT
408
409static aarch64_crc_builtin_datum aarch64_crc_builtin_data[] = {
410 AARCH64_CRC32_BUILTINS
411};
412
413#undef CRC32_BUILTIN
414
119103ca
JG
415static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX];
416
43e9d192
IB
417#define NUM_DREG_TYPES 6
418#define NUM_QREG_TYPES 6
419
f9d53c27
TB
420/* Internal scalar builtin types. These types are used to support
421 neon intrinsic builtins. They are _not_ user-visible types. Therefore
422 the mangling for these types are implementation defined. */
423const char *aarch64_scalar_builtin_types[] = {
424 "__builtin_aarch64_simd_qi",
425 "__builtin_aarch64_simd_hi",
426 "__builtin_aarch64_simd_si",
7c369485 427 "__builtin_aarch64_simd_hf",
f9d53c27
TB
428 "__builtin_aarch64_simd_sf",
429 "__builtin_aarch64_simd_di",
430 "__builtin_aarch64_simd_df",
431 "__builtin_aarch64_simd_poly8",
432 "__builtin_aarch64_simd_poly16",
433 "__builtin_aarch64_simd_poly64",
434 "__builtin_aarch64_simd_poly128",
435 "__builtin_aarch64_simd_ti",
436 "__builtin_aarch64_simd_uqi",
437 "__builtin_aarch64_simd_uhi",
438 "__builtin_aarch64_simd_usi",
439 "__builtin_aarch64_simd_udi",
440 "__builtin_aarch64_simd_ei",
441 "__builtin_aarch64_simd_oi",
442 "__builtin_aarch64_simd_ci",
443 "__builtin_aarch64_simd_xi",
444 NULL
445};
b5828b4b 446
f9d53c27
TB
447#define ENTRY(E, M, Q, G) E,
448enum aarch64_simd_type
449{
450#include "aarch64-simd-builtin-types.def"
451 ARM_NEON_H_TYPES_LAST
452};
453#undef ENTRY
b5828b4b 454
f9d53c27 455struct aarch64_simd_type_info
b5828b4b 456{
f9d53c27
TB
457 enum aarch64_simd_type type;
458
459 /* Internal type name. */
460 const char *name;
461
462 /* Internal type name(mangled). The mangled names conform to the
463 AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
464 Appendix A). To qualify for emission with the mangled names defined in
465 that document, a vector type must not only be of the correct mode but also
466 be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
467 types are registered by aarch64_init_simd_builtin_types (). In other
468 words, vector types defined in other ways e.g. via vector_size attribute
469 will get default mangled names. */
470 const char *mangle;
471
472 /* Internal type. */
473 tree itype;
474
475 /* Element type. */
b5828b4b
JG
476 tree eltype;
477
f9d53c27
TB
478 /* Machine mode the internal type maps to. */
479 enum machine_mode mode;
b5828b4b 480
f9d53c27
TB
481 /* Qualifiers. */
482 enum aarch64_type_qualifiers q;
483};
484
485#define ENTRY(E, M, Q, G) \
0d4a1197 486 {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, E_##M##mode, qualifier_##Q},
f9d53c27
TB
487static struct aarch64_simd_type_info aarch64_simd_types [] = {
488#include "aarch64-simd-builtin-types.def"
489};
490#undef ENTRY
491
492static tree aarch64_simd_intOI_type_node = NULL_TREE;
f9d53c27
TB
493static tree aarch64_simd_intCI_type_node = NULL_TREE;
494static tree aarch64_simd_intXI_type_node = NULL_TREE;
495
1b62ed4f
JG
496/* The user-visible __fp16 type, and a pointer to that type. Used
497 across the back-end. */
498tree aarch64_fp16_type_node = NULL_TREE;
499tree aarch64_fp16_ptr_type_node = NULL_TREE;
500
f9d53c27
TB
501static const char *
502aarch64_mangle_builtin_scalar_type (const_tree type)
503{
504 int i = 0;
505
506 while (aarch64_scalar_builtin_types[i] != NULL)
b5828b4b 507 {
f9d53c27
TB
508 const char *name = aarch64_scalar_builtin_types[i];
509
510 if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
511 && DECL_NAME (TYPE_NAME (type))
512 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), name))
513 return aarch64_scalar_builtin_types[i];
514 i++;
515 }
516 return NULL;
b5828b4b
JG
517}
518
f9d53c27
TB
519static const char *
520aarch64_mangle_builtin_vector_type (const_tree type)
b5828b4b 521{
f9d53c27
TB
522 int i;
523 int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
524
525 for (i = 0; i < nelts; i++)
526 if (aarch64_simd_types[i].mode == TYPE_MODE (type)
527 && TYPE_NAME (type)
528 && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
529 && DECL_NAME (TYPE_NAME (type))
530 && !strcmp
531 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))),
532 aarch64_simd_types[i].name))
533 return aarch64_simd_types[i].mangle;
534
535 return NULL;
6db1ec94
JG
536}
537
f9d53c27
TB
538const char *
539aarch64_mangle_builtin_type (const_tree type)
6db1ec94 540{
f9d53c27
TB
541 const char *mangle;
542 /* Walk through all the AArch64 builtins types tables to filter out the
543 incoming type. */
544 if ((mangle = aarch64_mangle_builtin_vector_type (type))
545 || (mangle = aarch64_mangle_builtin_scalar_type (type)))
546 return mangle;
547
548 return NULL;
6db1ec94
JG
549}
550
f9d53c27 551static tree
b8506a8a 552aarch64_simd_builtin_std_type (machine_mode mode,
f9d53c27 553 enum aarch64_type_qualifiers q)
6db1ec94 554{
f9d53c27
TB
555#define QUAL_TYPE(M) \
556 ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
557 switch (mode)
558 {
4e10a5a7 559 case E_QImode:
f9d53c27 560 return QUAL_TYPE (QI);
4e10a5a7 561 case E_HImode:
f9d53c27 562 return QUAL_TYPE (HI);
4e10a5a7 563 case E_SImode:
f9d53c27 564 return QUAL_TYPE (SI);
4e10a5a7 565 case E_DImode:
f9d53c27 566 return QUAL_TYPE (DI);
4e10a5a7 567 case E_TImode:
f9d53c27 568 return QUAL_TYPE (TI);
4e10a5a7 569 case E_OImode:
f9d53c27 570 return aarch64_simd_intOI_type_node;
4e10a5a7 571 case E_CImode:
f9d53c27 572 return aarch64_simd_intCI_type_node;
4e10a5a7 573 case E_XImode:
f9d53c27 574 return aarch64_simd_intXI_type_node;
4e10a5a7 575 case E_HFmode:
71a11456 576 return aarch64_fp16_type_node;
4e10a5a7 577 case E_SFmode:
f9d53c27 578 return float_type_node;
4e10a5a7 579 case E_DFmode:
f9d53c27
TB
580 return double_type_node;
581 default:
582 gcc_unreachable ();
583 }
584#undef QUAL_TYPE
6db1ec94
JG
585}
586
f9d53c27 587static tree
b8506a8a 588aarch64_lookup_simd_builtin_type (machine_mode mode,
f9d53c27 589 enum aarch64_type_qualifiers q)
6db1ec94 590{
f9d53c27
TB
591 int i;
592 int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
593
594 /* Non-poly scalar modes map to standard types not in the table. */
595 if (q != qualifier_poly && !VECTOR_MODE_P (mode))
596 return aarch64_simd_builtin_std_type (mode, q);
597
598 for (i = 0; i < nelts; i++)
599 if (aarch64_simd_types[i].mode == mode
600 && aarch64_simd_types[i].q == q)
601 return aarch64_simd_types[i].itype;
602
603 return NULL_TREE;
b5828b4b
JG
604}
605
f9d53c27 606static tree
b8506a8a 607aarch64_simd_builtin_type (machine_mode mode,
f9d53c27
TB
608 bool unsigned_p, bool poly_p)
609{
610 if (poly_p)
611 return aarch64_lookup_simd_builtin_type (mode, qualifier_poly);
612 else if (unsigned_p)
613 return aarch64_lookup_simd_builtin_type (mode, qualifier_unsigned);
614 else
615 return aarch64_lookup_simd_builtin_type (mode, qualifier_none);
616}
617
af55e82d 618static void
f9d53c27 619aarch64_init_simd_builtin_types (void)
43e9d192 620{
f9d53c27
TB
621 int i;
622 int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
623 tree tdecl;
624
625 /* Init all the element types built by the front-end. */
626 aarch64_simd_types[Int8x8_t].eltype = intQI_type_node;
627 aarch64_simd_types[Int8x16_t].eltype = intQI_type_node;
628 aarch64_simd_types[Int16x4_t].eltype = intHI_type_node;
629 aarch64_simd_types[Int16x8_t].eltype = intHI_type_node;
630 aarch64_simd_types[Int32x2_t].eltype = intSI_type_node;
631 aarch64_simd_types[Int32x4_t].eltype = intSI_type_node;
632 aarch64_simd_types[Int64x1_t].eltype = intDI_type_node;
633 aarch64_simd_types[Int64x2_t].eltype = intDI_type_node;
634 aarch64_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node;
635 aarch64_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node;
636 aarch64_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node;
637 aarch64_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node;
638 aarch64_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node;
639 aarch64_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
640 aarch64_simd_types[Uint64x1_t].eltype = unsigned_intDI_type_node;
641 aarch64_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
642
643 /* Poly types are a world of their own. */
644 aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
645 build_distinct_type_copy (unsigned_intQI_type_node);
646 aarch64_simd_types[Poly16_t].eltype = aarch64_simd_types[Poly16_t].itype =
647 build_distinct_type_copy (unsigned_intHI_type_node);
648 aarch64_simd_types[Poly64_t].eltype = aarch64_simd_types[Poly64_t].itype =
649 build_distinct_type_copy (unsigned_intDI_type_node);
650 aarch64_simd_types[Poly128_t].eltype = aarch64_simd_types[Poly128_t].itype =
651 build_distinct_type_copy (unsigned_intTI_type_node);
652 /* Init poly vector element types with scalar poly types. */
653 aarch64_simd_types[Poly8x8_t].eltype = aarch64_simd_types[Poly8_t].itype;
654 aarch64_simd_types[Poly8x16_t].eltype = aarch64_simd_types[Poly8_t].itype;
655 aarch64_simd_types[Poly16x4_t].eltype = aarch64_simd_types[Poly16_t].itype;
656 aarch64_simd_types[Poly16x8_t].eltype = aarch64_simd_types[Poly16_t].itype;
657 aarch64_simd_types[Poly64x1_t].eltype = aarch64_simd_types[Poly64_t].itype;
658 aarch64_simd_types[Poly64x2_t].eltype = aarch64_simd_types[Poly64_t].itype;
659
660 /* Continue with standard types. */
71a11456
AL
661 aarch64_simd_types[Float16x4_t].eltype = aarch64_fp16_type_node;
662 aarch64_simd_types[Float16x8_t].eltype = aarch64_fp16_type_node;
f9d53c27
TB
663 aarch64_simd_types[Float32x2_t].eltype = float_type_node;
664 aarch64_simd_types[Float32x4_t].eltype = float_type_node;
665 aarch64_simd_types[Float64x1_t].eltype = double_type_node;
666 aarch64_simd_types[Float64x2_t].eltype = double_type_node;
667
668 for (i = 0; i < nelts; i++)
669 {
670 tree eltype = aarch64_simd_types[i].eltype;
b8506a8a 671 machine_mode mode = aarch64_simd_types[i].mode;
f9d53c27
TB
672
673 if (aarch64_simd_types[i].itype == NULL)
b96824c4
RFI
674 {
675 aarch64_simd_types[i].itype
676 = build_distinct_type_copy
677 (build_vector_type (eltype, GET_MODE_NUNITS (mode)));
678 SET_TYPE_STRUCTURAL_EQUALITY (aarch64_simd_types[i].itype);
679 }
f9d53c27
TB
680
681 tdecl = add_builtin_type (aarch64_simd_types[i].name,
682 aarch64_simd_types[i].itype);
683 TYPE_NAME (aarch64_simd_types[i].itype) = tdecl;
f9d53c27 684 }
43e9d192 685
f9d53c27
TB
686#define AARCH64_BUILD_SIGNED_TYPE(mode) \
687 make_signed_type (GET_MODE_PRECISION (mode));
688 aarch64_simd_intOI_type_node = AARCH64_BUILD_SIGNED_TYPE (OImode);
f9d53c27
TB
689 aarch64_simd_intCI_type_node = AARCH64_BUILD_SIGNED_TYPE (CImode);
690 aarch64_simd_intXI_type_node = AARCH64_BUILD_SIGNED_TYPE (XImode);
691#undef AARCH64_BUILD_SIGNED_TYPE
692
f9d53c27
TB
693 tdecl = add_builtin_type
694 ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node);
695 TYPE_NAME (aarch64_simd_intOI_type_node) = tdecl;
696 tdecl = add_builtin_type
697 ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node);
698 TYPE_NAME (aarch64_simd_intCI_type_node) = tdecl;
699 tdecl = add_builtin_type
700 ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node);
701 TYPE_NAME (aarch64_simd_intXI_type_node) = tdecl;
702}
703
704static void
705aarch64_init_simd_builtin_scalar_types (void)
706{
707 /* Define typedefs for all the standard scalar types. */
708 (*lang_hooks.types.register_builtin_type) (intQI_type_node,
43e9d192 709 "__builtin_aarch64_simd_qi");
f9d53c27 710 (*lang_hooks.types.register_builtin_type) (intHI_type_node,
43e9d192 711 "__builtin_aarch64_simd_hi");
7c369485
AL
712 (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node,
713 "__builtin_aarch64_simd_hf");
f9d53c27 714 (*lang_hooks.types.register_builtin_type) (intSI_type_node,
43e9d192 715 "__builtin_aarch64_simd_si");
f9d53c27 716 (*lang_hooks.types.register_builtin_type) (float_type_node,
43e9d192 717 "__builtin_aarch64_simd_sf");
f9d53c27 718 (*lang_hooks.types.register_builtin_type) (intDI_type_node,
43e9d192 719 "__builtin_aarch64_simd_di");
f9d53c27 720 (*lang_hooks.types.register_builtin_type) (double_type_node,
43e9d192 721 "__builtin_aarch64_simd_df");
f9d53c27 722 (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
43e9d192 723 "__builtin_aarch64_simd_poly8");
f9d53c27 724 (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
43e9d192 725 "__builtin_aarch64_simd_poly16");
f9d53c27 726 (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
7baa225d 727 "__builtin_aarch64_simd_poly64");
f9d53c27 728 (*lang_hooks.types.register_builtin_type) (unsigned_intTI_type_node,
7baa225d 729 "__builtin_aarch64_simd_poly128");
f9d53c27 730 (*lang_hooks.types.register_builtin_type) (intTI_type_node,
43e9d192 731 "__builtin_aarch64_simd_ti");
b5828b4b 732 /* Unsigned integer types for various mode sizes. */
f9d53c27 733 (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
b5828b4b 734 "__builtin_aarch64_simd_uqi");
f9d53c27 735 (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
b5828b4b 736 "__builtin_aarch64_simd_uhi");
f9d53c27 737 (*lang_hooks.types.register_builtin_type) (unsigned_intSI_type_node,
b5828b4b 738 "__builtin_aarch64_simd_usi");
f9d53c27 739 (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
b5828b4b 740 "__builtin_aarch64_simd_udi");
f9d53c27
TB
741}
742
e95a988a
KT
743static bool aarch64_simd_builtins_initialized_p = false;
744
745void
f9d53c27
TB
746aarch64_init_simd_builtins (void)
747{
661fce82 748 unsigned int i, fcode = AARCH64_SIMD_PATTERN_START;
f9d53c27 749
e95a988a
KT
750 if (aarch64_simd_builtins_initialized_p)
751 return;
752
753 aarch64_simd_builtins_initialized_p = true;
754
f9d53c27 755 aarch64_init_simd_builtin_types ();
43e9d192 756
f9d53c27
TB
757 /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
758 Therefore we need to preserve the old __builtin scalar types. It can be
759 removed once all the intrinsics become strongly typed using the qualifier
760 system. */
761 aarch64_init_simd_builtin_scalar_types ();
762
661fce82 763 tree lane_check_fpr = build_function_type_list (void_type_node,
9c4f25cc
AP
764 size_type_node,
765 size_type_node,
661fce82
AL
766 intSI_type_node,
767 NULL);
768 aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_LANE_CHECK] =
769 add_builtin_function ("__builtin_aarch64_im_lane_boundsi", lane_check_fpr,
770 AARCH64_SIMD_BUILTIN_LANE_CHECK, BUILT_IN_MD,
771 NULL, NULL_TREE);
772
342be7f7 773 for (i = 0; i < ARRAY_SIZE (aarch64_simd_builtin_data); i++, fcode++)
43e9d192 774 {
b5828b4b 775 bool print_type_signature_p = false;
cae83731 776 char type_signature[SIMD_MAX_BUILTIN_ARGS + 1] = { 0 };
43e9d192 777 aarch64_simd_builtin_datum *d = &aarch64_simd_builtin_data[i];
342be7f7
JG
778 char namebuf[60];
779 tree ftype = NULL;
119103ca 780 tree fndecl = NULL;
342be7f7 781
342be7f7 782 d->fcode = fcode;
43e9d192 783
b5828b4b
JG
784 /* We must track two variables here. op_num is
785 the operand number as in the RTL pattern. This is
786 required to access the mode (e.g. V4SF mode) of the
787 argument, from which the base type can be derived.
788 arg_num is an index in to the qualifiers data, which
789 gives qualifiers to the type (e.g. const unsigned).
790 The reason these two variables may differ by one is the
791 void return type. While all return types take the 0th entry
792 in the qualifiers array, there is no operand for them in the
793 RTL pattern. */
794 int op_num = insn_data[d->code].n_operands - 1;
795 int arg_num = d->qualifiers[0] & qualifier_void
796 ? op_num + 1
797 : op_num;
798 tree return_type = void_type_node, args = void_list_node;
799 tree eltype;
800
801 /* Build a function type directly from the insn_data for this
802 builtin. The build_function_type () function takes care of
803 removing duplicates for us. */
804 for (; op_num >= 0; arg_num--, op_num--)
43e9d192 805 {
ef4bddc2 806 machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
b5828b4b 807 enum aarch64_type_qualifiers qualifiers = d->qualifiers[arg_num];
43e9d192 808
b5828b4b
JG
809 if (qualifiers & qualifier_unsigned)
810 {
9fd2074d 811 type_signature[op_num] = 'u';
b5828b4b
JG
812 print_type_signature_p = true;
813 }
6db1ec94
JG
814 else if (qualifiers & qualifier_poly)
815 {
9fd2074d 816 type_signature[op_num] = 'p';
6db1ec94
JG
817 print_type_signature_p = true;
818 }
b5828b4b 819 else
9fd2074d 820 type_signature[op_num] = 's';
b5828b4b
JG
821
822 /* Skip an internal operand for vget_{low, high}. */
823 if (qualifiers & qualifier_internal)
824 continue;
825
826 /* Some builtins have different user-facing types
827 for certain arguments, encoded in d->mode. */
828 if (qualifiers & qualifier_map_mode)
bc5e395d 829 op_mode = d->mode;
b5828b4b
JG
830
831 /* For pointers, we want a pointer to the basic type
832 of the vector. */
833 if (qualifiers & qualifier_pointer && VECTOR_MODE_P (op_mode))
834 op_mode = GET_MODE_INNER (op_mode);
835
f9d53c27
TB
836 eltype = aarch64_simd_builtin_type
837 (op_mode,
838 (qualifiers & qualifier_unsigned) != 0,
839 (qualifiers & qualifier_poly) != 0);
840 gcc_assert (eltype != NULL);
b5828b4b
JG
841
842 /* Add qualifiers. */
843 if (qualifiers & qualifier_const)
844 eltype = build_qualified_type (eltype, TYPE_QUAL_CONST);
845
846 if (qualifiers & qualifier_pointer)
847 eltype = build_pointer_type (eltype);
848
849 /* If we have reached arg_num == 0, we are at a non-void
850 return type. Otherwise, we are still processing
851 arguments. */
852 if (arg_num == 0)
853 return_type = eltype;
854 else
855 args = tree_cons (NULL_TREE, eltype, args);
856 }
342be7f7 857
b5828b4b 858 ftype = build_function_type (return_type, args);
43e9d192 859
342be7f7 860 gcc_assert (ftype != NULL);
43e9d192 861
b5828b4b 862 if (print_type_signature_p)
bc5e395d
JG
863 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s_%s",
864 d->name, type_signature);
b5828b4b 865 else
bc5e395d
JG
866 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s",
867 d->name);
43e9d192 868
119103ca
JG
869 fndecl = add_builtin_function (namebuf, ftype, fcode, BUILT_IN_MD,
870 NULL, NULL_TREE);
871 aarch64_builtin_decls[fcode] = fndecl;
43e9d192
IB
872 }
873}
874
5d357f26
KT
875static void
876aarch64_init_crc32_builtins ()
877{
f9d53c27 878 tree usi_type = aarch64_simd_builtin_std_type (SImode, qualifier_unsigned);
5d357f26
KT
879 unsigned int i = 0;
880
881 for (i = 0; i < ARRAY_SIZE (aarch64_crc_builtin_data); ++i)
882 {
883 aarch64_crc_builtin_datum* d = &aarch64_crc_builtin_data[i];
f9d53c27
TB
884 tree argtype = aarch64_simd_builtin_std_type (d->mode,
885 qualifier_unsigned);
5d357f26
KT
886 tree ftype = build_function_type_list (usi_type, usi_type, argtype, NULL_TREE);
887 tree fndecl = add_builtin_function (d->name, ftype, d->fcode,
888 BUILT_IN_MD, NULL, NULL_TREE);
889
890 aarch64_builtin_decls[d->fcode] = fndecl;
891 }
892}
893
a6fc00da
BH
894/* Add builtins for reciprocal square root. */
895
896void
897aarch64_init_builtin_rsqrt (void)
898{
899 tree fndecl = NULL;
900 tree ftype = NULL;
901
902 tree V2SF_type_node = build_vector_type (float_type_node, 2);
903 tree V2DF_type_node = build_vector_type (double_type_node, 2);
904 tree V4SF_type_node = build_vector_type (float_type_node, 4);
905
906 struct builtin_decls_data
907 {
908 tree type_node;
909 const char *builtin_name;
910 int function_code;
911 };
912
913 builtin_decls_data bdda[] =
914 {
915 { double_type_node, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF },
916 { float_type_node, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF },
917 { V2DF_type_node, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF },
918 { V2SF_type_node, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF },
919 { V4SF_type_node, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF }
920 };
921
922 builtin_decls_data *bdd = bdda;
923 builtin_decls_data *bdd_end = bdd + (sizeof (bdda) / sizeof (builtin_decls_data));
924
925 for (; bdd < bdd_end; bdd++)
926 {
927 ftype = build_function_type_list (bdd->type_node, bdd->type_node, NULL_TREE);
928 fndecl = add_builtin_function (bdd->builtin_name,
929 ftype, bdd->function_code, BUILT_IN_MD, NULL, NULL_TREE);
930 aarch64_builtin_decls[bdd->function_code] = fndecl;
931 }
932}
933
1b62ed4f
JG
934/* Initialize the backend types that support the user-visible __fp16
935 type, also initialize a pointer to that type, to be used when
936 forming HFAs. */
937
938static void
939aarch64_init_fp16_types (void)
940{
941 aarch64_fp16_type_node = make_node (REAL_TYPE);
942 TYPE_PRECISION (aarch64_fp16_type_node) = 16;
943 layout_type (aarch64_fp16_type_node);
944
945 (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node, "__fp16");
946 aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
947}
948
312492bd
JW
949/* Pointer authentication builtins that will become NOP on legacy platform.
950 Currently, these builtins are for internal use only (libgcc EH unwinder). */
951
952void
953aarch64_init_pauth_hint_builtins (void)
954{
955 /* Pointer Authentication builtins. */
956 tree ftype_pointer_auth
957 = build_function_type_list (ptr_type_node, ptr_type_node,
958 unsigned_intDI_type_node, NULL_TREE);
959 tree ftype_pointer_strip
960 = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
961
962 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
963 = add_builtin_function ("__builtin_aarch64_autia1716", ftype_pointer_auth,
964 AARCH64_PAUTH_BUILTIN_AUTIA1716, BUILT_IN_MD, NULL,
965 NULL_TREE);
966 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIA1716]
967 = add_builtin_function ("__builtin_aarch64_pacia1716", ftype_pointer_auth,
968 AARCH64_PAUTH_BUILTIN_PACIA1716, BUILT_IN_MD, NULL,
969 NULL_TREE);
970 aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
971 = add_builtin_function ("__builtin_aarch64_xpaclri", ftype_pointer_strip,
972 AARCH64_PAUTH_BUILTIN_XPACLRI, BUILT_IN_MD, NULL,
973 NULL_TREE);
974}
975
342be7f7
JG
976void
977aarch64_init_builtins (void)
43e9d192 978{
aa87aced
KV
979 tree ftype_set_fpr
980 = build_function_type_list (void_type_node, unsigned_type_node, NULL);
981 tree ftype_get_fpr
982 = build_function_type_list (unsigned_type_node, NULL);
983
984 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
985 = add_builtin_function ("__builtin_aarch64_get_fpcr", ftype_get_fpr,
986 AARCH64_BUILTIN_GET_FPCR, BUILT_IN_MD, NULL, NULL_TREE);
987 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
988 = add_builtin_function ("__builtin_aarch64_set_fpcr", ftype_set_fpr,
989 AARCH64_BUILTIN_SET_FPCR, BUILT_IN_MD, NULL, NULL_TREE);
990 aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
991 = add_builtin_function ("__builtin_aarch64_get_fpsr", ftype_get_fpr,
992 AARCH64_BUILTIN_GET_FPSR, BUILT_IN_MD, NULL, NULL_TREE);
993 aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
994 = add_builtin_function ("__builtin_aarch64_set_fpsr", ftype_set_fpr,
995 AARCH64_BUILTIN_SET_FPSR, BUILT_IN_MD, NULL, NULL_TREE);
996
1b62ed4f 997 aarch64_init_fp16_types ();
c2ec330c 998
342be7f7
JG
999 if (TARGET_SIMD)
1000 aarch64_init_simd_builtins ();
e95a988a
KT
1001
1002 aarch64_init_crc32_builtins ();
a6fc00da 1003 aarch64_init_builtin_rsqrt ();
312492bd 1004
a876231c
JW
1005 /* Initialize pointer authentication builtins which are backed by instructions
1006 in NOP encoding space.
1007
1008 NOTE: these builtins are supposed to be used by libgcc unwinder only, as
1009 there is no support on return address signing under ILP32, we don't
1010 register them. */
1011 if (!TARGET_ILP32)
1012 aarch64_init_pauth_hint_builtins ();
43e9d192
IB
1013}
1014
119103ca
JG
1015tree
1016aarch64_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
1017{
1018 if (code >= AARCH64_BUILTIN_MAX)
1019 return error_mark_node;
1020
1021 return aarch64_builtin_decls[code];
1022}
1023
43e9d192
IB
1024typedef enum
1025{
1026 SIMD_ARG_COPY_TO_REG,
1027 SIMD_ARG_CONSTANT,
2a49c16d 1028 SIMD_ARG_LANE_INDEX,
4d0a0237 1029 SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX,
43e9d192
IB
1030 SIMD_ARG_STOP
1031} builtin_simd_arg;
1032
e95a988a 1033
43e9d192
IB
1034static rtx
1035aarch64_simd_expand_args (rtx target, int icode, int have_retval,
4d0a0237 1036 tree exp, builtin_simd_arg *args,
b8506a8a 1037 machine_mode builtin_mode)
43e9d192 1038{
43e9d192 1039 rtx pat;
d9e80f49
AL
1040 rtx op[SIMD_MAX_BUILTIN_ARGS + 1]; /* First element for result operand. */
1041 int opc = 0;
1042
1043 if (have_retval)
1044 {
1045 machine_mode tmode = insn_data[icode].operand[0].mode;
1046 if (!target
43e9d192 1047 || GET_MODE (target) != tmode
d9e80f49
AL
1048 || !(*insn_data[icode].operand[0].predicate) (target, tmode))
1049 target = gen_reg_rtx (tmode);
1050 op[opc++] = target;
1051 }
43e9d192 1052
43e9d192
IB
1053 for (;;)
1054 {
d9e80f49 1055 builtin_simd_arg thisarg = args[opc - have_retval];
43e9d192
IB
1056
1057 if (thisarg == SIMD_ARG_STOP)
1058 break;
1059 else
1060 {
d9e80f49 1061 tree arg = CALL_EXPR_ARG (exp, opc - have_retval);
b8506a8a 1062 machine_mode mode = insn_data[icode].operand[opc].mode;
d9e80f49 1063 op[opc] = expand_normal (arg);
43e9d192
IB
1064
1065 switch (thisarg)
1066 {
1067 case SIMD_ARG_COPY_TO_REG:
d9e80f49
AL
1068 if (POINTER_TYPE_P (TREE_TYPE (arg)))
1069 op[opc] = convert_memory_address (Pmode, op[opc]);
1070 /*gcc_assert (GET_MODE (op[opc]) == mode); */
1071 if (!(*insn_data[icode].operand[opc].predicate)
1072 (op[opc], mode))
1073 op[opc] = copy_to_mode_reg (mode, op[opc]);
43e9d192
IB
1074 break;
1075
4d0a0237
CB
1076 case SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX:
1077 gcc_assert (opc > 1);
1078 if (CONST_INT_P (op[opc]))
1079 {
1080 aarch64_simd_lane_bounds (op[opc], 0,
1081 GET_MODE_NUNITS (builtin_mode),
1082 exp);
1083 /* Keep to GCC-vector-extension lane indices in the RTL. */
7ac29c0f
RS
1084 op[opc] = aarch64_endian_lane_rtx (builtin_mode,
1085 INTVAL (op[opc]));
4d0a0237
CB
1086 }
1087 goto constant_arg;
1088
2a49c16d
AL
1089 case SIMD_ARG_LANE_INDEX:
1090 /* Must be a previous operand into which this is an index. */
d9e80f49
AL
1091 gcc_assert (opc > 0);
1092 if (CONST_INT_P (op[opc]))
2a49c16d 1093 {
d9e80f49
AL
1094 machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
1095 aarch64_simd_lane_bounds (op[opc],
46ed6024 1096 0, GET_MODE_NUNITS (vmode), exp);
2a49c16d 1097 /* Keep to GCC-vector-extension lane indices in the RTL. */
7ac29c0f 1098 op[opc] = aarch64_endian_lane_rtx (vmode, INTVAL (op[opc]));
2a49c16d
AL
1099 }
1100 /* Fall through - if the lane index isn't a constant then
1101 the next case will error. */
191816a3 1102 /* FALLTHRU */
43e9d192 1103 case SIMD_ARG_CONSTANT:
4d0a0237 1104constant_arg:
d9e80f49
AL
1105 if (!(*insn_data[icode].operand[opc].predicate)
1106 (op[opc], mode))
d5a29419 1107 {
fca051af
AL
1108 error ("%Kargument %d must be a constant immediate",
1109 exp, opc + 1 - have_retval);
d5a29419
KT
1110 return const0_rtx;
1111 }
43e9d192
IB
1112 break;
1113
1114 case SIMD_ARG_STOP:
1115 gcc_unreachable ();
1116 }
1117
d9e80f49 1118 opc++;
43e9d192
IB
1119 }
1120 }
1121
d9e80f49
AL
1122 switch (opc)
1123 {
1124 case 1:
1125 pat = GEN_FCN (icode) (op[0]);
1126 break;
43e9d192 1127
d9e80f49
AL
1128 case 2:
1129 pat = GEN_FCN (icode) (op[0], op[1]);
1130 break;
43e9d192 1131
d9e80f49
AL
1132 case 3:
1133 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
1134 break;
43e9d192 1135
d9e80f49
AL
1136 case 4:
1137 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
1138 break;
43e9d192 1139
d9e80f49
AL
1140 case 5:
1141 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
1142 break;
43e9d192 1143
d9e80f49
AL
1144 case 6:
1145 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]);
1146 break;
43e9d192 1147
d9e80f49
AL
1148 default:
1149 gcc_unreachable ();
1150 }
43e9d192
IB
1151
1152 if (!pat)
d5a29419 1153 return NULL_RTX;
43e9d192
IB
1154
1155 emit_insn (pat);
1156
1157 return target;
1158}
1159
1160/* Expand an AArch64 AdvSIMD builtin(intrinsic). */
1161rtx
1162aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
1163{
661fce82
AL
1164 if (fcode == AARCH64_SIMD_BUILTIN_LANE_CHECK)
1165 {
9c4f25cc
AP
1166 rtx totalsize = expand_normal (CALL_EXPR_ARG (exp, 0));
1167 rtx elementsize = expand_normal (CALL_EXPR_ARG (exp, 1));
1168 if (CONST_INT_P (totalsize) && CONST_INT_P (elementsize)
1169 && UINTVAL (elementsize) != 0
1170 && UINTVAL (totalsize) != 0)
1171 {
1172 rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 2));
1173 if (CONST_INT_P (lane_idx))
1174 aarch64_simd_lane_bounds (lane_idx, 0,
1175 UINTVAL (totalsize)
1176 / UINTVAL (elementsize),
1177 exp);
1178 else
1179 error ("%Klane index must be a constant immediate", exp);
1180 }
661fce82 1181 else
9c4f25cc 1182 error ("%Ktotal size and element size must be a non-zero constant immediate", exp);
661fce82
AL
1183 /* Don't generate any RTL. */
1184 return const0_rtx;
1185 }
342be7f7 1186 aarch64_simd_builtin_datum *d =
661fce82 1187 &aarch64_simd_builtin_data[fcode - AARCH64_SIMD_PATTERN_START];
342be7f7 1188 enum insn_code icode = d->code;
0ff2bf46 1189 builtin_simd_arg args[SIMD_MAX_BUILTIN_ARGS + 1];
b5828b4b
JG
1190 int num_args = insn_data[d->code].n_operands;
1191 int is_void = 0;
1192 int k;
43e9d192 1193
b5828b4b 1194 is_void = !!(d->qualifiers[0] & qualifier_void);
43e9d192 1195
b5828b4b
JG
1196 num_args += is_void;
1197
1198 for (k = 1; k < num_args; k++)
1199 {
1200 /* We have four arrays of data, each indexed in a different fashion.
1201 qualifiers - element 0 always describes the function return type.
1202 operands - element 0 is either the operand for return value (if
1203 the function has a non-void return type) or the operand for the
1204 first argument.
1205 expr_args - element 0 always holds the first argument.
1206 args - element 0 is always used for the return type. */
1207 int qualifiers_k = k;
1208 int operands_k = k - is_void;
1209 int expr_args_k = k - 1;
1210
2a49c16d
AL
1211 if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
1212 args[k] = SIMD_ARG_LANE_INDEX;
4d0a0237
CB
1213 else if (d->qualifiers[qualifiers_k] & qualifier_struct_load_store_lane_index)
1214 args[k] = SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX;
2a49c16d 1215 else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
b5828b4b
JG
1216 args[k] = SIMD_ARG_CONSTANT;
1217 else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
1218 {
1219 rtx arg
1220 = expand_normal (CALL_EXPR_ARG (exp,
1221 (expr_args_k)));
1222 /* Handle constants only if the predicate allows it. */
1223 bool op_const_int_p =
1224 (CONST_INT_P (arg)
1225 && (*insn_data[icode].operand[operands_k].predicate)
1226 (arg, insn_data[icode].operand[operands_k].mode));
1227 args[k] = op_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG;
1228 }
1229 else
1230 args[k] = SIMD_ARG_COPY_TO_REG;
43e9d192 1231
43e9d192 1232 }
b5828b4b
JG
1233 args[k] = SIMD_ARG_STOP;
1234
1235 /* The interface to aarch64_simd_expand_args expects a 0 if
1236 the function is void, and a 1 if it is not. */
1237 return aarch64_simd_expand_args
4d0a0237 1238 (target, icode, !is_void, exp, &args[1], d->mode);
43e9d192 1239}
342be7f7 1240
5d357f26
KT
1241rtx
1242aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target)
1243{
1244 rtx pat;
1245 aarch64_crc_builtin_datum *d
1246 = &aarch64_crc_builtin_data[fcode - (AARCH64_CRC32_BUILTIN_BASE + 1)];
1247 enum insn_code icode = d->icode;
1248 tree arg0 = CALL_EXPR_ARG (exp, 0);
1249 tree arg1 = CALL_EXPR_ARG (exp, 1);
1250 rtx op0 = expand_normal (arg0);
1251 rtx op1 = expand_normal (arg1);
ef4bddc2
RS
1252 machine_mode tmode = insn_data[icode].operand[0].mode;
1253 machine_mode mode0 = insn_data[icode].operand[1].mode;
1254 machine_mode mode1 = insn_data[icode].operand[2].mode;
5d357f26
KT
1255
1256 if (! target
1257 || GET_MODE (target) != tmode
1258 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
1259 target = gen_reg_rtx (tmode);
1260
1261 gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
1262 && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
1263
1264 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
1265 op0 = copy_to_mode_reg (mode0, op0);
1266 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
1267 op1 = copy_to_mode_reg (mode1, op1);
1268
1269 pat = GEN_FCN (icode) (target, op0, op1);
d5a29419
KT
1270 if (!pat)
1271 return NULL_RTX;
1272
5d357f26
KT
1273 emit_insn (pat);
1274 return target;
1275}
1276
a6fc00da
BH
1277/* Function to expand reciprocal square root builtins. */
1278
1279static rtx
1280aarch64_expand_builtin_rsqrt (int fcode, tree exp, rtx target)
1281{
1282 tree arg0 = CALL_EXPR_ARG (exp, 0);
1283 rtx op0 = expand_normal (arg0);
1284
1285 rtx (*gen) (rtx, rtx);
1286
1287 switch (fcode)
1288 {
1289 case AARCH64_BUILTIN_RSQRT_DF:
ee62a5a6 1290 gen = gen_rsqrtdf2;
a6fc00da
BH
1291 break;
1292 case AARCH64_BUILTIN_RSQRT_SF:
ee62a5a6 1293 gen = gen_rsqrtsf2;
a6fc00da
BH
1294 break;
1295 case AARCH64_BUILTIN_RSQRT_V2DF:
ee62a5a6 1296 gen = gen_rsqrtv2df2;
a6fc00da
BH
1297 break;
1298 case AARCH64_BUILTIN_RSQRT_V2SF:
ee62a5a6 1299 gen = gen_rsqrtv2sf2;
a6fc00da
BH
1300 break;
1301 case AARCH64_BUILTIN_RSQRT_V4SF:
ee62a5a6 1302 gen = gen_rsqrtv4sf2;
a6fc00da
BH
1303 break;
1304 default: gcc_unreachable ();
1305 }
1306
1307 if (!target)
1308 target = gen_reg_rtx (GET_MODE (op0));
1309
1310 emit_insn (gen (target, op0));
1311
1312 return target;
1313}
1314
342be7f7
JG
1315/* Expand an expression EXP that calls a built-in function,
1316 with result going to TARGET if that's convenient. */
1317rtx
1318aarch64_expand_builtin (tree exp,
1319 rtx target,
1320 rtx subtarget ATTRIBUTE_UNUSED,
ef4bddc2 1321 machine_mode mode ATTRIBUTE_UNUSED,
342be7f7
JG
1322 int ignore ATTRIBUTE_UNUSED)
1323{
1324 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
1325 int fcode = DECL_FUNCTION_CODE (fndecl);
aa87aced
KV
1326 int icode;
1327 rtx pat, op0;
1328 tree arg0;
1329
1330 switch (fcode)
1331 {
1332 case AARCH64_BUILTIN_GET_FPCR:
1333 case AARCH64_BUILTIN_SET_FPCR:
1334 case AARCH64_BUILTIN_GET_FPSR:
1335 case AARCH64_BUILTIN_SET_FPSR:
1336 if ((fcode == AARCH64_BUILTIN_GET_FPCR)
1337 || (fcode == AARCH64_BUILTIN_GET_FPSR))
1338 {
1339 icode = (fcode == AARCH64_BUILTIN_GET_FPSR) ?
1340 CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;
1341 target = gen_reg_rtx (SImode);
1342 pat = GEN_FCN (icode) (target);
1343 }
1344 else
1345 {
1346 target = NULL_RTX;
1347 icode = (fcode == AARCH64_BUILTIN_SET_FPSR) ?
1348 CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;
1349 arg0 = CALL_EXPR_ARG (exp, 0);
e6cf8d65 1350 op0 = force_reg (SImode, expand_normal (arg0));
aa87aced
KV
1351 pat = GEN_FCN (icode) (op0);
1352 }
1353 emit_insn (pat);
1354 return target;
312492bd
JW
1355
1356 case AARCH64_PAUTH_BUILTIN_AUTIA1716:
1357 case AARCH64_PAUTH_BUILTIN_PACIA1716:
1358 case AARCH64_PAUTH_BUILTIN_XPACLRI:
1359 arg0 = CALL_EXPR_ARG (exp, 0);
1360 op0 = force_reg (Pmode, expand_normal (arg0));
1361
1362 if (!target)
1363 target = gen_reg_rtx (Pmode);
1364 else
1365 target = force_reg (Pmode, target);
1366
1367 emit_move_insn (target, op0);
1368
1369 if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
1370 {
1371 rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
1372 icode = CODE_FOR_xpaclri;
1373 emit_move_insn (lr, op0);
1374 emit_insn (GEN_FCN (icode) ());
1375 emit_move_insn (target, lr);
1376 }
1377 else
1378 {
1379 tree arg1 = CALL_EXPR_ARG (exp, 1);
1380 rtx op1 = force_reg (Pmode, expand_normal (arg1));
1381 icode = (fcode == AARCH64_PAUTH_BUILTIN_PACIA1716
1382 ? CODE_FOR_paci1716 : CODE_FOR_auti1716);
1383
1384 rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
1385 rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
1386 emit_move_insn (x17_reg, op0);
1387 emit_move_insn (x16_reg, op1);
1388 emit_insn (GEN_FCN (icode) ());
1389 emit_move_insn (target, x17_reg);
1390 }
1391
1392 return target;
aa87aced 1393 }
342be7f7 1394
5d357f26 1395 if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
342be7f7 1396 return aarch64_simd_expand_builtin (fcode, exp, target);
5d357f26
KT
1397 else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX)
1398 return aarch64_crc32_expand_builtin (fcode, exp, target);
342be7f7 1399
a6fc00da
BH
1400 if (fcode == AARCH64_BUILTIN_RSQRT_DF
1401 || fcode == AARCH64_BUILTIN_RSQRT_SF
1402 || fcode == AARCH64_BUILTIN_RSQRT_V2DF
1403 || fcode == AARCH64_BUILTIN_RSQRT_V2SF
1404 || fcode == AARCH64_BUILTIN_RSQRT_V4SF)
1405 return aarch64_expand_builtin_rsqrt (fcode, exp, target);
1406
d5a29419 1407 gcc_unreachable ();
342be7f7 1408}
42fc9a7f
JG
1409
1410tree
10766209
RS
1411aarch64_builtin_vectorized_function (unsigned int fn, tree type_out,
1412 tree type_in)
42fc9a7f 1413{
ef4bddc2 1414 machine_mode in_mode, out_mode;
42fc9a7f
JG
1415 int in_n, out_n;
1416
1417 if (TREE_CODE (type_out) != VECTOR_TYPE
1418 || TREE_CODE (type_in) != VECTOR_TYPE)
1419 return NULL_TREE;
1420
1421 out_mode = TYPE_MODE (TREE_TYPE (type_out));
1422 out_n = TYPE_VECTOR_SUBPARTS (type_out);
1423 in_mode = TYPE_MODE (TREE_TYPE (type_in));
1424 in_n = TYPE_VECTOR_SUBPARTS (type_in);
1425
1426#undef AARCH64_CHECK_BUILTIN_MODE
1427#define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
1428#define AARCH64_FIND_FRINT_VARIANT(N) \
1429 (AARCH64_CHECK_BUILTIN_MODE (2, D) \
e993fea1 1430 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
42fc9a7f 1431 : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
e993fea1 1432 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
42fc9a7f 1433 : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
e993fea1 1434 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
42fc9a7f 1435 : NULL_TREE)))
10766209 1436 switch (fn)
42fc9a7f 1437 {
42fc9a7f
JG
1438#undef AARCH64_CHECK_BUILTIN_MODE
1439#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1440 (out_mode == N##Fmode && out_n == C \
1441 && in_mode == N##Fmode && in_n == C)
10766209
RS
1442 CASE_CFN_FLOOR:
1443 return AARCH64_FIND_FRINT_VARIANT (floor);
1444 CASE_CFN_CEIL:
1445 return AARCH64_FIND_FRINT_VARIANT (ceil);
1446 CASE_CFN_TRUNC:
1447 return AARCH64_FIND_FRINT_VARIANT (btrunc);
1448 CASE_CFN_ROUND:
1449 return AARCH64_FIND_FRINT_VARIANT (round);
1450 CASE_CFN_NEARBYINT:
1451 return AARCH64_FIND_FRINT_VARIANT (nearbyint);
1452 CASE_CFN_SQRT:
1453 return AARCH64_FIND_FRINT_VARIANT (sqrt);
42fc9a7f 1454#undef AARCH64_CHECK_BUILTIN_MODE
b5574232
VP
1455#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1456 (out_mode == SImode && out_n == C \
1457 && in_mode == N##Imode && in_n == C)
10766209
RS
1458 CASE_CFN_CLZ:
1459 {
1460 if (AARCH64_CHECK_BUILTIN_MODE (4, S))
1461 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_clzv4si];
1462 return NULL_TREE;
1463 }
1464 CASE_CFN_CTZ:
1465 {
1466 if (AARCH64_CHECK_BUILTIN_MODE (2, S))
1467 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si];
1468 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
1469 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si];
1470 return NULL_TREE;
1471 }
b5574232 1472#undef AARCH64_CHECK_BUILTIN_MODE
42fc9a7f
JG
1473#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1474 (out_mode == N##Imode && out_n == C \
1475 && in_mode == N##Fmode && in_n == C)
10766209
RS
1476 CASE_CFN_IFLOOR:
1477 CASE_CFN_LFLOOR:
1478 CASE_CFN_LLFLOOR:
1479 {
1480 enum aarch64_builtins builtin;
1481 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
1482 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di;
1483 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
1484 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si;
1485 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
1486 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si;
1487 else
1488 return NULL_TREE;
1489
1490 return aarch64_builtin_decls[builtin];
1491 }
1492 CASE_CFN_ICEIL:
1493 CASE_CFN_LCEIL:
1494 CASE_CFN_LLCEIL:
1495 {
1496 enum aarch64_builtins builtin;
1497 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
1498 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di;
1499 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
1500 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si;
1501 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
1502 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si;
1503 else
1504 return NULL_TREE;
1505
1506 return aarch64_builtin_decls[builtin];
1507 }
1508 CASE_CFN_IROUND:
1509 CASE_CFN_LROUND:
1510 CASE_CFN_LLROUND:
1511 {
1512 enum aarch64_builtins builtin;
1513 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
1514 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di;
1515 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
1516 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si;
1517 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
1518 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si;
1519 else
1520 return NULL_TREE;
1521
1522 return aarch64_builtin_decls[builtin];
1523 }
1524 case CFN_BUILT_IN_BSWAP16:
c7f28cd5
KT
1525#undef AARCH64_CHECK_BUILTIN_MODE
1526#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1527 (out_mode == N##Imode && out_n == C \
1528 && in_mode == N##Imode && in_n == C)
10766209
RS
1529 if (AARCH64_CHECK_BUILTIN_MODE (4, H))
1530 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4hi];
1531 else if (AARCH64_CHECK_BUILTIN_MODE (8, H))
1532 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv8hi];
1533 else
1534 return NULL_TREE;
1535 case CFN_BUILT_IN_BSWAP32:
1536 if (AARCH64_CHECK_BUILTIN_MODE (2, S))
1537 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2si];
1538 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
1539 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4si];
1540 else
1541 return NULL_TREE;
1542 case CFN_BUILT_IN_BSWAP64:
1543 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
1544 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2di];
1545 else
1546 return NULL_TREE;
1547 default:
1548 return NULL_TREE;
42fc9a7f
JG
1549 }
1550
1551 return NULL_TREE;
1552}
0ac198d3 1553
a6fc00da
BH
1554/* Return builtin for reciprocal square root. */
1555
1556tree
ee62a5a6 1557aarch64_builtin_rsqrt (unsigned int fn)
a6fc00da 1558{
ee62a5a6
RS
1559 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df)
1560 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2DF];
1561 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf)
1562 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2SF];
1563 if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf)
1564 return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V4SF];
a6fc00da
BH
1565 return NULL_TREE;
1566}
1567
0ac198d3
JG
1568#undef VAR1
1569#define VAR1(T, N, MAP, A) \
e993fea1 1570 case AARCH64_SIMD_BUILTIN_##T##_##N##A:
0ac198d3 1571
9697e620
JG
1572tree
1573aarch64_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
1574 bool ignore ATTRIBUTE_UNUSED)
1575{
1576 int fcode = DECL_FUNCTION_CODE (fndecl);
1577 tree type = TREE_TYPE (TREE_TYPE (fndecl));
1578
1579 switch (fcode)
1580 {
8f905d69 1581 BUILTIN_VDQF (UNOP, abs, 2)
9697e620 1582 return fold_build1 (ABS_EXPR, type, args[0]);
1709ff9b
JG
1583 VAR1 (UNOP, floatv2si, 2, v2sf)
1584 VAR1 (UNOP, floatv4si, 2, v4sf)
1585 VAR1 (UNOP, floatv2di, 2, v2df)
1586 return fold_build1 (FLOAT_EXPR, type, args[0]);
9697e620
JG
1587 default:
1588 break;
1589 }
1590
1591 return NULL_TREE;
1592}
1593
0ac198d3
JG
1594bool
1595aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi)
1596{
1597 bool changed = false;
355fe088 1598 gimple *stmt = gsi_stmt (*gsi);
0ac198d3
JG
1599 tree call = gimple_call_fn (stmt);
1600 tree fndecl;
355fe088 1601 gimple *new_stmt = NULL;
22756ccf 1602
0ac198d3
JG
1603 if (call)
1604 {
1605 fndecl = gimple_call_fndecl (stmt);
1606 if (fndecl)
1607 {
1608 int fcode = DECL_FUNCTION_CODE (fndecl);
546e500c 1609 unsigned nargs = gimple_call_num_args (stmt);
0ac198d3
JG
1610 tree *args = (nargs > 0
1611 ? gimple_call_arg_ptr (stmt, 0)
1612 : &error_mark_node);
1613
16d24520 1614 /* We use gimple's IFN_REDUC_(PLUS|MIN|MAX)s for float, signed int
fc72cba7
AL
1615 and unsigned int; it will distinguish according to the types of
1616 the arguments to the __builtin. */
0ac198d3
JG
1617 switch (fcode)
1618 {
fc72cba7 1619 BUILTIN_VALL (UNOP, reduc_plus_scal_, 10)
16d24520
RS
1620 new_stmt = gimple_build_call_internal (IFN_REDUC_PLUS,
1621 1, args[0]);
1622 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
0ac198d3 1623 break;
fc72cba7
AL
1624 BUILTIN_VDQIF (UNOP, reduc_smax_scal_, 10)
1625 BUILTIN_VDQ_BHSI (UNOPU, reduc_umax_scal_, 10)
16d24520
RS
1626 new_stmt = gimple_build_call_internal (IFN_REDUC_MAX,
1627 1, args[0]);
1628 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
1598945b 1629 break;
fc72cba7
AL
1630 BUILTIN_VDQIF (UNOP, reduc_smin_scal_, 10)
1631 BUILTIN_VDQ_BHSI (UNOPU, reduc_umin_scal_, 10)
16d24520
RS
1632 new_stmt = gimple_build_call_internal (IFN_REDUC_MIN,
1633 1, args[0]);
1634 gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
1598945b 1635 break;
546e500c
BB
1636 BUILTIN_GPF (BINOP, fmulx, 0)
1637 {
1638 gcc_assert (nargs == 2);
1639 bool a0_cst_p = TREE_CODE (args[0]) == REAL_CST;
1640 bool a1_cst_p = TREE_CODE (args[1]) == REAL_CST;
1641 if (a0_cst_p || a1_cst_p)
1642 {
1643 if (a0_cst_p && a1_cst_p)
1644 {
1645 tree t0 = TREE_TYPE (args[0]);
1646 real_value a0 = (TREE_REAL_CST (args[0]));
1647 real_value a1 = (TREE_REAL_CST (args[1]));
1648 if (real_equal (&a1, &dconst0))
1649 std::swap (a0, a1);
1650 /* According to real_equal (), +0 equals -0. */
1651 if (real_equal (&a0, &dconst0) && real_isinf (&a1))
1652 {
1653 real_value res = dconst2;
1654 res.sign = a0.sign ^ a1.sign;
1655 new_stmt =
1656 gimple_build_assign (gimple_call_lhs (stmt),
1657 REAL_CST,
1658 build_real (t0, res));
1659 }
1660 else
1661 new_stmt =
1662 gimple_build_assign (gimple_call_lhs (stmt),
1663 MULT_EXPR,
1664 args[0], args[1]);
1665 }
1666 else /* a0_cst_p ^ a1_cst_p. */
1667 {
1668 real_value const_part = a0_cst_p
1669 ? TREE_REAL_CST (args[0]) : TREE_REAL_CST (args[1]);
1670 if (!real_equal (&const_part, &dconst0)
1671 && !real_isinf (&const_part))
1672 new_stmt =
1673 gimple_build_assign (gimple_call_lhs (stmt),
1674 MULT_EXPR, args[0], args[1]);
1675 }
1676 }
1677 if (new_stmt)
1678 {
1679 gimple_set_vuse (new_stmt, gimple_vuse (stmt));
1680 gimple_set_vdef (new_stmt, gimple_vdef (stmt));
1681 }
1682 break;
1683 }
0ac198d3
JG
1684 default:
1685 break;
1686 }
1687 }
1688 }
1689
1690 if (new_stmt)
1691 {
1692 gsi_replace (gsi, new_stmt, true);
1693 changed = true;
1694 }
1695
1696 return changed;
1697}
1698
aa87aced
KV
1699void
1700aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
1701{
1702 const unsigned AARCH64_FE_INVALID = 1;
1703 const unsigned AARCH64_FE_DIVBYZERO = 2;
1704 const unsigned AARCH64_FE_OVERFLOW = 4;
1705 const unsigned AARCH64_FE_UNDERFLOW = 8;
1706 const unsigned AARCH64_FE_INEXACT = 16;
1707 const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID
1708 | AARCH64_FE_DIVBYZERO
1709 | AARCH64_FE_OVERFLOW
1710 | AARCH64_FE_UNDERFLOW
1711 | AARCH64_FE_INEXACT);
1712 const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8;
1713 tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr;
1714 tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr;
1715 tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr;
1716 tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv;
1717
1718 /* Generate the equivalence of :
1719 unsigned int fenv_cr;
1720 fenv_cr = __builtin_aarch64_get_fpcr ();
1721
1722 unsigned int fenv_sr;
1723 fenv_sr = __builtin_aarch64_get_fpsr ();
1724
1725 Now set all exceptions to non-stop
1726 unsigned int mask_cr
1727 = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
1728 unsigned int masked_cr;
1729 masked_cr = fenv_cr & mask_cr;
1730
1731 And clear all exception flags
1732 unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
1733 unsigned int masked_cr;
1734 masked_sr = fenv_sr & mask_sr;
1735
1736 __builtin_aarch64_set_cr (masked_cr);
1737 __builtin_aarch64_set_sr (masked_sr); */
1738
09ba9ef7
RR
1739 fenv_cr = create_tmp_var_raw (unsigned_type_node);
1740 fenv_sr = create_tmp_var_raw (unsigned_type_node);
aa87aced
KV
1741
1742 get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR];
1743 set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR];
1744 get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR];
1745 set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR];
1746
1747 mask_cr = build_int_cst (unsigned_type_node,
1748 ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT));
1749 mask_sr = build_int_cst (unsigned_type_node,
1750 ~(AARCH64_FE_ALL_EXCEPT));
1751
1752 ld_fenv_cr = build2 (MODIFY_EXPR, unsigned_type_node,
09ba9ef7 1753 fenv_cr, build_call_expr (get_fpcr, 0));
aa87aced 1754 ld_fenv_sr = build2 (MODIFY_EXPR, unsigned_type_node,
09ba9ef7 1755 fenv_sr, build_call_expr (get_fpsr, 0));
aa87aced
KV
1756
1757 masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr);
1758 masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr);
1759
1760 hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr);
1761 hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr);
1762
1763 hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr,
1764 hold_fnclex_sr);
1765 masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr,
1766 masked_fenv_sr);
1767 ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr);
1768
1769 *hold = build2 (COMPOUND_EXPR, void_type_node,
1770 build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
1771 hold_fnclex);
1772
1773 /* Store the value of masked_fenv to clear the exceptions:
1774 __builtin_aarch64_set_fpsr (masked_fenv_sr); */
1775
1776 *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr);
1777
1778 /* Generate the equivalent of :
1779 unsigned int new_fenv_var;
1780 new_fenv_var = __builtin_aarch64_get_fpsr ();
1781
1782 __builtin_aarch64_set_fpsr (fenv_sr);
1783
1784 __atomic_feraiseexcept (new_fenv_var); */
1785
09ba9ef7 1786 new_fenv_var = create_tmp_var_raw (unsigned_type_node);
aa87aced
KV
1787 reload_fenv = build2 (MODIFY_EXPR, unsigned_type_node,
1788 new_fenv_var, build_call_expr (get_fpsr, 0));
1789 restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr);
1790 atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
1791 update_call = build_call_expr (atomic_feraiseexcept, 1,
1792 fold_convert (integer_type_node, new_fenv_var));
1793 *update = build2 (COMPOUND_EXPR, void_type_node,
1794 build2 (COMPOUND_EXPR, void_type_node,
1795 reload_fenv, restore_fnenv), update_call);
1796}
1797
1798
42fc9a7f
JG
1799#undef AARCH64_CHECK_BUILTIN_MODE
1800#undef AARCH64_FIND_FRINT_VARIANT
0ddec79f
JG
1801#undef CF0
1802#undef CF1
1803#undef CF2
1804#undef CF3
1805#undef CF4
1806#undef CF10
1807#undef VAR1
1808#undef VAR2
1809#undef VAR3
1810#undef VAR4
1811#undef VAR5
1812#undef VAR6
1813#undef VAR7
1814#undef VAR8
1815#undef VAR9
1816#undef VAR10
1817#undef VAR11
1818
3c03d39d 1819#include "gt-aarch64-builtins.h"