1 /* Builtins' description for AArch64 SIMD architecture.
2 Copyright (C) 2011-2022 Free Software Foundation, Inc.
3 Contributed by ARM Ltd.
5 This file is part of GCC.
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)
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.
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/>. */
21 #define IN_TARGET_CODE 1
25 #include "coretypes.h"
28 #include "basic-block.h"
38 #include "diagnostic-core.h"
39 #include "fold-const.h"
40 #include "stor-layout.h"
43 #include "langhooks.h"
44 #include "gimple-iterator.h"
45 #include "case-cfn-macros.h"
47 #include "stringpool.h"
49 #include "gimple-fold.h"
51 #define v8qi_UP E_V8QImode
52 #define v8di_UP E_V8DImode
53 #define v4hi_UP E_V4HImode
54 #define v4hf_UP E_V4HFmode
55 #define v2si_UP E_V2SImode
56 #define v2sf_UP E_V2SFmode
57 #define v1df_UP E_V1DFmode
58 #define di_UP E_DImode
59 #define df_UP E_DFmode
60 #define v16qi_UP E_V16QImode
61 #define v8hi_UP E_V8HImode
62 #define v8hf_UP E_V8HFmode
63 #define v4si_UP E_V4SImode
64 #define v4sf_UP E_V4SFmode
65 #define v2di_UP E_V2DImode
66 #define v2df_UP E_V2DFmode
67 #define ti_UP E_TImode
68 #define oi_UP E_OImode
69 #define ci_UP E_CImode
70 #define xi_UP E_XImode
71 #define si_UP E_SImode
72 #define sf_UP E_SFmode
73 #define hi_UP E_HImode
74 #define hf_UP E_HFmode
75 #define qi_UP E_QImode
76 #define bf_UP E_BFmode
77 #define v4bf_UP E_V4BFmode
78 #define v8bf_UP E_V8BFmode
79 #define v2x8qi_UP E_V2x8QImode
80 #define v2x4hi_UP E_V2x4HImode
81 #define v2x4hf_UP E_V2x4HFmode
82 #define v2x4bf_UP E_V2x4BFmode
83 #define v2x2si_UP E_V2x2SImode
84 #define v2x2sf_UP E_V2x2SFmode
85 #define v2x1di_UP E_V2x1DImode
86 #define v2x1df_UP E_V2x1DFmode
87 #define v2x16qi_UP E_V2x16QImode
88 #define v2x8hi_UP E_V2x8HImode
89 #define v2x8hf_UP E_V2x8HFmode
90 #define v2x8bf_UP E_V2x8BFmode
91 #define v2x4si_UP E_V2x4SImode
92 #define v2x4sf_UP E_V2x4SFmode
93 #define v2x2di_UP E_V2x2DImode
94 #define v2x2df_UP E_V2x2DFmode
95 #define v3x8qi_UP E_V3x8QImode
96 #define v3x4hi_UP E_V3x4HImode
97 #define v3x4hf_UP E_V3x4HFmode
98 #define v3x4bf_UP E_V3x4BFmode
99 #define v3x2si_UP E_V3x2SImode
100 #define v3x2sf_UP E_V3x2SFmode
101 #define v3x1di_UP E_V3x1DImode
102 #define v3x1df_UP E_V3x1DFmode
103 #define v3x16qi_UP E_V3x16QImode
104 #define v3x8hi_UP E_V3x8HImode
105 #define v3x8hf_UP E_V3x8HFmode
106 #define v3x8bf_UP E_V3x8BFmode
107 #define v3x4si_UP E_V3x4SImode
108 #define v3x4sf_UP E_V3x4SFmode
109 #define v3x2di_UP E_V3x2DImode
110 #define v3x2df_UP E_V3x2DFmode
111 #define v4x8qi_UP E_V4x8QImode
112 #define v4x4hi_UP E_V4x4HImode
113 #define v4x4hf_UP E_V4x4HFmode
114 #define v4x4bf_UP E_V4x4BFmode
115 #define v4x2si_UP E_V4x2SImode
116 #define v4x2sf_UP E_V4x2SFmode
117 #define v4x1di_UP E_V4x1DImode
118 #define v4x1df_UP E_V4x1DFmode
119 #define v4x16qi_UP E_V4x16QImode
120 #define v4x8hi_UP E_V4x8HImode
121 #define v4x8hf_UP E_V4x8HFmode
122 #define v4x8bf_UP E_V4x8BFmode
123 #define v4x4si_UP E_V4x4SImode
124 #define v4x4sf_UP E_V4x4SFmode
125 #define v4x2di_UP E_V4x2DImode
126 #define v4x2df_UP E_V4x2DFmode
129 #define SIMD_MAX_BUILTIN_ARGS 5
131 enum aarch64_type_qualifiers
134 qualifier_none
= 0x0,
135 /* unsigned T foo. */
136 qualifier_unsigned
= 0x1, /* 1 << 0 */
138 qualifier_const
= 0x2, /* 1 << 1 */
140 qualifier_pointer
= 0x4, /* 1 << 2 */
141 /* Used when expanding arguments if an operand could
143 qualifier_immediate
= 0x8, /* 1 << 3 */
144 qualifier_maybe_immediate
= 0x10, /* 1 << 4 */
145 /* void foo (...). */
146 qualifier_void
= 0x20, /* 1 << 5 */
147 /* Some patterns may have internal operands, this qualifier is an
148 instruction to the initialisation code to skip this operand. */
149 qualifier_internal
= 0x40, /* 1 << 6 */
150 /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
151 rather than using the type of the operand. */
152 qualifier_map_mode
= 0x80, /* 1 << 7 */
153 /* qualifier_pointer | qualifier_map_mode */
154 qualifier_pointer_map_mode
= 0x84,
155 /* qualifier_const | qualifier_pointer | qualifier_map_mode */
156 qualifier_const_pointer_map_mode
= 0x86,
157 /* Polynomial types. */
158 qualifier_poly
= 0x100,
159 /* Lane indices - must be in range, and flipped for bigendian. */
160 qualifier_lane_index
= 0x200,
161 /* Lane indices for single lane structure loads and stores. */
162 qualifier_struct_load_store_lane_index
= 0x400,
163 /* Lane indices selected in pairs. - must be in range, and flipped for
165 qualifier_lane_pair_index
= 0x800,
166 /* Lane indices selected in quadtuplets. - must be in range, and flipped for
168 qualifier_lane_quadtup_index
= 0x1000,
171 /* Flags that describe what a function might do. */
172 const unsigned int FLAG_NONE
= 0U;
173 const unsigned int FLAG_READ_FPCR
= 1U << 0;
174 const unsigned int FLAG_RAISE_FP_EXCEPTIONS
= 1U << 1;
175 const unsigned int FLAG_READ_MEMORY
= 1U << 2;
176 const unsigned int FLAG_PREFETCH_MEMORY
= 1U << 3;
177 const unsigned int FLAG_WRITE_MEMORY
= 1U << 4;
179 /* Not all FP intrinsics raise FP exceptions or read FPCR register,
180 use this flag to suppress it. */
181 const unsigned int FLAG_AUTO_FP
= 1U << 5;
183 const unsigned int FLAG_FP
= FLAG_READ_FPCR
| FLAG_RAISE_FP_EXCEPTIONS
;
184 const unsigned int FLAG_ALL
= FLAG_READ_FPCR
| FLAG_RAISE_FP_EXCEPTIONS
185 | FLAG_READ_MEMORY
| FLAG_PREFETCH_MEMORY
| FLAG_WRITE_MEMORY
;
186 const unsigned int FLAG_STORE
= FLAG_WRITE_MEMORY
| FLAG_AUTO_FP
;
187 const unsigned int FLAG_LOAD
= FLAG_READ_MEMORY
| FLAG_AUTO_FP
;
193 const enum insn_code code
;
195 enum aarch64_type_qualifiers
*qualifiers
;
197 } aarch64_simd_builtin_datum
;
199 static enum aarch64_type_qualifiers
200 aarch64_types_unop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
201 = { qualifier_none
, qualifier_none
};
202 #define TYPES_UNOP (aarch64_types_unop_qualifiers)
203 static enum aarch64_type_qualifiers
204 aarch64_types_unopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
205 = { qualifier_unsigned
, qualifier_unsigned
};
206 #define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
207 static enum aarch64_type_qualifiers
208 aarch64_types_unopus_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
209 = { qualifier_unsigned
, qualifier_none
};
210 #define TYPES_UNOPUS (aarch64_types_unopus_qualifiers)
211 static enum aarch64_type_qualifiers
212 aarch64_types_binop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
213 = { qualifier_none
, qualifier_none
, qualifier_maybe_immediate
};
214 #define TYPES_BINOP (aarch64_types_binop_qualifiers)
215 static enum aarch64_type_qualifiers
216 aarch64_types_binopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
217 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
};
218 #define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
219 static enum aarch64_type_qualifiers
220 aarch64_types_binop_uus_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
221 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_none
};
222 #define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
223 static enum aarch64_type_qualifiers
224 aarch64_types_binop_ssu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
225 = { qualifier_none
, qualifier_none
, qualifier_unsigned
};
226 #define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
227 static enum aarch64_type_qualifiers
228 aarch64_types_binop_uss_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
229 = { qualifier_unsigned
, qualifier_none
, qualifier_none
};
230 #define TYPES_BINOP_USS (aarch64_types_binop_uss_qualifiers)
231 static enum aarch64_type_qualifiers
232 aarch64_types_binopp_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
233 = { qualifier_poly
, qualifier_poly
, qualifier_poly
};
234 #define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
235 static enum aarch64_type_qualifiers
236 aarch64_types_binop_ppu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
237 = { qualifier_poly
, qualifier_poly
, qualifier_unsigned
};
238 #define TYPES_BINOP_PPU (aarch64_types_binop_ppu_qualifiers)
240 static enum aarch64_type_qualifiers
241 aarch64_types_ternop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
242 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_none
};
243 #define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
244 static enum aarch64_type_qualifiers
245 aarch64_types_ternop_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
246 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_lane_index
};
247 #define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
248 static enum aarch64_type_qualifiers
249 aarch64_types_ternopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
250 = { qualifier_unsigned
, qualifier_unsigned
,
251 qualifier_unsigned
, qualifier_unsigned
};
252 #define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
253 static enum aarch64_type_qualifiers
254 aarch64_types_ternopu_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
255 = { qualifier_unsigned
, qualifier_unsigned
,
256 qualifier_unsigned
, qualifier_lane_index
};
257 #define TYPES_TERNOPU_LANE (aarch64_types_ternopu_lane_qualifiers)
258 static enum aarch64_type_qualifiers
259 aarch64_types_ternopu_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
260 = { qualifier_unsigned
, qualifier_unsigned
,
261 qualifier_unsigned
, qualifier_immediate
};
262 #define TYPES_TERNOPUI (aarch64_types_ternopu_imm_qualifiers)
263 static enum aarch64_type_qualifiers
264 aarch64_types_ternop_sssu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
265 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_unsigned
};
266 #define TYPES_TERNOP_SSSU (aarch64_types_ternop_sssu_qualifiers)
267 static enum aarch64_type_qualifiers
268 aarch64_types_ternop_ssus_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
269 = { qualifier_none
, qualifier_none
, qualifier_unsigned
, qualifier_none
};
270 #define TYPES_TERNOP_SSUS (aarch64_types_ternop_ssus_qualifiers)
271 static enum aarch64_type_qualifiers
272 aarch64_types_ternop_suss_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
273 = { qualifier_none
, qualifier_unsigned
, qualifier_none
, qualifier_none
};
274 #define TYPES_TERNOP_SUSS (aarch64_types_ternop_suss_qualifiers)
275 static enum aarch64_type_qualifiers
276 aarch64_types_binop_pppu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
277 = { qualifier_poly
, qualifier_poly
, qualifier_poly
, qualifier_unsigned
};
278 #define TYPES_TERNOP_PPPU (aarch64_types_binop_pppu_qualifiers)
280 static enum aarch64_type_qualifiers
281 aarch64_types_quadop_lane_pair_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
282 = { qualifier_none
, qualifier_none
, qualifier_none
,
283 qualifier_none
, qualifier_lane_pair_index
};
284 #define TYPES_QUADOP_LANE_PAIR (aarch64_types_quadop_lane_pair_qualifiers)
285 static enum aarch64_type_qualifiers
286 aarch64_types_quadop_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
287 = { qualifier_none
, qualifier_none
, qualifier_none
,
288 qualifier_none
, qualifier_lane_index
};
289 #define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
290 static enum aarch64_type_qualifiers
291 aarch64_types_quadopu_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
292 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
,
293 qualifier_unsigned
, qualifier_lane_index
};
294 #define TYPES_QUADOPU_LANE (aarch64_types_quadopu_lane_qualifiers)
296 static enum aarch64_type_qualifiers
297 aarch64_types_quadopssus_lane_quadtup_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
298 = { qualifier_none
, qualifier_none
, qualifier_unsigned
,
299 qualifier_none
, qualifier_lane_quadtup_index
};
300 #define TYPES_QUADOPSSUS_LANE_QUADTUP \
301 (aarch64_types_quadopssus_lane_quadtup_qualifiers)
302 static enum aarch64_type_qualifiers
303 aarch64_types_quadopsssu_lane_quadtup_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
304 = { qualifier_none
, qualifier_none
, qualifier_none
,
305 qualifier_unsigned
, qualifier_lane_quadtup_index
};
306 #define TYPES_QUADOPSSSU_LANE_QUADTUP \
307 (aarch64_types_quadopsssu_lane_quadtup_qualifiers)
309 static enum aarch64_type_qualifiers
310 aarch64_types_quadopu_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
311 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
,
312 qualifier_unsigned
, qualifier_immediate
};
313 #define TYPES_QUADOPUI (aarch64_types_quadopu_imm_qualifiers)
315 static enum aarch64_type_qualifiers
316 aarch64_types_binop_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
317 = { qualifier_none
, qualifier_none
, qualifier_immediate
};
318 #define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
319 #define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
320 static enum aarch64_type_qualifiers
321 aarch64_types_shift_to_unsigned_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
322 = { qualifier_unsigned
, qualifier_none
, qualifier_immediate
};
323 #define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
324 static enum aarch64_type_qualifiers
325 aarch64_types_fcvt_from_unsigned_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
326 = { qualifier_none
, qualifier_unsigned
, qualifier_immediate
};
327 #define TYPES_FCVTIMM_SUS (aarch64_types_fcvt_from_unsigned_qualifiers)
328 static enum aarch64_type_qualifiers
329 aarch64_types_unsigned_shift_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
330 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_immediate
};
331 #define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
332 #define TYPES_USHIFT2IMM (aarch64_types_ternopu_imm_qualifiers)
333 static enum aarch64_type_qualifiers
334 aarch64_types_shift2_to_unsigned_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
335 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_none
, qualifier_immediate
};
336 #define TYPES_SHIFT2IMM_UUSS (aarch64_types_shift2_to_unsigned_qualifiers)
338 static enum aarch64_type_qualifiers
339 aarch64_types_ternop_s_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
340 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_immediate
};
341 #define TYPES_SETREG (aarch64_types_ternop_s_imm_qualifiers)
342 #define TYPES_SHIFTINSERT (aarch64_types_ternop_s_imm_qualifiers)
343 #define TYPES_SHIFTACC (aarch64_types_ternop_s_imm_qualifiers)
344 #define TYPES_SHIFT2IMM (aarch64_types_ternop_s_imm_qualifiers)
346 static enum aarch64_type_qualifiers
347 aarch64_types_ternop_p_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
348 = { qualifier_poly
, qualifier_poly
, qualifier_poly
, qualifier_immediate
};
349 #define TYPES_SHIFTINSERTP (aarch64_types_ternop_p_imm_qualifiers)
351 static enum aarch64_type_qualifiers
352 aarch64_types_unsigned_shiftacc_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
353 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
,
354 qualifier_immediate
};
355 #define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
357 static enum aarch64_type_qualifiers
358 aarch64_types_load1_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
359 = { qualifier_none
, qualifier_const_pointer_map_mode
};
360 #define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
361 #define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
362 static enum aarch64_type_qualifiers
363 aarch64_types_load1_u_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
364 = { qualifier_unsigned
, qualifier_const_pointer_map_mode
};
365 #define TYPES_LOAD1_U (aarch64_types_load1_u_qualifiers)
366 #define TYPES_LOADSTRUCT_U (aarch64_types_load1_u_qualifiers)
367 static enum aarch64_type_qualifiers
368 aarch64_types_load1_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
369 = { qualifier_poly
, qualifier_const_pointer_map_mode
};
370 #define TYPES_LOAD1_P (aarch64_types_load1_p_qualifiers)
371 #define TYPES_LOADSTRUCT_P (aarch64_types_load1_p_qualifiers)
373 static enum aarch64_type_qualifiers
374 aarch64_types_loadstruct_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
375 = { qualifier_none
, qualifier_const_pointer_map_mode
,
376 qualifier_none
, qualifier_struct_load_store_lane_index
};
377 #define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
378 static enum aarch64_type_qualifiers
379 aarch64_types_loadstruct_lane_u_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
380 = { qualifier_unsigned
, qualifier_const_pointer_map_mode
,
381 qualifier_unsigned
, qualifier_struct_load_store_lane_index
};
382 #define TYPES_LOADSTRUCT_LANE_U (aarch64_types_loadstruct_lane_u_qualifiers)
383 static enum aarch64_type_qualifiers
384 aarch64_types_loadstruct_lane_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
385 = { qualifier_poly
, qualifier_const_pointer_map_mode
,
386 qualifier_poly
, qualifier_struct_load_store_lane_index
};
387 #define TYPES_LOADSTRUCT_LANE_P (aarch64_types_loadstruct_lane_p_qualifiers)
389 static enum aarch64_type_qualifiers
390 aarch64_types_bsl_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
391 = { qualifier_poly
, qualifier_unsigned
,
392 qualifier_poly
, qualifier_poly
};
393 #define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
394 static enum aarch64_type_qualifiers
395 aarch64_types_bsl_s_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
396 = { qualifier_none
, qualifier_unsigned
,
397 qualifier_none
, qualifier_none
};
398 #define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
399 static enum aarch64_type_qualifiers
400 aarch64_types_bsl_u_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
401 = { qualifier_unsigned
, qualifier_unsigned
,
402 qualifier_unsigned
, qualifier_unsigned
};
403 #define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
405 /* The first argument (return type) of a store should be void type,
406 which we represent with qualifier_void. Their first operand will be
407 a DImode pointer to the location to store to, so we must use
408 qualifier_map_mode | qualifier_pointer to build a pointer to the
409 element type of the vector. */
410 static enum aarch64_type_qualifiers
411 aarch64_types_store1_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
412 = { qualifier_void
, qualifier_pointer_map_mode
, qualifier_none
};
413 #define TYPES_STORE1 (aarch64_types_store1_qualifiers)
414 #define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
415 static enum aarch64_type_qualifiers
416 aarch64_types_store1_u_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
417 = { qualifier_void
, qualifier_pointer_map_mode
, qualifier_unsigned
};
418 #define TYPES_STORE1_U (aarch64_types_store1_u_qualifiers)
419 #define TYPES_STORESTRUCT_U (aarch64_types_store1_u_qualifiers)
420 static enum aarch64_type_qualifiers
421 aarch64_types_store1_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
422 = { qualifier_void
, qualifier_pointer_map_mode
, qualifier_poly
};
423 #define TYPES_STORE1_P (aarch64_types_store1_p_qualifiers)
424 #define TYPES_STORESTRUCT_P (aarch64_types_store1_p_qualifiers)
426 static enum aarch64_type_qualifiers
427 aarch64_types_storestruct_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
428 = { qualifier_void
, qualifier_pointer_map_mode
,
429 qualifier_none
, qualifier_struct_load_store_lane_index
};
430 #define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
431 static enum aarch64_type_qualifiers
432 aarch64_types_storestruct_lane_u_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
433 = { qualifier_void
, qualifier_pointer_map_mode
,
434 qualifier_unsigned
, qualifier_struct_load_store_lane_index
};
435 #define TYPES_STORESTRUCT_LANE_U (aarch64_types_storestruct_lane_u_qualifiers)
436 static enum aarch64_type_qualifiers
437 aarch64_types_storestruct_lane_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
438 = { qualifier_void
, qualifier_pointer_map_mode
,
439 qualifier_poly
, qualifier_struct_load_store_lane_index
};
440 #define TYPES_STORESTRUCT_LANE_P (aarch64_types_storestruct_lane_p_qualifiers)
442 #define CF0(N, X) CODE_FOR_aarch64_##N##X
443 #define CF1(N, X) CODE_FOR_##N##X##1
444 #define CF2(N, X) CODE_FOR_##N##X##2
445 #define CF3(N, X) CODE_FOR_##N##X##3
446 #define CF4(N, X) CODE_FOR_##N##X##4
447 #define CF10(N, X) CODE_FOR_##N##X
449 #define VAR1(T, N, MAP, FLAG, A) \
450 {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T, FLAG_##FLAG},
451 #define VAR2(T, N, MAP, FLAG, A, B) \
452 VAR1 (T, N, MAP, FLAG, A) \
453 VAR1 (T, N, MAP, FLAG, B)
454 #define VAR3(T, N, MAP, FLAG, A, B, C) \
455 VAR2 (T, N, MAP, FLAG, A, B) \
456 VAR1 (T, N, MAP, FLAG, C)
457 #define VAR4(T, N, MAP, FLAG, A, B, C, D) \
458 VAR3 (T, N, MAP, FLAG, A, B, C) \
459 VAR1 (T, N, MAP, FLAG, D)
460 #define VAR5(T, N, MAP, FLAG, A, B, C, D, E) \
461 VAR4 (T, N, MAP, FLAG, A, B, C, D) \
462 VAR1 (T, N, MAP, FLAG, E)
463 #define VAR6(T, N, MAP, FLAG, A, B, C, D, E, F) \
464 VAR5 (T, N, MAP, FLAG, A, B, C, D, E) \
465 VAR1 (T, N, MAP, FLAG, F)
466 #define VAR7(T, N, MAP, FLAG, A, B, C, D, E, F, G) \
467 VAR6 (T, N, MAP, FLAG, A, B, C, D, E, F) \
468 VAR1 (T, N, MAP, FLAG, G)
469 #define VAR8(T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
470 VAR7 (T, N, MAP, FLAG, A, B, C, D, E, F, G) \
471 VAR1 (T, N, MAP, FLAG, H)
472 #define VAR9(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
473 VAR8 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
474 VAR1 (T, N, MAP, FLAG, I)
475 #define VAR10(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
476 VAR9 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
477 VAR1 (T, N, MAP, FLAG, J)
478 #define VAR11(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
479 VAR10 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
480 VAR1 (T, N, MAP, FLAG, K)
481 #define VAR12(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
482 VAR11 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
483 VAR1 (T, N, MAP, FLAG, L)
484 #define VAR13(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
485 VAR12 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
486 VAR1 (T, N, MAP, FLAG, M)
487 #define VAR14(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
488 VAR13 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
489 VAR1 (T, X, MAP, FLAG, N)
490 #define VAR15(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
491 VAR14 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
492 VAR1 (T, X, MAP, FLAG, O)
493 #define VAR16(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
494 VAR15 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
495 VAR1 (T, X, MAP, FLAG, P)
497 #include "aarch64-builtin-iterators.h"
499 static aarch64_simd_builtin_datum aarch64_simd_builtin_data
[] = {
500 #include "aarch64-simd-builtins.def"
503 /* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
504 #define AARCH64_CRC32_BUILTINS \
505 CRC32_BUILTIN (crc32b, QI) \
506 CRC32_BUILTIN (crc32h, HI) \
507 CRC32_BUILTIN (crc32w, SI) \
508 CRC32_BUILTIN (crc32x, DI) \
509 CRC32_BUILTIN (crc32cb, QI) \
510 CRC32_BUILTIN (crc32ch, HI) \
511 CRC32_BUILTIN (crc32cw, SI) \
512 CRC32_BUILTIN (crc32cx, DI)
514 /* The next 8 FCMLA instrinsics require some special handling compared the
515 normal simd intrinsics. */
516 #define AARCH64_SIMD_FCMLA_LANEQ_BUILTINS \
517 FCMLA_LANEQ_BUILTIN (0, v2sf, fcmla, V2SF, false) \
518 FCMLA_LANEQ_BUILTIN (90, v2sf, fcmla, V2SF, false) \
519 FCMLA_LANEQ_BUILTIN (180, v2sf, fcmla, V2SF, false) \
520 FCMLA_LANEQ_BUILTIN (270, v2sf, fcmla, V2SF, false) \
521 FCMLA_LANEQ_BUILTIN (0, v4hf, fcmla_laneq, V4HF, true) \
522 FCMLA_LANEQ_BUILTIN (90, v4hf, fcmla_laneq, V4HF, true) \
523 FCMLA_LANEQ_BUILTIN (180, v4hf, fcmla_laneq, V4HF, true) \
524 FCMLA_LANEQ_BUILTIN (270, v4hf, fcmla_laneq, V4HF, true) \
530 const enum insn_code icode
;
532 } aarch64_crc_builtin_datum
;
534 /* Hold information about how to expand the FCMLA_LANEQ builtins. */
539 const enum insn_code icode
;
542 } aarch64_fcmla_laneq_builtin_datum
;
544 #define CRC32_BUILTIN(N, M) \
547 #define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
548 AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M,
551 #define VAR1(T, N, MAP, FLAG, A) \
552 AARCH64_SIMD_BUILTIN_##T##_##N##A,
554 enum aarch64_builtins
558 AARCH64_BUILTIN_GET_FPCR
,
559 AARCH64_BUILTIN_SET_FPCR
,
560 AARCH64_BUILTIN_GET_FPSR
,
561 AARCH64_BUILTIN_SET_FPSR
,
563 AARCH64_BUILTIN_GET_FPCR64
,
564 AARCH64_BUILTIN_SET_FPCR64
,
565 AARCH64_BUILTIN_GET_FPSR64
,
566 AARCH64_BUILTIN_SET_FPSR64
,
568 AARCH64_BUILTIN_RSQRT_DF
,
569 AARCH64_BUILTIN_RSQRT_SF
,
570 AARCH64_BUILTIN_RSQRT_V2DF
,
571 AARCH64_BUILTIN_RSQRT_V2SF
,
572 AARCH64_BUILTIN_RSQRT_V4SF
,
573 AARCH64_SIMD_BUILTIN_BASE
,
574 AARCH64_SIMD_BUILTIN_LANE_CHECK
,
575 #include "aarch64-simd-builtins.def"
576 /* The first enum element which is based on an insn_data pattern. */
577 AARCH64_SIMD_PATTERN_START
= AARCH64_SIMD_BUILTIN_LANE_CHECK
+ 1,
578 AARCH64_SIMD_BUILTIN_MAX
= AARCH64_SIMD_PATTERN_START
579 + ARRAY_SIZE (aarch64_simd_builtin_data
) - 1,
580 AARCH64_CRC32_BUILTIN_BASE
,
581 AARCH64_CRC32_BUILTINS
582 AARCH64_CRC32_BUILTIN_MAX
,
583 /* ARMv8.3-A Pointer Authentication Builtins. */
584 AARCH64_PAUTH_BUILTIN_AUTIA1716
,
585 AARCH64_PAUTH_BUILTIN_PACIA1716
,
586 AARCH64_PAUTH_BUILTIN_AUTIB1716
,
587 AARCH64_PAUTH_BUILTIN_PACIB1716
,
588 AARCH64_PAUTH_BUILTIN_XPACLRI
,
589 /* Special cased Armv8.3-A Complex FMA by Lane quad Builtins. */
590 AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE
,
591 AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
592 /* Builtin for Arm8.3-a Javascript conversion instruction. */
595 AARCH64_TME_BUILTIN_TSTART
,
596 AARCH64_TME_BUILTIN_TCOMMIT
,
597 AARCH64_TME_BUILTIN_TTEST
,
598 AARCH64_TME_BUILTIN_TCANCEL
,
599 /* Armv8.5-a RNG instruction builtins. */
600 AARCH64_BUILTIN_RNG_RNDR
,
601 AARCH64_BUILTIN_RNG_RNDRRS
,
602 /* MEMTAG builtins. */
603 AARCH64_MEMTAG_BUILTIN_START
,
604 AARCH64_MEMTAG_BUILTIN_IRG
,
605 AARCH64_MEMTAG_BUILTIN_GMI
,
606 AARCH64_MEMTAG_BUILTIN_SUBP
,
607 AARCH64_MEMTAG_BUILTIN_INC_TAG
,
608 AARCH64_MEMTAG_BUILTIN_SET_TAG
,
609 AARCH64_MEMTAG_BUILTIN_GET_TAG
,
610 AARCH64_MEMTAG_BUILTIN_END
,
612 AARCH64_LS64_BUILTIN_LD64B
,
613 AARCH64_LS64_BUILTIN_ST64B
,
614 AARCH64_LS64_BUILTIN_ST64BV
,
615 AARCH64_LS64_BUILTIN_ST64BV0
,
620 #define CRC32_BUILTIN(N, M) \
621 {"__builtin_aarch64_"#N, E_##M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
623 static aarch64_crc_builtin_datum aarch64_crc_builtin_data
[] = {
624 AARCH64_CRC32_BUILTINS
628 #undef FCMLA_LANEQ_BUILTIN
629 #define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
630 {"__builtin_aarch64_fcmla_laneq"#I#N, E_##M##mode, CODE_FOR_aarch64_##X##I##N, \
631 AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M, T},
633 /* This structure contains how to manage the mapping form the builtin to the
634 instruction to generate in the backend and how to invoke the instruction. */
635 static aarch64_fcmla_laneq_builtin_datum aarch64_fcmla_lane_builtin_data
[] = {
636 AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
641 static GTY(()) tree aarch64_builtin_decls
[AARCH64_BUILTIN_MAX
];
643 #define NUM_DREG_TYPES 6
644 #define NUM_QREG_TYPES 6
646 /* Internal scalar builtin types. These types are used to support
647 neon intrinsic builtins. They are _not_ user-visible types. Therefore
648 the mangling for these types are implementation defined. */
649 const char *aarch64_scalar_builtin_types
[] = {
650 "__builtin_aarch64_simd_qi",
651 "__builtin_aarch64_simd_hi",
652 "__builtin_aarch64_simd_si",
653 "__builtin_aarch64_simd_hf",
654 "__builtin_aarch64_simd_sf",
655 "__builtin_aarch64_simd_di",
656 "__builtin_aarch64_simd_df",
657 "__builtin_aarch64_simd_poly8",
658 "__builtin_aarch64_simd_poly16",
659 "__builtin_aarch64_simd_poly64",
660 "__builtin_aarch64_simd_poly128",
661 "__builtin_aarch64_simd_ti",
662 "__builtin_aarch64_simd_uqi",
663 "__builtin_aarch64_simd_uhi",
664 "__builtin_aarch64_simd_usi",
665 "__builtin_aarch64_simd_udi",
666 "__builtin_aarch64_simd_ei",
667 "__builtin_aarch64_simd_oi",
668 "__builtin_aarch64_simd_ci",
669 "__builtin_aarch64_simd_xi",
670 "__builtin_aarch64_simd_bf",
674 #define ENTRY(E, M, Q, G) E,
675 enum aarch64_simd_type
677 #include "aarch64-simd-builtin-types.def"
678 ARM_NEON_H_TYPES_LAST
682 struct GTY(()) aarch64_simd_type_info
684 enum aarch64_simd_type type
;
686 /* Internal type name. */
689 /* Internal type name(mangled). The mangled names conform to the
690 AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
691 Appendix A). To qualify for emission with the mangled names defined in
692 that document, a vector type must not only be of the correct mode but also
693 be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
694 types are registered by aarch64_init_simd_builtin_types (). In other
695 words, vector types defined in other ways e.g. via vector_size attribute
696 will get default mangled names. */
705 /* Machine mode the internal type maps to. */
706 enum machine_mode mode
;
709 enum aarch64_type_qualifiers q
;
712 #define ENTRY(E, M, Q, G) \
713 {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, E_##M##mode, qualifier_##Q},
714 static GTY(()) struct aarch64_simd_type_info aarch64_simd_types
[] = {
715 #include "aarch64-simd-builtin-types.def"
719 static GTY(()) tree aarch64_simd_tuple_types
[ARM_NEON_H_TYPES_LAST
][3];
721 static GTY(()) tree aarch64_simd_intOI_type_node
= NULL_TREE
;
722 static GTY(()) tree aarch64_simd_intCI_type_node
= NULL_TREE
;
723 static GTY(()) tree aarch64_simd_intXI_type_node
= NULL_TREE
;
725 /* The user-visible __fp16 type, and a pointer to that type. Used
726 across the back-end. */
727 tree aarch64_fp16_type_node
= NULL_TREE
;
728 tree aarch64_fp16_ptr_type_node
= NULL_TREE
;
730 /* Back-end node type for brain float (bfloat) types. */
731 tree aarch64_bf16_type_node
= NULL_TREE
;
732 tree aarch64_bf16_ptr_type_node
= NULL_TREE
;
734 /* Wrapper around add_builtin_function. NAME is the name of the built-in
735 function, TYPE is the function type, CODE is the function subcode
736 (relative to AARCH64_BUILTIN_GENERAL), and ATTRS is the function
739 aarch64_general_add_builtin (const char *name
, tree type
, unsigned int code
,
740 tree attrs
= NULL_TREE
)
742 code
= (code
<< AARCH64_BUILTIN_SHIFT
) | AARCH64_BUILTIN_GENERAL
;
743 return add_builtin_function (name
, type
, code
, BUILT_IN_MD
,
748 aarch64_mangle_builtin_scalar_type (const_tree type
)
752 while (aarch64_scalar_builtin_types
[i
] != NULL
)
754 const char *name
= aarch64_scalar_builtin_types
[i
];
756 if (TREE_CODE (TYPE_NAME (type
)) == TYPE_DECL
757 && DECL_NAME (TYPE_NAME (type
))
758 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
))), name
))
759 return aarch64_scalar_builtin_types
[i
];
766 aarch64_mangle_builtin_vector_type (const_tree type
)
768 tree attrs
= TYPE_ATTRIBUTES (type
);
769 if (tree attr
= lookup_attribute ("Advanced SIMD type", attrs
))
771 tree mangled_name
= TREE_VALUE (TREE_VALUE (attr
));
772 return IDENTIFIER_POINTER (mangled_name
);
779 aarch64_general_mangle_builtin_type (const_tree type
)
782 /* Walk through all the AArch64 builtins types tables to filter out the
784 if ((mangle
= aarch64_mangle_builtin_vector_type (type
))
785 || (mangle
= aarch64_mangle_builtin_scalar_type (type
)))
792 aarch64_simd_builtin_std_type (machine_mode mode
,
793 enum aarch64_type_qualifiers q
)
795 #define QUAL_TYPE(M) \
796 ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
800 return QUAL_TYPE (QI
);
802 return QUAL_TYPE (HI
);
804 return QUAL_TYPE (SI
);
806 return QUAL_TYPE (DI
);
808 return QUAL_TYPE (TI
);
810 return aarch64_simd_intOI_type_node
;
812 return aarch64_simd_intCI_type_node
;
814 return aarch64_simd_intXI_type_node
;
816 return aarch64_fp16_type_node
;
818 return float_type_node
;
820 return double_type_node
;
822 return aarch64_bf16_type_node
;
830 aarch64_lookup_simd_builtin_type (machine_mode mode
,
831 enum aarch64_type_qualifiers q
)
834 int nelts
= sizeof (aarch64_simd_types
) / sizeof (aarch64_simd_types
[0]);
836 /* Non-poly scalar modes map to standard types not in the table. */
837 if (q
!= qualifier_poly
&& !VECTOR_MODE_P (mode
))
838 return aarch64_simd_builtin_std_type (mode
, q
);
840 for (i
= 0; i
< nelts
; i
++)
842 if (aarch64_simd_types
[i
].mode
== mode
843 && aarch64_simd_types
[i
].q
== q
)
844 return aarch64_simd_types
[i
].itype
;
845 if (aarch64_simd_tuple_types
[i
][0] != NULL_TREE
)
846 for (int j
= 0; j
< 3; j
++)
847 if (TYPE_MODE (aarch64_simd_tuple_types
[i
][j
]) == mode
848 && aarch64_simd_types
[i
].q
== q
)
849 return aarch64_simd_tuple_types
[i
][j
];
856 aarch64_simd_builtin_type (machine_mode mode
,
857 bool unsigned_p
, bool poly_p
)
860 return aarch64_lookup_simd_builtin_type (mode
, qualifier_poly
);
862 return aarch64_lookup_simd_builtin_type (mode
, qualifier_unsigned
);
864 return aarch64_lookup_simd_builtin_type (mode
, qualifier_none
);
868 aarch64_init_simd_builtin_types (void)
871 int nelts
= sizeof (aarch64_simd_types
) / sizeof (aarch64_simd_types
[0]);
874 /* Init all the element types built by the front-end. */
875 aarch64_simd_types
[Int8x8_t
].eltype
= intQI_type_node
;
876 aarch64_simd_types
[Int8x16_t
].eltype
= intQI_type_node
;
877 aarch64_simd_types
[Int16x4_t
].eltype
= intHI_type_node
;
878 aarch64_simd_types
[Int16x8_t
].eltype
= intHI_type_node
;
879 aarch64_simd_types
[Int32x2_t
].eltype
= intSI_type_node
;
880 aarch64_simd_types
[Int32x4_t
].eltype
= intSI_type_node
;
881 aarch64_simd_types
[Int64x1_t
].eltype
= intDI_type_node
;
882 aarch64_simd_types
[Int64x2_t
].eltype
= intDI_type_node
;
883 aarch64_simd_types
[Uint8x8_t
].eltype
= unsigned_intQI_type_node
;
884 aarch64_simd_types
[Uint8x16_t
].eltype
= unsigned_intQI_type_node
;
885 aarch64_simd_types
[Uint16x4_t
].eltype
= unsigned_intHI_type_node
;
886 aarch64_simd_types
[Uint16x8_t
].eltype
= unsigned_intHI_type_node
;
887 aarch64_simd_types
[Uint32x2_t
].eltype
= unsigned_intSI_type_node
;
888 aarch64_simd_types
[Uint32x4_t
].eltype
= unsigned_intSI_type_node
;
889 aarch64_simd_types
[Uint64x1_t
].eltype
= unsigned_intDI_type_node
;
890 aarch64_simd_types
[Uint64x2_t
].eltype
= unsigned_intDI_type_node
;
892 /* Poly types are a world of their own. */
893 aarch64_simd_types
[Poly8_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
=
894 build_distinct_type_copy (unsigned_intQI_type_node
);
895 /* Prevent front-ends from transforming Poly8_t arrays into string
897 TYPE_STRING_FLAG (aarch64_simd_types
[Poly8_t
].eltype
) = false;
899 aarch64_simd_types
[Poly16_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
=
900 build_distinct_type_copy (unsigned_intHI_type_node
);
901 aarch64_simd_types
[Poly64_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
=
902 build_distinct_type_copy (unsigned_intDI_type_node
);
903 aarch64_simd_types
[Poly128_t
].eltype
= aarch64_simd_types
[Poly128_t
].itype
=
904 build_distinct_type_copy (unsigned_intTI_type_node
);
905 /* Init poly vector element types with scalar poly types. */
906 aarch64_simd_types
[Poly8x8_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
;
907 aarch64_simd_types
[Poly8x16_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
;
908 aarch64_simd_types
[Poly16x4_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
;
909 aarch64_simd_types
[Poly16x8_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
;
910 aarch64_simd_types
[Poly64x1_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
;
911 aarch64_simd_types
[Poly64x2_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
;
913 /* Continue with standard types. */
914 aarch64_simd_types
[Float16x4_t
].eltype
= aarch64_fp16_type_node
;
915 aarch64_simd_types
[Float16x8_t
].eltype
= aarch64_fp16_type_node
;
916 aarch64_simd_types
[Float32x2_t
].eltype
= float_type_node
;
917 aarch64_simd_types
[Float32x4_t
].eltype
= float_type_node
;
918 aarch64_simd_types
[Float64x1_t
].eltype
= double_type_node
;
919 aarch64_simd_types
[Float64x2_t
].eltype
= double_type_node
;
921 /* Init Bfloat vector types with underlying __bf16 type. */
922 aarch64_simd_types
[Bfloat16x4_t
].eltype
= aarch64_bf16_type_node
;
923 aarch64_simd_types
[Bfloat16x8_t
].eltype
= aarch64_bf16_type_node
;
925 for (i
= 0; i
< nelts
; i
++)
927 tree eltype
= aarch64_simd_types
[i
].eltype
;
928 machine_mode mode
= aarch64_simd_types
[i
].mode
;
930 if (aarch64_simd_types
[i
].itype
== NULL
)
932 tree type
= build_vector_type (eltype
, GET_MODE_NUNITS (mode
));
933 type
= build_distinct_type_copy (type
);
934 SET_TYPE_STRUCTURAL_EQUALITY (type
);
936 tree mangled_name
= get_identifier (aarch64_simd_types
[i
].mangle
);
937 tree value
= tree_cons (NULL_TREE
, mangled_name
, NULL_TREE
);
938 TYPE_ATTRIBUTES (type
)
939 = tree_cons (get_identifier ("Advanced SIMD type"), value
,
940 TYPE_ATTRIBUTES (type
));
941 aarch64_simd_types
[i
].itype
= type
;
944 tdecl
= add_builtin_type (aarch64_simd_types
[i
].name
,
945 aarch64_simd_types
[i
].itype
);
946 TYPE_NAME (aarch64_simd_types
[i
].itype
) = tdecl
;
949 #define AARCH64_BUILD_SIGNED_TYPE(mode) \
950 make_signed_type (GET_MODE_PRECISION (mode));
951 aarch64_simd_intOI_type_node
= AARCH64_BUILD_SIGNED_TYPE (OImode
);
952 aarch64_simd_intCI_type_node
= AARCH64_BUILD_SIGNED_TYPE (CImode
);
953 aarch64_simd_intXI_type_node
= AARCH64_BUILD_SIGNED_TYPE (XImode
);
954 #undef AARCH64_BUILD_SIGNED_TYPE
956 tdecl
= add_builtin_type
957 ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node
);
958 TYPE_NAME (aarch64_simd_intOI_type_node
) = tdecl
;
959 tdecl
= add_builtin_type
960 ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node
);
961 TYPE_NAME (aarch64_simd_intCI_type_node
) = tdecl
;
962 tdecl
= add_builtin_type
963 ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node
);
964 TYPE_NAME (aarch64_simd_intXI_type_node
) = tdecl
;
968 aarch64_init_simd_builtin_scalar_types (void)
970 /* Define typedefs for all the standard scalar types. */
971 (*lang_hooks
.types
.register_builtin_type
) (intQI_type_node
,
972 "__builtin_aarch64_simd_qi");
973 (*lang_hooks
.types
.register_builtin_type
) (intHI_type_node
,
974 "__builtin_aarch64_simd_hi");
975 (*lang_hooks
.types
.register_builtin_type
) (aarch64_fp16_type_node
,
976 "__builtin_aarch64_simd_hf");
977 (*lang_hooks
.types
.register_builtin_type
) (intSI_type_node
,
978 "__builtin_aarch64_simd_si");
979 (*lang_hooks
.types
.register_builtin_type
) (float_type_node
,
980 "__builtin_aarch64_simd_sf");
981 (*lang_hooks
.types
.register_builtin_type
) (intDI_type_node
,
982 "__builtin_aarch64_simd_di");
983 (*lang_hooks
.types
.register_builtin_type
) (double_type_node
,
984 "__builtin_aarch64_simd_df");
985 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intQI_type_node
,
986 "__builtin_aarch64_simd_poly8");
987 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intHI_type_node
,
988 "__builtin_aarch64_simd_poly16");
989 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intDI_type_node
,
990 "__builtin_aarch64_simd_poly64");
991 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intTI_type_node
,
992 "__builtin_aarch64_simd_poly128");
993 (*lang_hooks
.types
.register_builtin_type
) (intTI_type_node
,
994 "__builtin_aarch64_simd_ti");
995 (*lang_hooks
.types
.register_builtin_type
) (aarch64_bf16_type_node
,
996 "__builtin_aarch64_simd_bf");
997 /* Unsigned integer types for various mode sizes. */
998 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intQI_type_node
,
999 "__builtin_aarch64_simd_uqi");
1000 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intHI_type_node
,
1001 "__builtin_aarch64_simd_uhi");
1002 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intSI_type_node
,
1003 "__builtin_aarch64_simd_usi");
1004 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intDI_type_node
,
1005 "__builtin_aarch64_simd_udi");
1008 /* Return a set of FLAG_* flags derived from FLAGS
1009 that describe what a function with result MODE could do,
1010 taking the command-line flags into account. */
1012 aarch64_call_properties (unsigned int flags
, machine_mode mode
)
1014 if (!(flags
& FLAG_AUTO_FP
) && FLOAT_MODE_P (mode
))
1017 /* -fno-trapping-math means that we can assume any FP exceptions
1018 are not user-visible. */
1019 if (!flag_trapping_math
)
1020 flags
&= ~FLAG_RAISE_FP_EXCEPTIONS
;
1025 /* Return true if calls to a function with flags F and mode MODE
1026 could modify some form of global state. */
1028 aarch64_modifies_global_state_p (unsigned int f
, machine_mode mode
)
1030 unsigned int flags
= aarch64_call_properties (f
, mode
);
1032 if (flags
& FLAG_RAISE_FP_EXCEPTIONS
)
1035 if (flags
& FLAG_PREFETCH_MEMORY
)
1038 return flags
& FLAG_WRITE_MEMORY
;
1041 /* Return true if calls to a function with flags F and mode MODE
1042 could read some form of global state. */
1044 aarch64_reads_global_state_p (unsigned int f
, machine_mode mode
)
1046 unsigned int flags
= aarch64_call_properties (f
, mode
);
1048 if (flags
& FLAG_READ_FPCR
)
1051 return flags
& FLAG_READ_MEMORY
;
1054 /* Return true if calls to a function with flags F and mode MODE
1055 could raise a signal. */
1057 aarch64_could_trap_p (unsigned int f
, machine_mode mode
)
1059 unsigned int flags
= aarch64_call_properties (f
, mode
);
1061 if (flags
& FLAG_RAISE_FP_EXCEPTIONS
)
1064 if (flags
& (FLAG_READ_MEMORY
| FLAG_WRITE_MEMORY
))
1070 /* Add attribute NAME to ATTRS. */
1072 aarch64_add_attribute (const char *name
, tree attrs
)
1074 return tree_cons (get_identifier (name
), NULL_TREE
, attrs
);
1077 /* Return the appropriate attributes for a function that has
1078 flags F and mode MODE. */
1080 aarch64_get_attributes (unsigned int f
, machine_mode mode
)
1082 tree attrs
= NULL_TREE
;
1084 if (!aarch64_modifies_global_state_p (f
, mode
))
1086 if (aarch64_reads_global_state_p (f
, mode
))
1087 attrs
= aarch64_add_attribute ("pure", attrs
);
1089 attrs
= aarch64_add_attribute ("const", attrs
);
1092 if (!flag_non_call_exceptions
|| !aarch64_could_trap_p (f
, mode
))
1093 attrs
= aarch64_add_attribute ("nothrow", attrs
);
1095 return aarch64_add_attribute ("leaf", attrs
);
1098 static bool aarch64_simd_builtins_initialized_p
= false;
1100 /* Due to the architecture not providing lane variant of the lane instructions
1101 for fcmla we can't use the standard simd builtin expansion code, but we
1102 still want the majority of the validation that would normally be done. */
1105 aarch64_init_fcmla_laneq_builtins (void)
1109 for (i
= 0; i
< ARRAY_SIZE (aarch64_fcmla_lane_builtin_data
); ++i
)
1111 aarch64_fcmla_laneq_builtin_datum
* d
1112 = &aarch64_fcmla_lane_builtin_data
[i
];
1113 tree argtype
= aarch64_lookup_simd_builtin_type (d
->mode
, qualifier_none
);
1114 machine_mode quadmode
= GET_MODE_2XWIDER_MODE (d
->mode
).require ();
1116 = aarch64_lookup_simd_builtin_type (quadmode
, qualifier_none
);
1118 = aarch64_simd_builtin_std_type (SImode
, qualifier_lane_pair_index
);
1119 tree ftype
= build_function_type_list (argtype
, argtype
, argtype
,
1120 quadtype
, lanetype
, NULL_TREE
);
1121 tree attrs
= aarch64_get_attributes (FLAG_FP
, d
->mode
);
1123 = aarch64_general_add_builtin (d
->name
, ftype
, d
->fcode
, attrs
);
1125 aarch64_builtin_decls
[d
->fcode
] = fndecl
;
1130 aarch64_init_simd_builtin_functions (bool called_from_pragma
)
1132 unsigned int i
, fcode
= AARCH64_SIMD_PATTERN_START
;
1134 if (!called_from_pragma
)
1136 tree lane_check_fpr
= build_function_type_list (void_type_node
,
1141 aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_LANE_CHECK
]
1142 = aarch64_general_add_builtin ("__builtin_aarch64_im_lane_boundsi",
1144 AARCH64_SIMD_BUILTIN_LANE_CHECK
);
1147 for (i
= 0; i
< ARRAY_SIZE (aarch64_simd_builtin_data
); i
++, fcode
++)
1149 bool print_type_signature_p
= false;
1150 char type_signature
[SIMD_MAX_BUILTIN_ARGS
+ 1] = { 0 };
1151 aarch64_simd_builtin_datum
*d
= &aarch64_simd_builtin_data
[i
];
1158 /* We must track two variables here. op_num is
1159 the operand number as in the RTL pattern. This is
1160 required to access the mode (e.g. V4SF mode) of the
1161 argument, from which the base type can be derived.
1162 arg_num is an index in to the qualifiers data, which
1163 gives qualifiers to the type (e.g. const unsigned).
1164 The reason these two variables may differ by one is the
1165 void return type. While all return types take the 0th entry
1166 in the qualifiers array, there is no operand for them in the
1168 int op_num
= insn_data
[d
->code
].n_operands
- 1;
1169 int arg_num
= d
->qualifiers
[0] & qualifier_void
1172 tree return_type
= void_type_node
, args
= void_list_node
;
1175 int struct_mode_args
= 0;
1176 for (int j
= op_num
; j
>= 0; j
--)
1178 machine_mode op_mode
= insn_data
[d
->code
].operand
[j
].mode
;
1179 if (aarch64_advsimd_struct_mode_p (op_mode
))
1183 if ((called_from_pragma
&& struct_mode_args
== 0)
1184 || (!called_from_pragma
&& struct_mode_args
> 0))
1187 /* Build a function type directly from the insn_data for this
1188 builtin. The build_function_type () function takes care of
1189 removing duplicates for us. */
1190 for (; op_num
>= 0; arg_num
--, op_num
--)
1192 machine_mode op_mode
= insn_data
[d
->code
].operand
[op_num
].mode
;
1193 enum aarch64_type_qualifiers qualifiers
= d
->qualifiers
[arg_num
];
1195 if (qualifiers
& qualifier_unsigned
)
1197 type_signature
[op_num
] = 'u';
1198 print_type_signature_p
= true;
1200 else if (qualifiers
& qualifier_poly
)
1202 type_signature
[op_num
] = 'p';
1203 print_type_signature_p
= true;
1206 type_signature
[op_num
] = 's';
1208 /* Skip an internal operand for vget_{low, high}. */
1209 if (qualifiers
& qualifier_internal
)
1212 /* Some builtins have different user-facing types
1213 for certain arguments, encoded in d->mode. */
1214 if (qualifiers
& qualifier_map_mode
)
1217 /* For pointers, we want a pointer to the basic type
1219 if (qualifiers
& qualifier_pointer
&& VECTOR_MODE_P (op_mode
))
1220 op_mode
= GET_MODE_INNER (op_mode
);
1222 eltype
= aarch64_simd_builtin_type
1224 (qualifiers
& qualifier_unsigned
) != 0,
1225 (qualifiers
& qualifier_poly
) != 0);
1226 gcc_assert (eltype
!= NULL
);
1228 /* Add qualifiers. */
1229 if (qualifiers
& qualifier_const
)
1230 eltype
= build_qualified_type (eltype
, TYPE_QUAL_CONST
);
1232 if (qualifiers
& qualifier_pointer
)
1233 eltype
= build_pointer_type (eltype
);
1235 /* If we have reached arg_num == 0, we are at a non-void
1236 return type. Otherwise, we are still processing
1239 return_type
= eltype
;
1241 args
= tree_cons (NULL_TREE
, eltype
, args
);
1244 ftype
= build_function_type (return_type
, args
);
1246 gcc_assert (ftype
!= NULL
);
1248 if (print_type_signature_p
)
1249 snprintf (namebuf
, sizeof (namebuf
), "__builtin_aarch64_%s_%s",
1250 d
->name
, type_signature
);
1252 snprintf (namebuf
, sizeof (namebuf
), "__builtin_aarch64_%s",
1255 tree attrs
= aarch64_get_attributes (d
->flags
, d
->mode
);
1257 if (called_from_pragma
)
1259 unsigned int raw_code
1260 = (fcode
<< AARCH64_BUILTIN_SHIFT
) | AARCH64_BUILTIN_GENERAL
;
1261 fndecl
= simulate_builtin_function_decl (input_location
, namebuf
,
1262 ftype
, raw_code
, NULL
,
1266 fndecl
= aarch64_general_add_builtin (namebuf
, ftype
, fcode
, attrs
);
1268 aarch64_builtin_decls
[fcode
] = fndecl
;
1272 /* Register the tuple type that contains NUM_VECTORS of the AdvSIMD type
1273 indexed by TYPE_INDEX. */
1275 register_tuple_type (unsigned int num_vectors
, unsigned int type_index
)
1277 aarch64_simd_type_info
*type
= &aarch64_simd_types
[type_index
];
1279 /* Synthesize the name of the user-visible vector tuple type. */
1280 const char *vector_type_name
= type
->name
;
1281 char tuple_type_name
[sizeof ("bfloat16x4x2_t")];
1282 snprintf (tuple_type_name
, sizeof (tuple_type_name
), "%.*sx%d_t",
1283 (int) strlen (vector_type_name
) - 4, vector_type_name
+ 2,
1285 tuple_type_name
[0] = TOLOWER (tuple_type_name
[0]);
1287 tree vector_type
= type
->itype
;
1288 tree array_type
= build_array_type_nelts (vector_type
, num_vectors
);
1289 if (type
->mode
== DImode
)
1291 if (num_vectors
== 2)
1292 SET_TYPE_MODE (array_type
, V2x1DImode
);
1293 else if (num_vectors
== 3)
1294 SET_TYPE_MODE (array_type
, V3x1DImode
);
1295 else if (num_vectors
== 4)
1296 SET_TYPE_MODE (array_type
, V4x1DImode
);
1299 unsigned int alignment
1300 = (known_eq (GET_MODE_SIZE (type
->mode
), 16) ? 128 : 64);
1301 gcc_assert (TYPE_MODE_RAW (array_type
) == TYPE_MODE (array_type
)
1302 && TYPE_ALIGN (array_type
) == alignment
);
1304 tree field
= build_decl (input_location
, FIELD_DECL
,
1305 get_identifier ("val"), array_type
);
1307 tree t
= lang_hooks
.types
.simulate_record_decl (input_location
,
1309 make_array_slice (&field
,
1311 gcc_assert (TYPE_MODE_RAW (t
) == TYPE_MODE (t
)
1312 && TYPE_ALIGN (t
) == alignment
);
1314 if (num_vectors
== 2)
1315 aarch64_simd_tuple_types
[type_index
][0] = t
;
1316 else if (num_vectors
== 3)
1317 aarch64_simd_tuple_types
[type_index
][1] = t
;
1318 else if (num_vectors
== 4)
1319 aarch64_simd_tuple_types
[type_index
][2] = t
;
1323 aarch64_scalar_builtin_type_p (aarch64_simd_type t
)
1325 return (t
== Poly8_t
|| t
== Poly16_t
|| t
== Poly64_t
|| t
== Poly128_t
);
1328 /* Implement #pragma GCC aarch64 "arm_neon.h". */
1330 handle_arm_neon_h (void)
1332 /* Register the AdvSIMD vector tuple types. */
1333 for (unsigned int i
= 0; i
< ARM_NEON_H_TYPES_LAST
; i
++)
1334 for (unsigned int count
= 2; count
<= 4; ++count
)
1335 if (!aarch64_scalar_builtin_type_p (aarch64_simd_types
[i
].type
))
1336 register_tuple_type (count
, i
);
1338 aarch64_init_simd_builtin_functions (true);
1342 aarch64_init_simd_builtins (void)
1344 if (aarch64_simd_builtins_initialized_p
)
1347 aarch64_simd_builtins_initialized_p
= true;
1349 aarch64_init_simd_builtin_types ();
1351 /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
1352 Therefore we need to preserve the old __builtin scalar types. It can be
1353 removed once all the intrinsics become strongly typed using the qualifier
1355 aarch64_init_simd_builtin_scalar_types ();
1357 aarch64_init_simd_builtin_functions (false);
1359 handle_arm_neon_h ();
1361 /* Initialize the remaining fcmla_laneq intrinsics. */
1362 aarch64_init_fcmla_laneq_builtins ();
1366 aarch64_init_crc32_builtins ()
1368 tree usi_type
= aarch64_simd_builtin_std_type (SImode
, qualifier_unsigned
);
1371 for (i
= 0; i
< ARRAY_SIZE (aarch64_crc_builtin_data
); ++i
)
1373 aarch64_crc_builtin_datum
* d
= &aarch64_crc_builtin_data
[i
];
1374 tree argtype
= aarch64_simd_builtin_std_type (d
->mode
,
1375 qualifier_unsigned
);
1376 tree ftype
= build_function_type_list (usi_type
, usi_type
, argtype
, NULL_TREE
);
1377 tree attrs
= aarch64_get_attributes (FLAG_NONE
, d
->mode
);
1379 = aarch64_general_add_builtin (d
->name
, ftype
, d
->fcode
, attrs
);
1381 aarch64_builtin_decls
[d
->fcode
] = fndecl
;
1385 /* Add builtins for reciprocal square root. */
1388 aarch64_init_builtin_rsqrt (void)
1393 tree V2SF_type_node
= build_vector_type (float_type_node
, 2);
1394 tree V2DF_type_node
= build_vector_type (double_type_node
, 2);
1395 tree V4SF_type_node
= build_vector_type (float_type_node
, 4);
1397 struct builtin_decls_data
1400 const char *builtin_name
;
1404 builtin_decls_data bdda
[] =
1406 { double_type_node
, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF
},
1407 { float_type_node
, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF
},
1408 { V2DF_type_node
, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF
},
1409 { V2SF_type_node
, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF
},
1410 { V4SF_type_node
, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF
}
1413 builtin_decls_data
*bdd
= bdda
;
1414 builtin_decls_data
*bdd_end
= bdd
+ (sizeof (bdda
) / sizeof (builtin_decls_data
));
1416 for (; bdd
< bdd_end
; bdd
++)
1418 ftype
= build_function_type_list (bdd
->type_node
, bdd
->type_node
, NULL_TREE
);
1419 tree attrs
= aarch64_get_attributes (FLAG_FP
, TYPE_MODE (bdd
->type_node
));
1420 fndecl
= aarch64_general_add_builtin (bdd
->builtin_name
,
1421 ftype
, bdd
->function_code
, attrs
);
1422 aarch64_builtin_decls
[bdd
->function_code
] = fndecl
;
1426 /* Initialize the backend types that support the user-visible __fp16
1427 type, also initialize a pointer to that type, to be used when
1431 aarch64_init_fp16_types (void)
1433 aarch64_fp16_type_node
= make_node (REAL_TYPE
);
1434 TYPE_PRECISION (aarch64_fp16_type_node
) = 16;
1435 layout_type (aarch64_fp16_type_node
);
1437 (*lang_hooks
.types
.register_builtin_type
) (aarch64_fp16_type_node
, "__fp16");
1438 aarch64_fp16_ptr_type_node
= build_pointer_type (aarch64_fp16_type_node
);
1441 /* Initialize the backend REAL_TYPE type supporting bfloat types. */
1443 aarch64_init_bf16_types (void)
1445 aarch64_bf16_type_node
= make_node (REAL_TYPE
);
1446 TYPE_PRECISION (aarch64_bf16_type_node
) = 16;
1447 SET_TYPE_MODE (aarch64_bf16_type_node
, BFmode
);
1448 layout_type (aarch64_bf16_type_node
);
1450 lang_hooks
.types
.register_builtin_type (aarch64_bf16_type_node
, "__bf16");
1451 aarch64_bf16_ptr_type_node
= build_pointer_type (aarch64_bf16_type_node
);
1454 /* Pointer authentication builtins that will become NOP on legacy platform.
1455 Currently, these builtins are for internal use only (libgcc EH unwinder). */
1458 aarch64_init_pauth_hint_builtins (void)
1460 /* Pointer Authentication builtins. */
1461 tree ftype_pointer_auth
1462 = build_function_type_list (ptr_type_node
, ptr_type_node
,
1463 unsigned_intDI_type_node
, NULL_TREE
);
1464 tree ftype_pointer_strip
1465 = build_function_type_list (ptr_type_node
, ptr_type_node
, NULL_TREE
);
1467 aarch64_builtin_decls
[AARCH64_PAUTH_BUILTIN_AUTIA1716
]
1468 = aarch64_general_add_builtin ("__builtin_aarch64_autia1716",
1470 AARCH64_PAUTH_BUILTIN_AUTIA1716
);
1471 aarch64_builtin_decls
[AARCH64_PAUTH_BUILTIN_PACIA1716
]
1472 = aarch64_general_add_builtin ("__builtin_aarch64_pacia1716",
1474 AARCH64_PAUTH_BUILTIN_PACIA1716
);
1475 aarch64_builtin_decls
[AARCH64_PAUTH_BUILTIN_AUTIB1716
]
1476 = aarch64_general_add_builtin ("__builtin_aarch64_autib1716",
1478 AARCH64_PAUTH_BUILTIN_AUTIB1716
);
1479 aarch64_builtin_decls
[AARCH64_PAUTH_BUILTIN_PACIB1716
]
1480 = aarch64_general_add_builtin ("__builtin_aarch64_pacib1716",
1482 AARCH64_PAUTH_BUILTIN_PACIB1716
);
1483 aarch64_builtin_decls
[AARCH64_PAUTH_BUILTIN_XPACLRI
]
1484 = aarch64_general_add_builtin ("__builtin_aarch64_xpaclri",
1485 ftype_pointer_strip
,
1486 AARCH64_PAUTH_BUILTIN_XPACLRI
);
1489 /* Initialize the transactional memory extension (TME) builtins. */
1491 aarch64_init_tme_builtins (void)
1493 tree ftype_uint64_void
1494 = build_function_type_list (uint64_type_node
, NULL
);
1495 tree ftype_void_void
1496 = build_function_type_list (void_type_node
, NULL
);
1497 tree ftype_void_uint64
1498 = build_function_type_list (void_type_node
, uint64_type_node
, NULL
);
1500 aarch64_builtin_decls
[AARCH64_TME_BUILTIN_TSTART
]
1501 = aarch64_general_add_builtin ("__builtin_aarch64_tstart",
1503 AARCH64_TME_BUILTIN_TSTART
);
1504 aarch64_builtin_decls
[AARCH64_TME_BUILTIN_TTEST
]
1505 = aarch64_general_add_builtin ("__builtin_aarch64_ttest",
1507 AARCH64_TME_BUILTIN_TTEST
);
1508 aarch64_builtin_decls
[AARCH64_TME_BUILTIN_TCOMMIT
]
1509 = aarch64_general_add_builtin ("__builtin_aarch64_tcommit",
1511 AARCH64_TME_BUILTIN_TCOMMIT
);
1512 aarch64_builtin_decls
[AARCH64_TME_BUILTIN_TCANCEL
]
1513 = aarch64_general_add_builtin ("__builtin_aarch64_tcancel",
1515 AARCH64_TME_BUILTIN_TCANCEL
);
1518 /* Add builtins for Random Number instructions. */
1521 aarch64_init_rng_builtins (void)
1523 tree unsigned_ptr_type
= build_pointer_type (unsigned_intDI_type_node
);
1525 = build_function_type_list (integer_type_node
, unsigned_ptr_type
, NULL
);
1526 aarch64_builtin_decls
[AARCH64_BUILTIN_RNG_RNDR
]
1527 = aarch64_general_add_builtin ("__builtin_aarch64_rndr", ftype
,
1528 AARCH64_BUILTIN_RNG_RNDR
);
1529 aarch64_builtin_decls
[AARCH64_BUILTIN_RNG_RNDRRS
]
1530 = aarch64_general_add_builtin ("__builtin_aarch64_rndrrs", ftype
,
1531 AARCH64_BUILTIN_RNG_RNDRRS
);
1534 /* Initialize the memory tagging extension (MTE) builtins. */
1538 enum insn_code icode
;
1539 } aarch64_memtag_builtin_data
[AARCH64_MEMTAG_BUILTIN_END
-
1540 AARCH64_MEMTAG_BUILTIN_START
- 1];
1543 aarch64_init_memtag_builtins (void)
1547 #define AARCH64_INIT_MEMTAG_BUILTINS_DECL(F, N, I, T) \
1548 aarch64_builtin_decls[AARCH64_MEMTAG_BUILTIN_##F] \
1549 = aarch64_general_add_builtin ("__builtin_aarch64_memtag_"#N, \
1550 T, AARCH64_MEMTAG_BUILTIN_##F); \
1551 aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_##F - \
1552 AARCH64_MEMTAG_BUILTIN_START - 1] = \
1555 fntype
= build_function_type_list (ptr_type_node
, ptr_type_node
,
1556 uint64_type_node
, NULL
);
1557 AARCH64_INIT_MEMTAG_BUILTINS_DECL (IRG
, irg
, irg
, fntype
);
1559 fntype
= build_function_type_list (uint64_type_node
, ptr_type_node
,
1560 uint64_type_node
, NULL
);
1561 AARCH64_INIT_MEMTAG_BUILTINS_DECL (GMI
, gmi
, gmi
, fntype
);
1563 fntype
= build_function_type_list (ptrdiff_type_node
, ptr_type_node
,
1564 ptr_type_node
, NULL
);
1565 AARCH64_INIT_MEMTAG_BUILTINS_DECL (SUBP
, subp
, subp
, fntype
);
1567 fntype
= build_function_type_list (ptr_type_node
, ptr_type_node
,
1568 unsigned_type_node
, NULL
);
1569 AARCH64_INIT_MEMTAG_BUILTINS_DECL (INC_TAG
, inc_tag
, addg
, fntype
);
1571 fntype
= build_function_type_list (void_type_node
, ptr_type_node
, NULL
);
1572 AARCH64_INIT_MEMTAG_BUILTINS_DECL (SET_TAG
, set_tag
, stg
, fntype
);
1574 fntype
= build_function_type_list (ptr_type_node
, ptr_type_node
, NULL
);
1575 AARCH64_INIT_MEMTAG_BUILTINS_DECL (GET_TAG
, get_tag
, ldg
, fntype
);
1577 #undef AARCH64_INIT_MEMTAG_BUILTINS_DECL
1580 /* Add builtins for Load/store 64 Byte instructions. */
1587 } ls64_builtins_data
;
1589 static GTY(()) tree ls64_arm_data_t
= NULL_TREE
;
1592 aarch64_init_ls64_builtins_types (void)
1598 } __arm_data512_t; */
1599 const char *tuple_type_name
= "__arm_data512_t";
1600 tree node_type
= get_typenode_from_name (UINT64_TYPE
);
1601 tree array_type
= build_array_type_nelts (node_type
, 8);
1602 SET_TYPE_MODE (array_type
, V8DImode
);
1604 gcc_assert (TYPE_MODE_RAW (array_type
) == TYPE_MODE (array_type
));
1605 gcc_assert (TYPE_ALIGN (array_type
) == 64);
1607 tree field
= build_decl (input_location
, FIELD_DECL
,
1608 get_identifier ("val"), array_type
);
1610 ls64_arm_data_t
= lang_hooks
.types
.simulate_record_decl (input_location
,
1612 make_array_slice (&field
, 1));
1614 gcc_assert (TYPE_MODE (ls64_arm_data_t
) == V8DImode
);
1615 gcc_assert (TYPE_MODE_RAW (ls64_arm_data_t
) == TYPE_MODE (ls64_arm_data_t
));
1616 gcc_assert (TYPE_ALIGN (ls64_arm_data_t
) == 64);
1620 aarch64_init_ls64_builtins (void)
1622 aarch64_init_ls64_builtins_types ();
1624 ls64_builtins_data data
[4] = {
1625 {"__builtin_aarch64_ld64b", AARCH64_LS64_BUILTIN_LD64B
,
1626 build_function_type_list (ls64_arm_data_t
,
1627 const_ptr_type_node
, NULL_TREE
)},
1628 {"__builtin_aarch64_st64b", AARCH64_LS64_BUILTIN_ST64B
,
1629 build_function_type_list (void_type_node
, ptr_type_node
,
1630 ls64_arm_data_t
, NULL_TREE
)},
1631 {"__builtin_aarch64_st64bv", AARCH64_LS64_BUILTIN_ST64BV
,
1632 build_function_type_list (uint64_type_node
, ptr_type_node
,
1633 ls64_arm_data_t
, NULL_TREE
)},
1634 {"__builtin_aarch64_st64bv0", AARCH64_LS64_BUILTIN_ST64BV0
,
1635 build_function_type_list (uint64_type_node
, ptr_type_node
,
1636 ls64_arm_data_t
, NULL_TREE
)},
1639 for (size_t i
= 0; i
< ARRAY_SIZE (data
); ++i
)
1640 aarch64_builtin_decls
[data
[i
].code
]
1641 = aarch64_general_add_builtin (data
[i
].name
, data
[i
].type
, data
[i
].code
);
1644 /* Initialize fpsr fpcr getters and setters. */
1647 aarch64_init_fpsr_fpcr_builtins (void)
1650 = build_function_type_list (void_type_node
, unsigned_type_node
, NULL
);
1652 = build_function_type_list (unsigned_type_node
, NULL
);
1654 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR
]
1655 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr",
1657 AARCH64_BUILTIN_GET_FPCR
);
1658 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR
]
1659 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr",
1661 AARCH64_BUILTIN_SET_FPCR
);
1662 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR
]
1663 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr",
1665 AARCH64_BUILTIN_GET_FPSR
);
1666 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR
]
1667 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr",
1669 AARCH64_BUILTIN_SET_FPSR
);
1672 = build_function_type_list (void_type_node
, long_long_unsigned_type_node
,
1675 = build_function_type_list (long_long_unsigned_type_node
, NULL
);
1677 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR64
]
1678 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr64",
1680 AARCH64_BUILTIN_GET_FPCR64
);
1681 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR64
]
1682 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr64",
1684 AARCH64_BUILTIN_SET_FPCR64
);
1685 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR64
]
1686 = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr64",
1688 AARCH64_BUILTIN_GET_FPSR64
);
1689 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR64
]
1690 = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr64",
1692 AARCH64_BUILTIN_SET_FPSR64
);
1695 /* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group. */
1698 aarch64_general_init_builtins (void)
1700 aarch64_init_fpsr_fpcr_builtins ();
1702 aarch64_init_fp16_types ();
1704 aarch64_init_bf16_types ();
1707 aarch64_init_simd_builtins ();
1709 aarch64_init_crc32_builtins ();
1710 aarch64_init_builtin_rsqrt ();
1711 aarch64_init_rng_builtins ();
1714 = build_function_type_list (intSI_type_node
, double_type_node
, NULL
);
1715 aarch64_builtin_decls
[AARCH64_JSCVT
]
1716 = aarch64_general_add_builtin ("__builtin_aarch64_jcvtzs", ftype_jcvt
,
1719 /* Initialize pointer authentication builtins which are backed by instructions
1720 in NOP encoding space.
1722 NOTE: these builtins are supposed to be used by libgcc unwinder only, as
1723 there is no support on return address signing under ILP32, we don't
1726 aarch64_init_pauth_hint_builtins ();
1729 aarch64_init_tme_builtins ();
1732 aarch64_init_memtag_builtins ();
1735 aarch64_init_ls64_builtins ();
1738 /* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group. */
1740 aarch64_general_builtin_decl (unsigned code
, bool)
1742 if (code
>= AARCH64_BUILTIN_MAX
)
1743 return error_mark_node
;
1745 return aarch64_builtin_decls
[code
];
1750 SIMD_ARG_COPY_TO_REG
,
1752 SIMD_ARG_LANE_INDEX
,
1753 SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX
,
1754 SIMD_ARG_LANE_PAIR_INDEX
,
1755 SIMD_ARG_LANE_QUADTUP_INDEX
,
1761 aarch64_simd_expand_args (rtx target
, int icode
, int have_retval
,
1762 tree exp
, builtin_simd_arg
*args
,
1763 machine_mode builtin_mode
)
1766 rtx op
[SIMD_MAX_BUILTIN_ARGS
+ 1]; /* First element for result operand. */
1771 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
1773 || GET_MODE (target
) != tmode
1774 || !(*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
1775 target
= gen_reg_rtx (tmode
);
1781 builtin_simd_arg thisarg
= args
[opc
- have_retval
];
1783 if (thisarg
== SIMD_ARG_STOP
)
1787 tree arg
= CALL_EXPR_ARG (exp
, opc
- have_retval
);
1788 machine_mode mode
= insn_data
[icode
].operand
[opc
].mode
;
1789 op
[opc
] = expand_normal (arg
);
1793 case SIMD_ARG_COPY_TO_REG
:
1794 if (POINTER_TYPE_P (TREE_TYPE (arg
)))
1795 op
[opc
] = convert_memory_address (Pmode
, op
[opc
]);
1796 /*gcc_assert (GET_MODE (op[opc]) == mode); */
1797 if (!(*insn_data
[icode
].operand
[opc
].predicate
)
1799 op
[opc
] = copy_to_mode_reg (mode
, op
[opc
]);
1802 case SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX
:
1803 gcc_assert (opc
> 1);
1804 if (CONST_INT_P (op
[opc
]))
1807 = GET_MODE_NUNITS (builtin_mode
).to_constant ();
1808 aarch64_simd_lane_bounds (op
[opc
], 0, nunits
, exp
);
1809 /* Keep to GCC-vector-extension lane indices in the RTL. */
1810 op
[opc
] = aarch64_endian_lane_rtx (builtin_mode
,
1815 case SIMD_ARG_LANE_INDEX
:
1816 /* Must be a previous operand into which this is an index. */
1817 gcc_assert (opc
> 0);
1818 if (CONST_INT_P (op
[opc
]))
1820 machine_mode vmode
= insn_data
[icode
].operand
[opc
- 1].mode
;
1822 = GET_MODE_NUNITS (vmode
).to_constant ();
1823 aarch64_simd_lane_bounds (op
[opc
], 0, nunits
, exp
);
1824 /* Keep to GCC-vector-extension lane indices in the RTL. */
1825 op
[opc
] = aarch64_endian_lane_rtx (vmode
, INTVAL (op
[opc
]));
1827 /* If the lane index isn't a constant then error out. */
1830 case SIMD_ARG_LANE_PAIR_INDEX
:
1831 /* Must be a previous operand into which this is an index and
1832 index is restricted to nunits / 2. */
1833 gcc_assert (opc
> 0);
1834 if (CONST_INT_P (op
[opc
]))
1836 machine_mode vmode
= insn_data
[icode
].operand
[opc
- 1].mode
;
1838 = GET_MODE_NUNITS (vmode
).to_constant ();
1839 aarch64_simd_lane_bounds (op
[opc
], 0, nunits
/ 2, exp
);
1840 /* Keep to GCC-vector-extension lane indices in the RTL. */
1841 int lane
= INTVAL (op
[opc
]);
1842 op
[opc
] = gen_int_mode (ENDIAN_LANE_N (nunits
/ 2, lane
),
1845 /* If the lane index isn't a constant then error out. */
1847 case SIMD_ARG_LANE_QUADTUP_INDEX
:
1848 /* Must be a previous operand into which this is an index and
1849 index is restricted to nunits / 4. */
1850 gcc_assert (opc
> 0);
1851 if (CONST_INT_P (op
[opc
]))
1853 machine_mode vmode
= insn_data
[icode
].operand
[opc
- 1].mode
;
1855 = GET_MODE_NUNITS (vmode
).to_constant ();
1856 aarch64_simd_lane_bounds (op
[opc
], 0, nunits
/ 4, exp
);
1857 /* Keep to GCC-vector-extension lane indices in the RTL. */
1858 int lane
= INTVAL (op
[opc
]);
1859 op
[opc
] = gen_int_mode (ENDIAN_LANE_N (nunits
/ 4, lane
),
1862 /* If the lane index isn't a constant then error out. */
1864 case SIMD_ARG_CONSTANT
:
1866 if (!(*insn_data
[icode
].operand
[opc
].predicate
)
1869 error_at (EXPR_LOCATION (exp
),
1870 "argument %d must be a constant immediate",
1871 opc
+ 1 - have_retval
);
1887 pat
= GEN_FCN (icode
) (op
[0]);
1891 pat
= GEN_FCN (icode
) (op
[0], op
[1]);
1895 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2]);
1899 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3]);
1903 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3], op
[4]);
1907 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3], op
[4], op
[5]);
1922 /* Expand an AArch64 AdvSIMD builtin(intrinsic). */
1924 aarch64_simd_expand_builtin (int fcode
, tree exp
, rtx target
)
1926 if (fcode
== AARCH64_SIMD_BUILTIN_LANE_CHECK
)
1928 rtx totalsize
= expand_normal (CALL_EXPR_ARG (exp
, 0));
1929 rtx elementsize
= expand_normal (CALL_EXPR_ARG (exp
, 1));
1930 if (CONST_INT_P (totalsize
) && CONST_INT_P (elementsize
)
1931 && UINTVAL (elementsize
) != 0
1932 && UINTVAL (totalsize
) != 0)
1934 rtx lane_idx
= expand_normal (CALL_EXPR_ARG (exp
, 2));
1935 if (CONST_INT_P (lane_idx
))
1936 aarch64_simd_lane_bounds (lane_idx
, 0,
1938 / UINTVAL (elementsize
),
1941 error_at (EXPR_LOCATION (exp
),
1942 "lane index must be a constant immediate");
1945 error_at (EXPR_LOCATION (exp
),
1946 "total size and element size must be a non-zero "
1947 "constant immediate");
1948 /* Don't generate any RTL. */
1951 aarch64_simd_builtin_datum
*d
=
1952 &aarch64_simd_builtin_data
[fcode
- AARCH64_SIMD_PATTERN_START
];
1953 enum insn_code icode
= d
->code
;
1954 builtin_simd_arg args
[SIMD_MAX_BUILTIN_ARGS
+ 1];
1955 int num_args
= insn_data
[d
->code
].n_operands
;
1959 is_void
= !!(d
->qualifiers
[0] & qualifier_void
);
1961 num_args
+= is_void
;
1963 for (k
= 1; k
< num_args
; k
++)
1965 /* We have four arrays of data, each indexed in a different fashion.
1966 qualifiers - element 0 always describes the function return type.
1967 operands - element 0 is either the operand for return value (if
1968 the function has a non-void return type) or the operand for the
1970 expr_args - element 0 always holds the first argument.
1971 args - element 0 is always used for the return type. */
1972 int qualifiers_k
= k
;
1973 int operands_k
= k
- is_void
;
1974 int expr_args_k
= k
- 1;
1976 if (d
->qualifiers
[qualifiers_k
] & qualifier_lane_index
)
1977 args
[k
] = SIMD_ARG_LANE_INDEX
;
1978 else if (d
->qualifiers
[qualifiers_k
] & qualifier_lane_pair_index
)
1979 args
[k
] = SIMD_ARG_LANE_PAIR_INDEX
;
1980 else if (d
->qualifiers
[qualifiers_k
] & qualifier_lane_quadtup_index
)
1981 args
[k
] = SIMD_ARG_LANE_QUADTUP_INDEX
;
1982 else if (d
->qualifiers
[qualifiers_k
] & qualifier_struct_load_store_lane_index
)
1983 args
[k
] = SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX
;
1984 else if (d
->qualifiers
[qualifiers_k
] & qualifier_immediate
)
1985 args
[k
] = SIMD_ARG_CONSTANT
;
1986 else if (d
->qualifiers
[qualifiers_k
] & qualifier_maybe_immediate
)
1989 = expand_normal (CALL_EXPR_ARG (exp
,
1991 /* Handle constants only if the predicate allows it. */
1992 bool op_const_int_p
=
1994 && (*insn_data
[icode
].operand
[operands_k
].predicate
)
1995 (arg
, insn_data
[icode
].operand
[operands_k
].mode
));
1996 args
[k
] = op_const_int_p
? SIMD_ARG_CONSTANT
: SIMD_ARG_COPY_TO_REG
;
1999 args
[k
] = SIMD_ARG_COPY_TO_REG
;
2002 args
[k
] = SIMD_ARG_STOP
;
2004 /* The interface to aarch64_simd_expand_args expects a 0 if
2005 the function is void, and a 1 if it is not. */
2006 return aarch64_simd_expand_args
2007 (target
, icode
, !is_void
, exp
, &args
[1], d
->mode
);
2011 aarch64_crc32_expand_builtin (int fcode
, tree exp
, rtx target
)
2014 aarch64_crc_builtin_datum
*d
2015 = &aarch64_crc_builtin_data
[fcode
- (AARCH64_CRC32_BUILTIN_BASE
+ 1)];
2016 enum insn_code icode
= d
->icode
;
2017 tree arg0
= CALL_EXPR_ARG (exp
, 0);
2018 tree arg1
= CALL_EXPR_ARG (exp
, 1);
2019 rtx op0
= expand_normal (arg0
);
2020 rtx op1
= expand_normal (arg1
);
2021 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
2022 machine_mode mode0
= insn_data
[icode
].operand
[1].mode
;
2023 machine_mode mode1
= insn_data
[icode
].operand
[2].mode
;
2026 || GET_MODE (target
) != tmode
2027 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
2028 target
= gen_reg_rtx (tmode
);
2030 gcc_assert ((GET_MODE (op0
) == mode0
|| GET_MODE (op0
) == VOIDmode
)
2031 && (GET_MODE (op1
) == mode1
|| GET_MODE (op1
) == VOIDmode
));
2033 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
2034 op0
= copy_to_mode_reg (mode0
, op0
);
2035 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
2036 op1
= copy_to_mode_reg (mode1
, op1
);
2038 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
2046 /* Function to expand reciprocal square root builtins. */
2049 aarch64_expand_builtin_rsqrt (int fcode
, tree exp
, rtx target
)
2051 tree arg0
= CALL_EXPR_ARG (exp
, 0);
2052 rtx op0
= expand_normal (arg0
);
2054 rtx (*gen
) (rtx
, rtx
);
2058 case AARCH64_BUILTIN_RSQRT_DF
:
2061 case AARCH64_BUILTIN_RSQRT_SF
:
2064 case AARCH64_BUILTIN_RSQRT_V2DF
:
2065 gen
= gen_rsqrtv2df2
;
2067 case AARCH64_BUILTIN_RSQRT_V2SF
:
2068 gen
= gen_rsqrtv2sf2
;
2070 case AARCH64_BUILTIN_RSQRT_V4SF
:
2071 gen
= gen_rsqrtv4sf2
;
2073 default: gcc_unreachable ();
2077 target
= gen_reg_rtx (GET_MODE (op0
));
2079 emit_insn (gen (target
, op0
));
2084 /* Expand a FCMLA lane expression EXP with code FCODE and
2085 result going to TARGET if that is convenient. */
2088 aarch64_expand_fcmla_builtin (tree exp
, rtx target
, int fcode
)
2090 int bcode
= fcode
- AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE
- 1;
2091 aarch64_fcmla_laneq_builtin_datum
* d
2092 = &aarch64_fcmla_lane_builtin_data
[bcode
];
2093 machine_mode quadmode
= GET_MODE_2XWIDER_MODE (d
->mode
).require ();
2094 rtx op0
= force_reg (d
->mode
, expand_normal (CALL_EXPR_ARG (exp
, 0)));
2095 rtx op1
= force_reg (d
->mode
, expand_normal (CALL_EXPR_ARG (exp
, 1)));
2096 rtx op2
= force_reg (quadmode
, expand_normal (CALL_EXPR_ARG (exp
, 2)));
2097 tree tmp
= CALL_EXPR_ARG (exp
, 3);
2098 rtx lane_idx
= expand_expr (tmp
, NULL_RTX
, VOIDmode
, EXPAND_INITIALIZER
);
2100 /* Validate that the lane index is a constant. */
2101 if (!CONST_INT_P (lane_idx
))
2103 error_at (EXPR_LOCATION (exp
),
2104 "argument %d must be a constant immediate", 4);
2108 /* Validate that the index is within the expected range. */
2109 int nunits
= GET_MODE_NUNITS (quadmode
).to_constant ();
2110 aarch64_simd_lane_bounds (lane_idx
, 0, nunits
/ 2, exp
);
2112 /* Generate the correct register and mode. */
2113 int lane
= INTVAL (lane_idx
);
2115 if (lane
< nunits
/ 4)
2116 op2
= simplify_gen_subreg (d
->mode
, op2
, quadmode
,
2117 subreg_lowpart_offset (d
->mode
, quadmode
));
2120 /* Select the upper 64 bits, either a V2SF or V4HF, this however
2121 is quite messy, as the operation required even though simple
2122 doesn't have a simple RTL pattern, and seems it's quite hard to
2123 define using a single RTL pattern. The target generic version
2124 gen_highpart_mode generates code that isn't optimal. */
2125 rtx temp1
= gen_reg_rtx (d
->mode
);
2126 rtx temp2
= gen_reg_rtx (DImode
);
2127 temp1
= simplify_gen_subreg (d
->mode
, op2
, quadmode
,
2128 subreg_lowpart_offset (d
->mode
, quadmode
));
2129 temp1
= simplify_gen_subreg (V2DImode
, temp1
, d
->mode
, 0);
2130 if (BYTES_BIG_ENDIAN
)
2131 emit_insn (gen_aarch64_get_lanev2di (temp2
, temp1
, const0_rtx
));
2133 emit_insn (gen_aarch64_get_lanev2di (temp2
, temp1
, const1_rtx
));
2134 op2
= simplify_gen_subreg (d
->mode
, temp2
, GET_MODE (temp2
), 0);
2136 /* And recalculate the index. */
2140 /* Keep to GCC-vector-extension lane indices in the RTL, only nunits / 4
2141 (max nunits in range check) are valid. Which means only 0-1, so we
2142 only need to know the order in a V2mode. */
2143 lane_idx
= aarch64_endian_lane_rtx (V2DImode
, lane
);
2147 || GET_MODE (target
) != d
->mode
)
2148 target
= gen_reg_rtx (d
->mode
);
2153 pat
= GEN_FCN (d
->icode
) (target
, op0
, op1
, op2
, lane_idx
);
2155 pat
= GEN_FCN (d
->icode
) (target
, op0
, op1
, op2
);
2164 /* Function to expand an expression EXP which calls one of the Transactional
2165 Memory Extension (TME) builtins FCODE with the result going to TARGET. */
2167 aarch64_expand_builtin_tme (int fcode
, tree exp
, rtx target
)
2171 case AARCH64_TME_BUILTIN_TSTART
:
2172 target
= gen_reg_rtx (DImode
);
2173 emit_insn (GEN_FCN (CODE_FOR_tstart
) (target
));
2176 case AARCH64_TME_BUILTIN_TTEST
:
2177 target
= gen_reg_rtx (DImode
);
2178 emit_insn (GEN_FCN (CODE_FOR_ttest
) (target
));
2181 case AARCH64_TME_BUILTIN_TCOMMIT
:
2182 emit_insn (GEN_FCN (CODE_FOR_tcommit
) ());
2185 case AARCH64_TME_BUILTIN_TCANCEL
:
2187 tree arg0
= CALL_EXPR_ARG (exp
, 0);
2188 rtx op0
= expand_normal (arg0
);
2189 if (CONST_INT_P (op0
) && UINTVAL (op0
) <= 65536)
2190 emit_insn (GEN_FCN (CODE_FOR_tcancel
) (op0
));
2193 error_at (EXPR_LOCATION (exp
),
2194 "argument must be a 16-bit constant immediate");
2206 /* Function to expand an expression EXP which calls one of the Load/Store
2207 64 Byte extension (LS64) builtins FCODE with the result going to TARGET. */
2209 aarch64_expand_builtin_ls64 (int fcode
, tree exp
, rtx target
)
2211 expand_operand ops
[3];
2215 case AARCH64_LS64_BUILTIN_LD64B
:
2217 rtx op0
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2218 create_output_operand (&ops
[0], target
, V8DImode
);
2219 create_input_operand (&ops
[1], op0
, DImode
);
2220 expand_insn (CODE_FOR_ld64b
, 2, ops
);
2221 return ops
[0].value
;
2223 case AARCH64_LS64_BUILTIN_ST64B
:
2225 rtx op0
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2226 rtx op1
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2227 create_output_operand (&ops
[0], op0
, DImode
);
2228 create_input_operand (&ops
[1], op1
, V8DImode
);
2229 expand_insn (CODE_FOR_st64b
, 2, ops
);
2232 case AARCH64_LS64_BUILTIN_ST64BV
:
2234 rtx op0
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2235 rtx op1
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2236 create_output_operand (&ops
[0], target
, DImode
);
2237 create_input_operand (&ops
[1], op0
, DImode
);
2238 create_input_operand (&ops
[2], op1
, V8DImode
);
2239 expand_insn (CODE_FOR_st64bv
, 3, ops
);
2240 return ops
[0].value
;
2242 case AARCH64_LS64_BUILTIN_ST64BV0
:
2244 rtx op0
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2245 rtx op1
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2246 create_output_operand (&ops
[0], target
, DImode
);
2247 create_input_operand (&ops
[1], op0
, DImode
);
2248 create_input_operand (&ops
[2], op1
, V8DImode
);
2249 expand_insn (CODE_FOR_st64bv0
, 3, ops
);
2250 return ops
[0].value
;
2257 /* Expand a random number builtin EXP with code FCODE, putting the result
2258 int TARGET. If IGNORE is true the return value is ignored. */
2261 aarch64_expand_rng_builtin (tree exp
, rtx target
, int fcode
, int ignore
)
2264 enum insn_code icode
;
2265 if (fcode
== AARCH64_BUILTIN_RNG_RNDR
)
2266 icode
= CODE_FOR_aarch64_rndr
;
2267 else if (fcode
== AARCH64_BUILTIN_RNG_RNDRRS
)
2268 icode
= CODE_FOR_aarch64_rndrrs
;
2272 rtx rand
= gen_reg_rtx (DImode
);
2273 pat
= GEN_FCN (icode
) (rand
);
2277 tree arg0
= CALL_EXPR_ARG (exp
, 0);
2278 rtx res_addr
= expand_normal (arg0
);
2279 res_addr
= convert_memory_address (Pmode
, res_addr
);
2280 rtx res_mem
= gen_rtx_MEM (DImode
, res_addr
);
2282 emit_move_insn (res_mem
, rand
);
2283 /* If the status result is unused don't generate the CSET code. */
2287 rtx cc_reg
= gen_rtx_REG (CC_Zmode
, CC_REGNUM
);
2288 rtx cmp_rtx
= gen_rtx_fmt_ee (EQ
, SImode
, cc_reg
, const0_rtx
);
2289 emit_insn (gen_aarch64_cstoresi (target
, cmp_rtx
, cc_reg
));
2293 /* Expand an expression EXP that calls a MEMTAG built-in FCODE
2294 with result going to TARGET. */
2296 aarch64_expand_builtin_memtag (int fcode
, tree exp
, rtx target
)
2300 error ("Memory Tagging Extension does not support %<-mabi=ilp32%>");
2305 enum insn_code icode
= aarch64_memtag_builtin_data
[fcode
-
2306 AARCH64_MEMTAG_BUILTIN_START
- 1].icode
;
2308 rtx op0
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2309 machine_mode mode0
= GET_MODE (op0
);
2310 op0
= force_reg (mode0
== VOIDmode
? DImode
: mode0
, op0
);
2311 op0
= convert_to_mode (DImode
, op0
, true);
2315 case AARCH64_MEMTAG_BUILTIN_IRG
:
2316 case AARCH64_MEMTAG_BUILTIN_GMI
:
2317 case AARCH64_MEMTAG_BUILTIN_SUBP
:
2318 case AARCH64_MEMTAG_BUILTIN_INC_TAG
:
2321 || GET_MODE (target
) != DImode
2322 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, DImode
))
2323 target
= gen_reg_rtx (DImode
);
2325 if (fcode
== AARCH64_MEMTAG_BUILTIN_INC_TAG
)
2327 rtx op1
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2329 if ((*insn_data
[icode
].operand
[3].predicate
) (op1
, QImode
))
2331 pat
= GEN_FCN (icode
) (target
, op0
, const0_rtx
, op1
);
2334 error_at (EXPR_LOCATION (exp
),
2335 "argument %d must be a constant immediate "
2336 "in range [0,15]", 2);
2341 rtx op1
= expand_normal (CALL_EXPR_ARG (exp
, 1));
2342 machine_mode mode1
= GET_MODE (op1
);
2343 op1
= force_reg (mode1
== VOIDmode
? DImode
: mode1
, op1
);
2344 op1
= convert_to_mode (DImode
, op1
, true);
2345 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
2349 case AARCH64_MEMTAG_BUILTIN_GET_TAG
:
2351 pat
= GEN_FCN (icode
) (target
, op0
, const0_rtx
);
2353 case AARCH64_MEMTAG_BUILTIN_SET_TAG
:
2354 pat
= GEN_FCN (icode
) (op0
, op0
, const0_rtx
);
2367 /* Expand an expression EXP as fpsr or fpcr setter (depending on
2368 UNSPEC) using MODE. */
2370 aarch64_expand_fpsr_fpcr_setter (int unspec
, machine_mode mode
, tree exp
)
2372 tree arg
= CALL_EXPR_ARG (exp
, 0);
2373 rtx op
= force_reg (mode
, expand_normal (arg
));
2374 emit_insn (gen_aarch64_set (unspec
, mode
, op
));
2377 /* Expand a fpsr or fpcr getter (depending on UNSPEC) using MODE.
2378 Return the target. */
2380 aarch64_expand_fpsr_fpcr_getter (enum insn_code icode
, machine_mode mode
,
2384 create_output_operand (&op
, target
, mode
);
2385 expand_insn (icode
, 1, &op
);
2389 /* Expand an expression EXP that calls built-in function FCODE,
2390 with result going to TARGET if that's convenient. IGNORE is true
2391 if the result of the builtin is ignored. */
2393 aarch64_general_expand_builtin (unsigned int fcode
, tree exp
, rtx target
,
2402 case AARCH64_BUILTIN_GET_FPCR
:
2403 return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpcrsi
,
2405 case AARCH64_BUILTIN_SET_FPCR
:
2406 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR
, SImode
, exp
);
2408 case AARCH64_BUILTIN_GET_FPSR
:
2409 return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpsrsi
,
2411 case AARCH64_BUILTIN_SET_FPSR
:
2412 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR
, SImode
, exp
);
2414 case AARCH64_BUILTIN_GET_FPCR64
:
2415 return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpcrdi
,
2417 case AARCH64_BUILTIN_SET_FPCR64
:
2418 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR
, DImode
, exp
);
2420 case AARCH64_BUILTIN_GET_FPSR64
:
2421 return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpsrdi
,
2423 case AARCH64_BUILTIN_SET_FPSR64
:
2424 aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR
, DImode
, exp
);
2426 case AARCH64_PAUTH_BUILTIN_AUTIA1716
:
2427 case AARCH64_PAUTH_BUILTIN_PACIA1716
:
2428 case AARCH64_PAUTH_BUILTIN_AUTIB1716
:
2429 case AARCH64_PAUTH_BUILTIN_PACIB1716
:
2430 case AARCH64_PAUTH_BUILTIN_XPACLRI
:
2431 arg0
= CALL_EXPR_ARG (exp
, 0);
2432 op0
= force_reg (Pmode
, expand_normal (arg0
));
2434 if (fcode
== AARCH64_PAUTH_BUILTIN_XPACLRI
)
2436 rtx lr
= gen_rtx_REG (Pmode
, R30_REGNUM
);
2437 icode
= CODE_FOR_xpaclri
;
2438 emit_move_insn (lr
, op0
);
2439 emit_insn (GEN_FCN (icode
) ());
2444 tree arg1
= CALL_EXPR_ARG (exp
, 1);
2445 rtx op1
= force_reg (Pmode
, expand_normal (arg1
));
2448 case AARCH64_PAUTH_BUILTIN_AUTIA1716
:
2449 icode
= CODE_FOR_autia1716
;
2451 case AARCH64_PAUTH_BUILTIN_AUTIB1716
:
2452 icode
= CODE_FOR_autib1716
;
2454 case AARCH64_PAUTH_BUILTIN_PACIA1716
:
2455 icode
= CODE_FOR_pacia1716
;
2457 case AARCH64_PAUTH_BUILTIN_PACIB1716
:
2458 icode
= CODE_FOR_pacib1716
;
2465 rtx x16_reg
= gen_rtx_REG (Pmode
, R16_REGNUM
);
2466 rtx x17_reg
= gen_rtx_REG (Pmode
, R17_REGNUM
);
2467 emit_move_insn (x17_reg
, op0
);
2468 emit_move_insn (x16_reg
, op1
);
2469 emit_insn (GEN_FCN (icode
) ());
2475 expand_operand ops
[2];
2476 create_output_operand (&ops
[0], target
, SImode
);
2477 op0
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2478 create_input_operand (&ops
[1], op0
, DFmode
);
2479 expand_insn (CODE_FOR_aarch64_fjcvtzs
, 2, ops
);
2480 return ops
[0].value
;
2483 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V2SF
:
2484 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V2SF
:
2485 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V2SF
:
2486 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V2SF
:
2487 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V4HF
:
2488 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V4HF
:
2489 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V4HF
:
2490 case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V4HF
:
2491 return aarch64_expand_fcmla_builtin (exp
, target
, fcode
);
2492 case AARCH64_BUILTIN_RNG_RNDR
:
2493 case AARCH64_BUILTIN_RNG_RNDRRS
:
2494 return aarch64_expand_rng_builtin (exp
, target
, fcode
, ignore
);
2497 if (fcode
>= AARCH64_SIMD_BUILTIN_BASE
&& fcode
<= AARCH64_SIMD_BUILTIN_MAX
)
2498 return aarch64_simd_expand_builtin (fcode
, exp
, target
);
2499 else if (fcode
>= AARCH64_CRC32_BUILTIN_BASE
&& fcode
<= AARCH64_CRC32_BUILTIN_MAX
)
2500 return aarch64_crc32_expand_builtin (fcode
, exp
, target
);
2502 if (fcode
== AARCH64_BUILTIN_RSQRT_DF
2503 || fcode
== AARCH64_BUILTIN_RSQRT_SF
2504 || fcode
== AARCH64_BUILTIN_RSQRT_V2DF
2505 || fcode
== AARCH64_BUILTIN_RSQRT_V2SF
2506 || fcode
== AARCH64_BUILTIN_RSQRT_V4SF
)
2507 return aarch64_expand_builtin_rsqrt (fcode
, exp
, target
);
2509 if (fcode
== AARCH64_TME_BUILTIN_TSTART
2510 || fcode
== AARCH64_TME_BUILTIN_TCOMMIT
2511 || fcode
== AARCH64_TME_BUILTIN_TTEST
2512 || fcode
== AARCH64_TME_BUILTIN_TCANCEL
)
2513 return aarch64_expand_builtin_tme (fcode
, exp
, target
);
2515 if (fcode
== AARCH64_LS64_BUILTIN_LD64B
2516 || fcode
== AARCH64_LS64_BUILTIN_ST64B
2517 || fcode
== AARCH64_LS64_BUILTIN_ST64BV
2518 || fcode
== AARCH64_LS64_BUILTIN_ST64BV0
)
2519 return aarch64_expand_builtin_ls64 (fcode
, exp
, target
);
2521 if (fcode
>= AARCH64_MEMTAG_BUILTIN_START
2522 && fcode
<= AARCH64_MEMTAG_BUILTIN_END
)
2523 return aarch64_expand_builtin_memtag (fcode
, exp
, target
);
2529 aarch64_builtin_vectorized_function (unsigned int fn
, tree type_out
,
2532 machine_mode in_mode
, out_mode
;
2534 if (TREE_CODE (type_out
) != VECTOR_TYPE
2535 || TREE_CODE (type_in
) != VECTOR_TYPE
)
2538 out_mode
= TYPE_MODE (type_out
);
2539 in_mode
= TYPE_MODE (type_in
);
2541 #undef AARCH64_CHECK_BUILTIN_MODE
2542 #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
2543 #define AARCH64_FIND_FRINT_VARIANT(N) \
2544 (AARCH64_CHECK_BUILTIN_MODE (2, D) \
2545 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
2546 : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
2547 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
2548 : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
2549 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
2553 #undef AARCH64_CHECK_BUILTIN_MODE
2554 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
2555 (out_mode == V##C##N##Fmode && in_mode == V##C##N##Fmode)
2557 return AARCH64_FIND_FRINT_VARIANT (floor
);
2559 return AARCH64_FIND_FRINT_VARIANT (ceil
);
2561 return AARCH64_FIND_FRINT_VARIANT (btrunc
);
2563 return AARCH64_FIND_FRINT_VARIANT (round
);
2565 return AARCH64_FIND_FRINT_VARIANT (nearbyint
);
2567 return AARCH64_FIND_FRINT_VARIANT (sqrt
);
2568 #undef AARCH64_CHECK_BUILTIN_MODE
2569 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
2570 (out_mode == V##C##SImode && in_mode == V##C##N##Imode)
2573 if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
2574 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_clzv4si
];
2579 if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
2580 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si
];
2581 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
2582 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si
];
2585 #undef AARCH64_CHECK_BUILTIN_MODE
2586 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
2587 (out_mode == V##C##N##Imode && in_mode == V##C##N##Fmode)
2592 enum aarch64_builtins builtin
;
2593 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
2594 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di
;
2595 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
2596 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si
;
2597 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
2598 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si
;
2602 return aarch64_builtin_decls
[builtin
];
2608 enum aarch64_builtins builtin
;
2609 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
2610 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di
;
2611 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
2612 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si
;
2613 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
2614 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si
;
2618 return aarch64_builtin_decls
[builtin
];
2624 enum aarch64_builtins builtin
;
2625 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
2626 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di
;
2627 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
2628 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si
;
2629 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
2630 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si
;
2634 return aarch64_builtin_decls
[builtin
];
2643 /* Return builtin for reciprocal square root. */
2646 aarch64_general_builtin_rsqrt (unsigned int fn
)
2648 if (fn
== AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df
)
2649 return aarch64_builtin_decls
[AARCH64_BUILTIN_RSQRT_V2DF
];
2650 if (fn
== AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf
)
2651 return aarch64_builtin_decls
[AARCH64_BUILTIN_RSQRT_V2SF
];
2652 if (fn
== AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf
)
2653 return aarch64_builtin_decls
[AARCH64_BUILTIN_RSQRT_V4SF
];
2657 /* Return true if the lane check can be removed as there is no
2658 error going to be emitted. */
2660 aarch64_fold_builtin_lane_check (tree arg0
, tree arg1
, tree arg2
)
2662 if (TREE_CODE (arg0
) != INTEGER_CST
)
2664 if (TREE_CODE (arg1
) != INTEGER_CST
)
2666 if (TREE_CODE (arg2
) != INTEGER_CST
)
2669 auto totalsize
= wi::to_widest (arg0
);
2670 auto elementsize
= wi::to_widest (arg1
);
2671 if (totalsize
== 0 || elementsize
== 0)
2673 auto lane
= wi::to_widest (arg2
);
2674 auto high
= wi::udiv_trunc (totalsize
, elementsize
);
2675 return wi::ltu_p (lane
, high
);
2679 #define VAR1(T, N, MAP, FLAG, A) \
2680 case AARCH64_SIMD_BUILTIN_##T##_##N##A:
2682 /* Try to fold a call to the built-in function with subcode FCODE. The
2683 function is passed the N_ARGS arguments in ARGS and it returns a value
2684 of type TYPE. Return the new expression on success and NULL_TREE on
2687 aarch64_general_fold_builtin (unsigned int fcode
, tree type
,
2688 unsigned int n_args ATTRIBUTE_UNUSED
, tree
*args
)
2692 BUILTIN_VDQF (UNOP
, abs
, 2, ALL
)
2693 return fold_build1 (ABS_EXPR
, type
, args
[0]);
2694 VAR1 (UNOP
, floatv2si
, 2, ALL
, v2sf
)
2695 VAR1 (UNOP
, floatv4si
, 2, ALL
, v4sf
)
2696 VAR1 (UNOP
, floatv2di
, 2, ALL
, v2df
)
2697 return fold_build1 (FLOAT_EXPR
, type
, args
[0]);
2698 case AARCH64_SIMD_BUILTIN_LANE_CHECK
:
2699 gcc_assert (n_args
== 3);
2700 if (aarch64_fold_builtin_lane_check (args
[0], args
[1], args
[2]))
2710 enum aarch64_simd_type
2711 get_mem_type_for_load_store (unsigned int fcode
)
2715 VAR1 (LOAD1
, ld1
, 0, LOAD
, v8qi
)
2716 VAR1 (STORE1
, st1
, 0, STORE
, v8qi
)
2718 VAR1 (LOAD1
, ld1
, 0, LOAD
, v16qi
)
2719 VAR1 (STORE1
, st1
, 0, STORE
, v16qi
)
2721 VAR1 (LOAD1
, ld1
, 0, LOAD
, v4hi
)
2722 VAR1 (STORE1
, st1
, 0, STORE
, v4hi
)
2724 VAR1 (LOAD1
, ld1
, 0, LOAD
, v8hi
)
2725 VAR1 (STORE1
, st1
, 0, STORE
, v8hi
)
2727 VAR1 (LOAD1
, ld1
, 0, LOAD
, v2si
)
2728 VAR1 (STORE1
, st1
, 0, STORE
, v2si
)
2730 VAR1 (LOAD1
, ld1
, 0, LOAD
, v4si
)
2731 VAR1 (STORE1
, st1
, 0, STORE
, v4si
)
2733 VAR1 (LOAD1
, ld1
, 0, LOAD
, v2di
)
2734 VAR1 (STORE1
, st1
, 0, STORE
, v2di
)
2736 VAR1 (LOAD1_U
, ld1
, 0, LOAD
, v8qi
)
2737 VAR1 (STORE1_U
, st1
, 0, STORE
, v8qi
)
2739 VAR1 (LOAD1_U
, ld1
, 0, LOAD
, v16qi
)
2740 VAR1 (STORE1_U
, st1
, 0, STORE
, v16qi
)
2742 VAR1 (LOAD1_U
, ld1
, 0, LOAD
, v4hi
)
2743 VAR1 (STORE1_U
, st1
, 0, STORE
, v4hi
)
2745 VAR1 (LOAD1_U
, ld1
, 0, LOAD
, v8hi
)
2746 VAR1 (STORE1_U
, st1
, 0, STORE
, v8hi
)
2748 VAR1 (LOAD1_U
, ld1
, 0, LOAD
, v2si
)
2749 VAR1 (STORE1_U
, st1
, 0, STORE
, v2si
)
2751 VAR1 (LOAD1_U
, ld1
, 0, LOAD
, v4si
)
2752 VAR1 (STORE1_U
, st1
, 0, STORE
, v4si
)
2754 VAR1 (LOAD1_U
, ld1
, 0, LOAD
, v2di
)
2755 VAR1 (STORE1_U
, st1
, 0, STORE
, v2di
)
2757 VAR1 (LOAD1_P
, ld1
, 0, LOAD
, v8qi
)
2758 VAR1 (STORE1_P
, st1
, 0, STORE
, v8qi
)
2760 VAR1 (LOAD1_P
, ld1
, 0, LOAD
, v16qi
)
2761 VAR1 (STORE1_P
, st1
, 0, STORE
, v16qi
)
2763 VAR1 (LOAD1_P
, ld1
, 0, LOAD
, v4hi
)
2764 VAR1 (STORE1_P
, st1
, 0, STORE
, v4hi
)
2766 VAR1 (LOAD1_P
, ld1
, 0, LOAD
, v8hi
)
2767 VAR1 (STORE1_P
, st1
, 0, STORE
, v8hi
)
2769 VAR1 (LOAD1_P
, ld1
, 0, LOAD
, v2di
)
2770 VAR1 (STORE1_P
, st1
, 0, STORE
, v2di
)
2772 VAR1 (LOAD1
, ld1
, 0, LOAD
, v4hf
)
2773 VAR1 (STORE1
, st1
, 0, STORE
, v4hf
)
2775 VAR1 (LOAD1
, ld1
, 0, LOAD
, v8hf
)
2776 VAR1 (STORE1
, st1
, 0, STORE
, v8hf
)
2778 VAR1 (LOAD1
, ld1
, 0, LOAD
, v4bf
)
2779 VAR1 (STORE1
, st1
, 0, STORE
, v4bf
)
2780 return Bfloat16x4_t
;
2781 VAR1 (LOAD1
, ld1
, 0, LOAD
, v8bf
)
2782 VAR1 (STORE1
, st1
, 0, STORE
, v8bf
)
2783 return Bfloat16x8_t
;
2784 VAR1 (LOAD1
, ld1
, 0, LOAD
, v2sf
)
2785 VAR1 (STORE1
, st1
, 0, STORE
, v2sf
)
2787 VAR1 (LOAD1
, ld1
, 0, LOAD
, v4sf
)
2788 VAR1 (STORE1
, st1
, 0, STORE
, v4sf
)
2790 VAR1 (LOAD1
, ld1
, 0, LOAD
, v2df
)
2791 VAR1 (STORE1
, st1
, 0, STORE
, v2df
)
2799 /* Try to fold STMT, given that it's a call to the built-in function with
2800 subcode FCODE. Return the new statement on success and null on
2803 aarch64_general_gimple_fold_builtin (unsigned int fcode
, gcall
*stmt
,
2804 gimple_stmt_iterator
*gsi ATTRIBUTE_UNUSED
)
2806 gimple
*new_stmt
= NULL
;
2807 unsigned nargs
= gimple_call_num_args (stmt
);
2808 tree
*args
= (nargs
> 0
2809 ? gimple_call_arg_ptr (stmt
, 0)
2810 : &error_mark_node
);
2812 /* We use gimple's IFN_REDUC_(PLUS|MIN|MAX)s for float, signed int
2813 and unsigned int; it will distinguish according to the types of
2814 the arguments to the __builtin. */
2817 BUILTIN_VALL (UNOP
, reduc_plus_scal_
, 10, ALL
)
2818 new_stmt
= gimple_build_call_internal (IFN_REDUC_PLUS
,
2820 gimple_call_set_lhs (new_stmt
, gimple_call_lhs (stmt
));
2823 /*lower store and load neon builtins to gimple. */
2824 BUILTIN_VALL_F16 (LOAD1
, ld1
, 0, LOAD
)
2825 BUILTIN_VDQ_I (LOAD1_U
, ld1
, 0, LOAD
)
2826 BUILTIN_VALLP_NO_DI (LOAD1_P
, ld1
, 0, LOAD
)
2827 if (!BYTES_BIG_ENDIAN
)
2829 enum aarch64_simd_type mem_type
2830 = get_mem_type_for_load_store(fcode
);
2831 aarch64_simd_type_info simd_type
2832 = aarch64_simd_types
[mem_type
];
2833 tree elt_ptr_type
= build_pointer_type_for_mode (simd_type
.eltype
,
2835 tree zero
= build_zero_cst (elt_ptr_type
);
2836 /* Use element type alignment. */
2838 = build_aligned_type (simd_type
.itype
,
2839 TYPE_ALIGN (simd_type
.eltype
));
2841 = gimple_build_assign (gimple_get_lhs (stmt
),
2842 fold_build2 (MEM_REF
,
2848 BUILTIN_VALL_F16 (STORE1
, st1
, 0, STORE
)
2849 BUILTIN_VDQ_I (STORE1_U
, st1
, 0, STORE
)
2850 BUILTIN_VALLP_NO_DI (STORE1_P
, st1
, 0, STORE
)
2851 if (!BYTES_BIG_ENDIAN
)
2853 enum aarch64_simd_type mem_type
2854 = get_mem_type_for_load_store(fcode
);
2855 aarch64_simd_type_info simd_type
2856 = aarch64_simd_types
[mem_type
];
2857 tree elt_ptr_type
= build_pointer_type_for_mode (simd_type
.eltype
,
2859 tree zero
= build_zero_cst (elt_ptr_type
);
2860 /* Use element type alignment. */
2862 = build_aligned_type (simd_type
.itype
,
2863 TYPE_ALIGN (simd_type
.eltype
));
2865 = gimple_build_assign (fold_build2 (MEM_REF
, access_type
,
2871 BUILTIN_VDQIF (UNOP
, reduc_smax_scal_
, 10, ALL
)
2872 BUILTIN_VDQ_BHSI (UNOPU
, reduc_umax_scal_
, 10, ALL
)
2873 new_stmt
= gimple_build_call_internal (IFN_REDUC_MAX
,
2875 gimple_call_set_lhs (new_stmt
, gimple_call_lhs (stmt
));
2877 BUILTIN_VDQIF (UNOP
, reduc_smin_scal_
, 10, ALL
)
2878 BUILTIN_VDQ_BHSI (UNOPU
, reduc_umin_scal_
, 10, ALL
)
2879 new_stmt
= gimple_build_call_internal (IFN_REDUC_MIN
,
2881 gimple_call_set_lhs (new_stmt
, gimple_call_lhs (stmt
));
2883 BUILTIN_VSDQ_I_DI (BINOP
, ashl
, 3, NONE
)
2884 if (TREE_CODE (args
[1]) == INTEGER_CST
2885 && wi::ltu_p (wi::to_wide (args
[1]), element_precision (args
[0])))
2886 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
2887 LSHIFT_EXPR
, args
[0], args
[1]);
2889 BUILTIN_VSDQ_I_DI (BINOP
, sshl
, 0, NONE
)
2890 BUILTIN_VSDQ_I_DI (BINOP_UUS
, ushl
, 0, NONE
)
2893 tree ctype
= TREE_TYPE (cst
);
2894 /* Left shifts can be both scalar or vector, e.g. uint64x1_t is
2895 treated as a scalar type not a vector one. */
2896 if ((cst
= uniform_integer_cst_p (cst
)) != NULL_TREE
)
2898 wide_int wcst
= wi::to_wide (cst
);
2899 tree unit_ty
= TREE_TYPE (cst
);
2901 wide_int abs_cst
= wi::abs (wcst
);
2902 if (wi::geu_p (abs_cst
, element_precision (args
[0])))
2905 if (wi::neg_p (wcst
, TYPE_SIGN (ctype
)))
2908 final_cst
= wide_int_to_tree (unit_ty
, abs_cst
);
2909 if (TREE_CODE (cst
) != INTEGER_CST
)
2910 final_cst
= build_uniform_cst (ctype
, final_cst
);
2912 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
2913 RSHIFT_EXPR
, args
[0],
2917 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
2918 LSHIFT_EXPR
, args
[0], args
[1]);
2922 BUILTIN_VDQ_I (SHIFTIMM
, ashr
, 3, NONE
)
2923 VAR1 (SHIFTIMM
, ashr_simd
, 0, NONE
, di
)
2924 BUILTIN_VDQ_I (USHIFTIMM
, lshr
, 3, NONE
)
2925 VAR1 (USHIFTIMM
, lshr_simd
, 0, NONE
, di
)
2926 if (TREE_CODE (args
[1]) == INTEGER_CST
2927 && wi::ltu_p (wi::to_wide (args
[1]), element_precision (args
[0])))
2928 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
2929 RSHIFT_EXPR
, args
[0], args
[1]);
2931 BUILTIN_GPF (BINOP
, fmulx
, 0, ALL
)
2933 gcc_assert (nargs
== 2);
2934 bool a0_cst_p
= TREE_CODE (args
[0]) == REAL_CST
;
2935 bool a1_cst_p
= TREE_CODE (args
[1]) == REAL_CST
;
2936 if (a0_cst_p
|| a1_cst_p
)
2938 if (a0_cst_p
&& a1_cst_p
)
2940 tree t0
= TREE_TYPE (args
[0]);
2941 real_value a0
= (TREE_REAL_CST (args
[0]));
2942 real_value a1
= (TREE_REAL_CST (args
[1]));
2943 if (real_equal (&a1
, &dconst0
))
2945 /* According to real_equal (), +0 equals -0. */
2946 if (real_equal (&a0
, &dconst0
) && real_isinf (&a1
))
2948 real_value res
= dconst2
;
2949 res
.sign
= a0
.sign
^ a1
.sign
;
2950 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
2952 build_real (t0
, res
));
2955 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
2959 else /* a0_cst_p ^ a1_cst_p. */
2961 real_value const_part
= a0_cst_p
2962 ? TREE_REAL_CST (args
[0]) : TREE_REAL_CST (args
[1]);
2963 if (!real_equal (&const_part
, &dconst0
)
2964 && !real_isinf (&const_part
))
2965 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
2972 gimple_set_vuse (new_stmt
, gimple_vuse (stmt
));
2973 gimple_set_vdef (new_stmt
, gimple_vdef (stmt
));
2977 case AARCH64_SIMD_BUILTIN_LANE_CHECK
:
2978 if (aarch64_fold_builtin_lane_check (args
[0], args
[1], args
[2]))
2980 unlink_stmt_vdef (stmt
);
2981 release_defs (stmt
);
2982 new_stmt
= gimple_build_nop ();
2992 aarch64_atomic_assign_expand_fenv (tree
*hold
, tree
*clear
, tree
*update
)
2994 const unsigned AARCH64_FE_INVALID
= 1;
2995 const unsigned AARCH64_FE_DIVBYZERO
= 2;
2996 const unsigned AARCH64_FE_OVERFLOW
= 4;
2997 const unsigned AARCH64_FE_UNDERFLOW
= 8;
2998 const unsigned AARCH64_FE_INEXACT
= 16;
2999 const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT
= (AARCH64_FE_INVALID
3000 | AARCH64_FE_DIVBYZERO
3001 | AARCH64_FE_OVERFLOW
3002 | AARCH64_FE_UNDERFLOW
3003 | AARCH64_FE_INEXACT
);
3004 const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT
= 8;
3005 tree fenv_cr
, fenv_sr
, get_fpcr
, set_fpcr
, mask_cr
, mask_sr
;
3006 tree ld_fenv_cr
, ld_fenv_sr
, masked_fenv_cr
, masked_fenv_sr
, hold_fnclex_cr
;
3007 tree hold_fnclex_sr
, new_fenv_var
, reload_fenv
, restore_fnenv
, get_fpsr
, set_fpsr
;
3008 tree update_call
, atomic_feraiseexcept
, hold_fnclex
, masked_fenv
, ld_fenv
;
3010 /* Generate the equivalence of :
3011 unsigned int fenv_cr;
3012 fenv_cr = __builtin_aarch64_get_fpcr ();
3014 unsigned int fenv_sr;
3015 fenv_sr = __builtin_aarch64_get_fpsr ();
3017 Now set all exceptions to non-stop
3018 unsigned int mask_cr
3019 = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
3020 unsigned int masked_cr;
3021 masked_cr = fenv_cr & mask_cr;
3023 And clear all exception flags
3024 unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
3025 unsigned int masked_cr;
3026 masked_sr = fenv_sr & mask_sr;
3028 __builtin_aarch64_set_cr (masked_cr);
3029 __builtin_aarch64_set_sr (masked_sr); */
3031 fenv_cr
= create_tmp_var_raw (unsigned_type_node
);
3032 fenv_sr
= create_tmp_var_raw (unsigned_type_node
);
3034 get_fpcr
= aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR
];
3035 set_fpcr
= aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR
];
3036 get_fpsr
= aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR
];
3037 set_fpsr
= aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR
];
3039 mask_cr
= build_int_cst (unsigned_type_node
,
3040 ~(AARCH64_FE_ALL_EXCEPT
<< AARCH64_FE_EXCEPT_SHIFT
));
3041 mask_sr
= build_int_cst (unsigned_type_node
,
3042 ~(AARCH64_FE_ALL_EXCEPT
));
3044 ld_fenv_cr
= build4 (TARGET_EXPR
, unsigned_type_node
,
3045 fenv_cr
, build_call_expr (get_fpcr
, 0),
3046 NULL_TREE
, NULL_TREE
);
3047 ld_fenv_sr
= build4 (TARGET_EXPR
, unsigned_type_node
,
3048 fenv_sr
, build_call_expr (get_fpsr
, 0),
3049 NULL_TREE
, NULL_TREE
);
3051 masked_fenv_cr
= build2 (BIT_AND_EXPR
, unsigned_type_node
, fenv_cr
, mask_cr
);
3052 masked_fenv_sr
= build2 (BIT_AND_EXPR
, unsigned_type_node
, fenv_sr
, mask_sr
);
3054 hold_fnclex_cr
= build_call_expr (set_fpcr
, 1, masked_fenv_cr
);
3055 hold_fnclex_sr
= build_call_expr (set_fpsr
, 1, masked_fenv_sr
);
3057 hold_fnclex
= build2 (COMPOUND_EXPR
, void_type_node
, hold_fnclex_cr
,
3059 masked_fenv
= build2 (COMPOUND_EXPR
, void_type_node
, masked_fenv_cr
,
3061 ld_fenv
= build2 (COMPOUND_EXPR
, void_type_node
, ld_fenv_cr
, ld_fenv_sr
);
3063 *hold
= build2 (COMPOUND_EXPR
, void_type_node
,
3064 build2 (COMPOUND_EXPR
, void_type_node
, masked_fenv
, ld_fenv
),
3067 /* Store the value of masked_fenv to clear the exceptions:
3068 __builtin_aarch64_set_fpsr (masked_fenv_sr); */
3070 *clear
= build_call_expr (set_fpsr
, 1, masked_fenv_sr
);
3072 /* Generate the equivalent of :
3073 unsigned int new_fenv_var;
3074 new_fenv_var = __builtin_aarch64_get_fpsr ();
3076 __builtin_aarch64_set_fpsr (fenv_sr);
3078 __atomic_feraiseexcept (new_fenv_var); */
3080 new_fenv_var
= create_tmp_var_raw (unsigned_type_node
);
3081 reload_fenv
= build4 (TARGET_EXPR
, unsigned_type_node
,
3082 new_fenv_var
, build_call_expr (get_fpsr
, 0),
3083 NULL_TREE
, NULL_TREE
);
3084 restore_fnenv
= build_call_expr (set_fpsr
, 1, fenv_sr
);
3085 atomic_feraiseexcept
= builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT
);
3086 update_call
= build_call_expr (atomic_feraiseexcept
, 1,
3087 fold_convert (integer_type_node
, new_fenv_var
));
3088 *update
= build2 (COMPOUND_EXPR
, void_type_node
,
3089 build2 (COMPOUND_EXPR
, void_type_node
,
3090 reload_fenv
, restore_fnenv
), update_call
);
3093 /* Resolve overloaded MEMTAG build-in functions. */
3094 #define AARCH64_BUILTIN_SUBCODE(F) \
3095 (DECL_MD_FUNCTION_CODE (F) >> AARCH64_BUILTIN_SHIFT)
3098 aarch64_resolve_overloaded_memtag (location_t loc
,
3099 tree fndecl
, void *pass_params
)
3101 vec
<tree
, va_gc
> *params
= static_cast<vec
<tree
, va_gc
> *> (pass_params
);
3102 unsigned param_num
= params
? params
->length() : 0;
3103 unsigned int fcode
= AARCH64_BUILTIN_SUBCODE (fndecl
);
3104 tree inittype
= aarch64_memtag_builtin_data
[
3105 fcode
- AARCH64_MEMTAG_BUILTIN_START
- 1].ftype
;
3106 unsigned arg_num
= list_length (TYPE_ARG_TYPES (inittype
)) - 1;
3108 if (param_num
!= arg_num
)
3110 TREE_TYPE (fndecl
) = inittype
;
3115 if (fcode
== AARCH64_MEMTAG_BUILTIN_SUBP
)
3117 tree t0
= TREE_TYPE ((*params
)[0]);
3118 tree t1
= TREE_TYPE ((*params
)[1]);
3120 if (t0
== error_mark_node
|| TREE_CODE (t0
) != POINTER_TYPE
)
3122 if (t1
== error_mark_node
|| TREE_CODE (t1
) != POINTER_TYPE
)
3125 if (TYPE_MODE (t0
) != DImode
)
3126 warning_at (loc
, 1, "expected 64-bit address but argument 1 is %d-bit",
3127 (int)tree_to_shwi (DECL_SIZE ((*params
)[0])));
3129 if (TYPE_MODE (t1
) != DImode
)
3130 warning_at (loc
, 1, "expected 64-bit address but argument 2 is %d-bit",
3131 (int)tree_to_shwi (DECL_SIZE ((*params
)[1])));
3133 retype
= build_function_type_list (ptrdiff_type_node
, t0
, t1
, NULL
);
3137 tree t0
= TREE_TYPE ((*params
)[0]);
3139 if (t0
== error_mark_node
|| TREE_CODE (t0
) != POINTER_TYPE
)
3141 TREE_TYPE (fndecl
) = inittype
;
3145 if (TYPE_MODE (t0
) != DImode
)
3146 warning_at (loc
, 1, "expected 64-bit address but argument 1 is %d-bit",
3147 (int)tree_to_shwi (DECL_SIZE ((*params
)[0])));
3151 case AARCH64_MEMTAG_BUILTIN_IRG
:
3152 retype
= build_function_type_list (t0
, t0
, uint64_type_node
, NULL
);
3154 case AARCH64_MEMTAG_BUILTIN_GMI
:
3155 retype
= build_function_type_list (uint64_type_node
, t0
,
3156 uint64_type_node
, NULL
);
3158 case AARCH64_MEMTAG_BUILTIN_INC_TAG
:
3159 retype
= build_function_type_list (t0
, t0
, unsigned_type_node
, NULL
);
3161 case AARCH64_MEMTAG_BUILTIN_SET_TAG
:
3162 retype
= build_function_type_list (void_type_node
, t0
, NULL
);
3164 case AARCH64_MEMTAG_BUILTIN_GET_TAG
:
3165 retype
= build_function_type_list (t0
, t0
, NULL
);
3172 if (!retype
|| retype
== error_mark_node
)
3173 TREE_TYPE (fndecl
) = inittype
;
3175 TREE_TYPE (fndecl
) = retype
;
3180 /* Called at aarch64_resolve_overloaded_builtin in aarch64-c.c. */
3182 aarch64_resolve_overloaded_builtin_general (location_t loc
, tree function
,
3185 unsigned int fcode
= AARCH64_BUILTIN_SUBCODE (function
);
3187 if (fcode
>= AARCH64_MEMTAG_BUILTIN_START
3188 && fcode
<= AARCH64_MEMTAG_BUILTIN_END
)
3189 return aarch64_resolve_overloaded_memtag(loc
, function
, pass_params
);
3194 #undef AARCH64_CHECK_BUILTIN_MODE
3195 #undef AARCH64_FIND_FRINT_VARIANT
3214 #include "gt-aarch64-builtins.h"