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