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