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