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