1 /* Builtins' description for AArch64 SIMD architecture.
2 Copyright (C) 2011-2016 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/>. */
23 #include "coretypes.h"
26 #include "basic-block.h"
35 #include "diagnostic-core.h"
36 #include "fold-const.h"
37 #include "stor-layout.h"
40 #include "langhooks.h"
41 #include "gimple-iterator.h"
42 #include "case-cfn-macros.h"
44 #define v8qi_UP V8QImode
45 #define v4hi_UP V4HImode
46 #define v4hf_UP V4HFmode
47 #define v2si_UP V2SImode
48 #define v2sf_UP V2SFmode
49 #define v1df_UP V1DFmode
52 #define v16qi_UP V16QImode
53 #define v8hi_UP V8HImode
54 #define v8hf_UP V8HFmode
55 #define v4si_UP V4SImode
56 #define v4sf_UP V4SFmode
57 #define v2di_UP V2DImode
58 #define v2df_UP V2DFmode
70 #define SIMD_MAX_BUILTIN_ARGS 5
72 enum aarch64_type_qualifiers
77 qualifier_unsigned
= 0x1, /* 1 << 0 */
79 qualifier_const
= 0x2, /* 1 << 1 */
81 qualifier_pointer
= 0x4, /* 1 << 2 */
82 /* Used when expanding arguments if an operand could
84 qualifier_immediate
= 0x8, /* 1 << 3 */
85 qualifier_maybe_immediate
= 0x10, /* 1 << 4 */
87 qualifier_void
= 0x20, /* 1 << 5 */
88 /* Some patterns may have internal operands, this qualifier is an
89 instruction to the initialisation code to skip this operand. */
90 qualifier_internal
= 0x40, /* 1 << 6 */
91 /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
92 rather than using the type of the operand. */
93 qualifier_map_mode
= 0x80, /* 1 << 7 */
94 /* qualifier_pointer | qualifier_map_mode */
95 qualifier_pointer_map_mode
= 0x84,
96 /* qualifier_const | qualifier_pointer | qualifier_map_mode */
97 qualifier_const_pointer_map_mode
= 0x86,
98 /* Polynomial types. */
99 qualifier_poly
= 0x100,
100 /* Lane indices - must be in range, and flipped for bigendian. */
101 qualifier_lane_index
= 0x200,
102 /* Lane indices for single lane structure loads and stores. */
103 qualifier_struct_load_store_lane_index
= 0x400
110 const enum insn_code code
;
112 enum aarch64_type_qualifiers
*qualifiers
;
113 } aarch64_simd_builtin_datum
;
115 static enum aarch64_type_qualifiers
116 aarch64_types_unop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
117 = { qualifier_none
, qualifier_none
};
118 #define TYPES_UNOP (aarch64_types_unop_qualifiers)
119 static enum aarch64_type_qualifiers
120 aarch64_types_unopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
121 = { qualifier_unsigned
, qualifier_unsigned
};
122 #define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
123 static enum aarch64_type_qualifiers
124 aarch64_types_unopus_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
125 = { qualifier_unsigned
, qualifier_none
};
126 #define TYPES_UNOPUS (aarch64_types_unopus_qualifiers)
127 static enum aarch64_type_qualifiers
128 aarch64_types_binop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
129 = { qualifier_none
, qualifier_none
, qualifier_maybe_immediate
};
130 #define TYPES_BINOP (aarch64_types_binop_qualifiers)
131 static enum aarch64_type_qualifiers
132 aarch64_types_binopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
133 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
};
134 #define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
135 static enum aarch64_type_qualifiers
136 aarch64_types_binop_uus_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
137 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_none
};
138 #define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
139 static enum aarch64_type_qualifiers
140 aarch64_types_binop_ssu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
141 = { qualifier_none
, qualifier_none
, qualifier_unsigned
};
142 #define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
143 static enum aarch64_type_qualifiers
144 aarch64_types_binop_uss_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
145 = { qualifier_unsigned
, qualifier_none
, qualifier_none
};
146 #define TYPES_BINOP_USS (aarch64_types_binop_uss_qualifiers)
147 static enum aarch64_type_qualifiers
148 aarch64_types_binopp_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
149 = { qualifier_poly
, qualifier_poly
, qualifier_poly
};
150 #define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
152 static enum aarch64_type_qualifiers
153 aarch64_types_ternop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
154 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_none
};
155 #define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
156 static enum aarch64_type_qualifiers
157 aarch64_types_ternop_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
158 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_lane_index
};
159 #define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
160 static enum aarch64_type_qualifiers
161 aarch64_types_ternopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
162 = { qualifier_unsigned
, qualifier_unsigned
,
163 qualifier_unsigned
, qualifier_unsigned
};
164 #define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
166 static enum aarch64_type_qualifiers
167 aarch64_types_quadop_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
168 = { qualifier_none
, qualifier_none
, qualifier_none
,
169 qualifier_none
, qualifier_lane_index
};
170 #define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
172 static enum aarch64_type_qualifiers
173 aarch64_types_binop_imm_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
174 = { qualifier_poly
, qualifier_none
, qualifier_immediate
};
175 #define TYPES_GETREGP (aarch64_types_binop_imm_p_qualifiers)
176 static enum aarch64_type_qualifiers
177 aarch64_types_binop_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
178 = { qualifier_none
, qualifier_none
, qualifier_immediate
};
179 #define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
180 #define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
181 static enum aarch64_type_qualifiers
182 aarch64_types_shift_to_unsigned_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
183 = { qualifier_unsigned
, qualifier_none
, qualifier_immediate
};
184 #define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
185 static enum aarch64_type_qualifiers
186 aarch64_types_fcvt_from_unsigned_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
187 = { qualifier_none
, qualifier_unsigned
, qualifier_immediate
};
188 #define TYPES_FCVTIMM_SUS (aarch64_types_fcvt_from_unsigned_qualifiers)
189 static enum aarch64_type_qualifiers
190 aarch64_types_unsigned_shift_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
191 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_immediate
};
192 #define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
194 static enum aarch64_type_qualifiers
195 aarch64_types_ternop_s_imm_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
196 = { qualifier_none
, qualifier_none
, qualifier_poly
, qualifier_immediate
};
197 #define TYPES_SETREGP (aarch64_types_ternop_s_imm_p_qualifiers)
198 static enum aarch64_type_qualifiers
199 aarch64_types_ternop_s_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
200 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_immediate
};
201 #define TYPES_SETREG (aarch64_types_ternop_s_imm_qualifiers)
202 #define TYPES_SHIFTINSERT (aarch64_types_ternop_s_imm_qualifiers)
203 #define TYPES_SHIFTACC (aarch64_types_ternop_s_imm_qualifiers)
205 static enum aarch64_type_qualifiers
206 aarch64_types_ternop_p_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
207 = { qualifier_poly
, qualifier_poly
, qualifier_poly
, qualifier_immediate
};
208 #define TYPES_SHIFTINSERTP (aarch64_types_ternop_p_imm_qualifiers)
210 static enum aarch64_type_qualifiers
211 aarch64_types_unsigned_shiftacc_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
212 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
,
213 qualifier_immediate
};
214 #define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
217 static enum aarch64_type_qualifiers
218 aarch64_types_combine_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
219 = { qualifier_none
, qualifier_none
, qualifier_none
};
220 #define TYPES_COMBINE (aarch64_types_combine_qualifiers)
222 static enum aarch64_type_qualifiers
223 aarch64_types_combine_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
224 = { qualifier_poly
, qualifier_poly
, qualifier_poly
};
225 #define TYPES_COMBINEP (aarch64_types_combine_p_qualifiers)
227 static enum aarch64_type_qualifiers
228 aarch64_types_load1_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
229 = { qualifier_none
, qualifier_const_pointer_map_mode
};
230 #define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
231 #define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
232 static enum aarch64_type_qualifiers
233 aarch64_types_loadstruct_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
234 = { qualifier_none
, qualifier_const_pointer_map_mode
,
235 qualifier_none
, qualifier_struct_load_store_lane_index
};
236 #define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
238 static enum aarch64_type_qualifiers
239 aarch64_types_bsl_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
240 = { qualifier_poly
, qualifier_unsigned
,
241 qualifier_poly
, qualifier_poly
};
242 #define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
243 static enum aarch64_type_qualifiers
244 aarch64_types_bsl_s_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
245 = { qualifier_none
, qualifier_unsigned
,
246 qualifier_none
, qualifier_none
};
247 #define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
248 static enum aarch64_type_qualifiers
249 aarch64_types_bsl_u_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
250 = { qualifier_unsigned
, qualifier_unsigned
,
251 qualifier_unsigned
, qualifier_unsigned
};
252 #define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
254 /* The first argument (return type) of a store should be void type,
255 which we represent with qualifier_void. Their first operand will be
256 a DImode pointer to the location to store to, so we must use
257 qualifier_map_mode | qualifier_pointer to build a pointer to the
258 element type of the vector. */
259 static enum aarch64_type_qualifiers
260 aarch64_types_store1_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
261 = { qualifier_void
, qualifier_pointer_map_mode
, qualifier_poly
};
262 #define TYPES_STORE1P (aarch64_types_store1_p_qualifiers)
263 static enum aarch64_type_qualifiers
264 aarch64_types_store1_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
265 = { qualifier_void
, qualifier_pointer_map_mode
, qualifier_none
};
266 #define TYPES_STORE1 (aarch64_types_store1_qualifiers)
267 #define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
268 static enum aarch64_type_qualifiers
269 aarch64_types_storestruct_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
270 = { qualifier_void
, qualifier_pointer_map_mode
,
271 qualifier_none
, qualifier_struct_load_store_lane_index
};
272 #define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
274 #define CF0(N, X) CODE_FOR_aarch64_##N##X
275 #define CF1(N, X) CODE_FOR_##N##X##1
276 #define CF2(N, X) CODE_FOR_##N##X##2
277 #define CF3(N, X) CODE_FOR_##N##X##3
278 #define CF4(N, X) CODE_FOR_##N##X##4
279 #define CF10(N, X) CODE_FOR_##N##X
281 #define VAR1(T, N, MAP, A) \
282 {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T},
283 #define VAR2(T, N, MAP, A, B) \
284 VAR1 (T, N, MAP, A) \
286 #define VAR3(T, N, MAP, A, B, C) \
287 VAR2 (T, N, MAP, A, B) \
289 #define VAR4(T, N, MAP, A, B, C, D) \
290 VAR3 (T, N, MAP, A, B, C) \
292 #define VAR5(T, N, MAP, A, B, C, D, E) \
293 VAR4 (T, N, MAP, A, B, C, D) \
295 #define VAR6(T, N, MAP, A, B, C, D, E, F) \
296 VAR5 (T, N, MAP, A, B, C, D, E) \
298 #define VAR7(T, N, MAP, A, B, C, D, E, F, G) \
299 VAR6 (T, N, MAP, A, B, C, D, E, F) \
301 #define VAR8(T, N, MAP, A, B, C, D, E, F, G, H) \
302 VAR7 (T, N, MAP, A, B, C, D, E, F, G) \
304 #define VAR9(T, N, MAP, A, B, C, D, E, F, G, H, I) \
305 VAR8 (T, N, MAP, A, B, C, D, E, F, G, H) \
307 #define VAR10(T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
308 VAR9 (T, N, MAP, A, B, C, D, E, F, G, H, I) \
310 #define VAR11(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
311 VAR10 (T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
313 #define VAR12(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L) \
314 VAR11 (T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
316 #define VAR13(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L, M) \
317 VAR12 (T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L) \
319 #define VAR14(T, X, MAP, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
320 VAR13 (T, X, MAP, A, B, C, D, E, F, G, H, I, J, K, L, M) \
323 #include "aarch64-builtin-iterators.h"
325 static aarch64_simd_builtin_datum aarch64_simd_builtin_data
[] = {
326 #include "aarch64-simd-builtins.def"
329 /* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
330 #define AARCH64_CRC32_BUILTINS \
331 CRC32_BUILTIN (crc32b, QI) \
332 CRC32_BUILTIN (crc32h, HI) \
333 CRC32_BUILTIN (crc32w, SI) \
334 CRC32_BUILTIN (crc32x, DI) \
335 CRC32_BUILTIN (crc32cb, QI) \
336 CRC32_BUILTIN (crc32ch, HI) \
337 CRC32_BUILTIN (crc32cw, SI) \
338 CRC32_BUILTIN (crc32cx, DI)
344 const enum insn_code icode
;
346 } aarch64_crc_builtin_datum
;
348 #define CRC32_BUILTIN(N, M) \
352 #define VAR1(T, N, MAP, A) \
353 AARCH64_SIMD_BUILTIN_##T##_##N##A,
355 enum aarch64_builtins
359 AARCH64_BUILTIN_GET_FPCR
,
360 AARCH64_BUILTIN_SET_FPCR
,
361 AARCH64_BUILTIN_GET_FPSR
,
362 AARCH64_BUILTIN_SET_FPSR
,
364 AARCH64_BUILTIN_RSQRT_DF
,
365 AARCH64_BUILTIN_RSQRT_SF
,
366 AARCH64_BUILTIN_RSQRT_V2DF
,
367 AARCH64_BUILTIN_RSQRT_V2SF
,
368 AARCH64_BUILTIN_RSQRT_V4SF
,
369 AARCH64_SIMD_BUILTIN_BASE
,
370 AARCH64_SIMD_BUILTIN_LANE_CHECK
,
371 #include "aarch64-simd-builtins.def"
372 /* The first enum element which is based on an insn_data pattern. */
373 AARCH64_SIMD_PATTERN_START
= AARCH64_SIMD_BUILTIN_LANE_CHECK
+ 1,
374 AARCH64_SIMD_BUILTIN_MAX
= AARCH64_SIMD_PATTERN_START
375 + ARRAY_SIZE (aarch64_simd_builtin_data
) - 1,
376 AARCH64_CRC32_BUILTIN_BASE
,
377 AARCH64_CRC32_BUILTINS
378 AARCH64_CRC32_BUILTIN_MAX
,
383 #define CRC32_BUILTIN(N, M) \
384 {"__builtin_aarch64_"#N, M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
386 static aarch64_crc_builtin_datum aarch64_crc_builtin_data
[] = {
387 AARCH64_CRC32_BUILTINS
392 static GTY(()) tree aarch64_builtin_decls
[AARCH64_BUILTIN_MAX
];
394 #define NUM_DREG_TYPES 6
395 #define NUM_QREG_TYPES 6
397 /* Internal scalar builtin types. These types are used to support
398 neon intrinsic builtins. They are _not_ user-visible types. Therefore
399 the mangling for these types are implementation defined. */
400 const char *aarch64_scalar_builtin_types
[] = {
401 "__builtin_aarch64_simd_qi",
402 "__builtin_aarch64_simd_hi",
403 "__builtin_aarch64_simd_si",
404 "__builtin_aarch64_simd_hf",
405 "__builtin_aarch64_simd_sf",
406 "__builtin_aarch64_simd_di",
407 "__builtin_aarch64_simd_df",
408 "__builtin_aarch64_simd_poly8",
409 "__builtin_aarch64_simd_poly16",
410 "__builtin_aarch64_simd_poly64",
411 "__builtin_aarch64_simd_poly128",
412 "__builtin_aarch64_simd_ti",
413 "__builtin_aarch64_simd_uqi",
414 "__builtin_aarch64_simd_uhi",
415 "__builtin_aarch64_simd_usi",
416 "__builtin_aarch64_simd_udi",
417 "__builtin_aarch64_simd_ei",
418 "__builtin_aarch64_simd_oi",
419 "__builtin_aarch64_simd_ci",
420 "__builtin_aarch64_simd_xi",
424 #define ENTRY(E, M, Q, G) E,
425 enum aarch64_simd_type
427 #include "aarch64-simd-builtin-types.def"
428 ARM_NEON_H_TYPES_LAST
432 struct aarch64_simd_type_info
434 enum aarch64_simd_type type
;
436 /* Internal type name. */
439 /* Internal type name(mangled). The mangled names conform to the
440 AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
441 Appendix A). To qualify for emission with the mangled names defined in
442 that document, a vector type must not only be of the correct mode but also
443 be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
444 types are registered by aarch64_init_simd_builtin_types (). In other
445 words, vector types defined in other ways e.g. via vector_size attribute
446 will get default mangled names. */
455 /* Machine mode the internal type maps to. */
456 enum machine_mode mode
;
459 enum aarch64_type_qualifiers q
;
462 #define ENTRY(E, M, Q, G) \
463 {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, M##mode, qualifier_##Q},
464 static struct aarch64_simd_type_info aarch64_simd_types
[] = {
465 #include "aarch64-simd-builtin-types.def"
469 static tree aarch64_simd_intOI_type_node
= NULL_TREE
;
470 static tree aarch64_simd_intCI_type_node
= NULL_TREE
;
471 static tree aarch64_simd_intXI_type_node
= NULL_TREE
;
473 /* The user-visible __fp16 type, and a pointer to that type. Used
474 across the back-end. */
475 tree aarch64_fp16_type_node
= NULL_TREE
;
476 tree aarch64_fp16_ptr_type_node
= NULL_TREE
;
479 aarch64_mangle_builtin_scalar_type (const_tree type
)
483 while (aarch64_scalar_builtin_types
[i
] != NULL
)
485 const char *name
= aarch64_scalar_builtin_types
[i
];
487 if (TREE_CODE (TYPE_NAME (type
)) == TYPE_DECL
488 && DECL_NAME (TYPE_NAME (type
))
489 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
))), name
))
490 return aarch64_scalar_builtin_types
[i
];
497 aarch64_mangle_builtin_vector_type (const_tree type
)
500 int nelts
= sizeof (aarch64_simd_types
) / sizeof (aarch64_simd_types
[0]);
502 for (i
= 0; i
< nelts
; i
++)
503 if (aarch64_simd_types
[i
].mode
== TYPE_MODE (type
)
505 && TREE_CODE (TYPE_NAME (type
)) == TYPE_DECL
506 && DECL_NAME (TYPE_NAME (type
))
508 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
))),
509 aarch64_simd_types
[i
].name
))
510 return aarch64_simd_types
[i
].mangle
;
516 aarch64_mangle_builtin_type (const_tree type
)
519 /* Walk through all the AArch64 builtins types tables to filter out the
521 if ((mangle
= aarch64_mangle_builtin_vector_type (type
))
522 || (mangle
= aarch64_mangle_builtin_scalar_type (type
)))
529 aarch64_simd_builtin_std_type (enum machine_mode mode
,
530 enum aarch64_type_qualifiers q
)
532 #define QUAL_TYPE(M) \
533 ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
537 return QUAL_TYPE (QI
);
539 return QUAL_TYPE (HI
);
541 return QUAL_TYPE (SI
);
543 return QUAL_TYPE (DI
);
545 return QUAL_TYPE (TI
);
547 return aarch64_simd_intOI_type_node
;
549 return aarch64_simd_intCI_type_node
;
551 return aarch64_simd_intXI_type_node
;
553 return aarch64_fp16_type_node
;
555 return float_type_node
;
557 return double_type_node
;
565 aarch64_lookup_simd_builtin_type (enum machine_mode mode
,
566 enum aarch64_type_qualifiers q
)
569 int nelts
= sizeof (aarch64_simd_types
) / sizeof (aarch64_simd_types
[0]);
571 /* Non-poly scalar modes map to standard types not in the table. */
572 if (q
!= qualifier_poly
&& !VECTOR_MODE_P (mode
))
573 return aarch64_simd_builtin_std_type (mode
, q
);
575 for (i
= 0; i
< nelts
; i
++)
576 if (aarch64_simd_types
[i
].mode
== mode
577 && aarch64_simd_types
[i
].q
== q
)
578 return aarch64_simd_types
[i
].itype
;
584 aarch64_simd_builtin_type (enum machine_mode mode
,
585 bool unsigned_p
, bool poly_p
)
588 return aarch64_lookup_simd_builtin_type (mode
, qualifier_poly
);
590 return aarch64_lookup_simd_builtin_type (mode
, qualifier_unsigned
);
592 return aarch64_lookup_simd_builtin_type (mode
, qualifier_none
);
596 aarch64_init_simd_builtin_types (void)
599 int nelts
= sizeof (aarch64_simd_types
) / sizeof (aarch64_simd_types
[0]);
602 /* Init all the element types built by the front-end. */
603 aarch64_simd_types
[Int8x8_t
].eltype
= intQI_type_node
;
604 aarch64_simd_types
[Int8x16_t
].eltype
= intQI_type_node
;
605 aarch64_simd_types
[Int16x4_t
].eltype
= intHI_type_node
;
606 aarch64_simd_types
[Int16x8_t
].eltype
= intHI_type_node
;
607 aarch64_simd_types
[Int32x2_t
].eltype
= intSI_type_node
;
608 aarch64_simd_types
[Int32x4_t
].eltype
= intSI_type_node
;
609 aarch64_simd_types
[Int64x1_t
].eltype
= intDI_type_node
;
610 aarch64_simd_types
[Int64x2_t
].eltype
= intDI_type_node
;
611 aarch64_simd_types
[Uint8x8_t
].eltype
= unsigned_intQI_type_node
;
612 aarch64_simd_types
[Uint8x16_t
].eltype
= unsigned_intQI_type_node
;
613 aarch64_simd_types
[Uint16x4_t
].eltype
= unsigned_intHI_type_node
;
614 aarch64_simd_types
[Uint16x8_t
].eltype
= unsigned_intHI_type_node
;
615 aarch64_simd_types
[Uint32x2_t
].eltype
= unsigned_intSI_type_node
;
616 aarch64_simd_types
[Uint32x4_t
].eltype
= unsigned_intSI_type_node
;
617 aarch64_simd_types
[Uint64x1_t
].eltype
= unsigned_intDI_type_node
;
618 aarch64_simd_types
[Uint64x2_t
].eltype
= unsigned_intDI_type_node
;
620 /* Poly types are a world of their own. */
621 aarch64_simd_types
[Poly8_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
=
622 build_distinct_type_copy (unsigned_intQI_type_node
);
623 aarch64_simd_types
[Poly16_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
=
624 build_distinct_type_copy (unsigned_intHI_type_node
);
625 aarch64_simd_types
[Poly64_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
=
626 build_distinct_type_copy (unsigned_intDI_type_node
);
627 aarch64_simd_types
[Poly128_t
].eltype
= aarch64_simd_types
[Poly128_t
].itype
=
628 build_distinct_type_copy (unsigned_intTI_type_node
);
629 /* Init poly vector element types with scalar poly types. */
630 aarch64_simd_types
[Poly8x8_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
;
631 aarch64_simd_types
[Poly8x16_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
;
632 aarch64_simd_types
[Poly16x4_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
;
633 aarch64_simd_types
[Poly16x8_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
;
634 aarch64_simd_types
[Poly64x1_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
;
635 aarch64_simd_types
[Poly64x2_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
;
637 /* Continue with standard types. */
638 aarch64_simd_types
[Float16x4_t
].eltype
= aarch64_fp16_type_node
;
639 aarch64_simd_types
[Float16x8_t
].eltype
= aarch64_fp16_type_node
;
640 aarch64_simd_types
[Float32x2_t
].eltype
= float_type_node
;
641 aarch64_simd_types
[Float32x4_t
].eltype
= float_type_node
;
642 aarch64_simd_types
[Float64x1_t
].eltype
= double_type_node
;
643 aarch64_simd_types
[Float64x2_t
].eltype
= double_type_node
;
645 for (i
= 0; i
< nelts
; i
++)
647 tree eltype
= aarch64_simd_types
[i
].eltype
;
648 enum machine_mode mode
= aarch64_simd_types
[i
].mode
;
650 if (aarch64_simd_types
[i
].itype
== NULL
)
652 aarch64_simd_types
[i
].itype
653 = build_distinct_type_copy
654 (build_vector_type (eltype
, GET_MODE_NUNITS (mode
)));
655 SET_TYPE_STRUCTURAL_EQUALITY (aarch64_simd_types
[i
].itype
);
658 tdecl
= add_builtin_type (aarch64_simd_types
[i
].name
,
659 aarch64_simd_types
[i
].itype
);
660 TYPE_NAME (aarch64_simd_types
[i
].itype
) = tdecl
;
663 #define AARCH64_BUILD_SIGNED_TYPE(mode) \
664 make_signed_type (GET_MODE_PRECISION (mode));
665 aarch64_simd_intOI_type_node
= AARCH64_BUILD_SIGNED_TYPE (OImode
);
666 aarch64_simd_intCI_type_node
= AARCH64_BUILD_SIGNED_TYPE (CImode
);
667 aarch64_simd_intXI_type_node
= AARCH64_BUILD_SIGNED_TYPE (XImode
);
668 #undef AARCH64_BUILD_SIGNED_TYPE
670 tdecl
= add_builtin_type
671 ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node
);
672 TYPE_NAME (aarch64_simd_intOI_type_node
) = tdecl
;
673 tdecl
= add_builtin_type
674 ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node
);
675 TYPE_NAME (aarch64_simd_intCI_type_node
) = tdecl
;
676 tdecl
= add_builtin_type
677 ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node
);
678 TYPE_NAME (aarch64_simd_intXI_type_node
) = tdecl
;
682 aarch64_init_simd_builtin_scalar_types (void)
684 /* Define typedefs for all the standard scalar types. */
685 (*lang_hooks
.types
.register_builtin_type
) (intQI_type_node
,
686 "__builtin_aarch64_simd_qi");
687 (*lang_hooks
.types
.register_builtin_type
) (intHI_type_node
,
688 "__builtin_aarch64_simd_hi");
689 (*lang_hooks
.types
.register_builtin_type
) (aarch64_fp16_type_node
,
690 "__builtin_aarch64_simd_hf");
691 (*lang_hooks
.types
.register_builtin_type
) (intSI_type_node
,
692 "__builtin_aarch64_simd_si");
693 (*lang_hooks
.types
.register_builtin_type
) (float_type_node
,
694 "__builtin_aarch64_simd_sf");
695 (*lang_hooks
.types
.register_builtin_type
) (intDI_type_node
,
696 "__builtin_aarch64_simd_di");
697 (*lang_hooks
.types
.register_builtin_type
) (double_type_node
,
698 "__builtin_aarch64_simd_df");
699 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intQI_type_node
,
700 "__builtin_aarch64_simd_poly8");
701 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intHI_type_node
,
702 "__builtin_aarch64_simd_poly16");
703 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intDI_type_node
,
704 "__builtin_aarch64_simd_poly64");
705 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intTI_type_node
,
706 "__builtin_aarch64_simd_poly128");
707 (*lang_hooks
.types
.register_builtin_type
) (intTI_type_node
,
708 "__builtin_aarch64_simd_ti");
709 /* Unsigned integer types for various mode sizes. */
710 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intQI_type_node
,
711 "__builtin_aarch64_simd_uqi");
712 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intHI_type_node
,
713 "__builtin_aarch64_simd_uhi");
714 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intSI_type_node
,
715 "__builtin_aarch64_simd_usi");
716 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intDI_type_node
,
717 "__builtin_aarch64_simd_udi");
720 static bool aarch64_simd_builtins_initialized_p
= false;
723 aarch64_init_simd_builtins (void)
725 unsigned int i
, fcode
= AARCH64_SIMD_PATTERN_START
;
727 if (aarch64_simd_builtins_initialized_p
)
730 aarch64_simd_builtins_initialized_p
= true;
732 aarch64_init_simd_builtin_types ();
734 /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
735 Therefore we need to preserve the old __builtin scalar types. It can be
736 removed once all the intrinsics become strongly typed using the qualifier
738 aarch64_init_simd_builtin_scalar_types ();
740 tree lane_check_fpr
= build_function_type_list (void_type_node
,
745 aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_LANE_CHECK
] =
746 add_builtin_function ("__builtin_aarch64_im_lane_boundsi", lane_check_fpr
,
747 AARCH64_SIMD_BUILTIN_LANE_CHECK
, BUILT_IN_MD
,
750 for (i
= 0; i
< ARRAY_SIZE (aarch64_simd_builtin_data
); i
++, fcode
++)
752 bool print_type_signature_p
= false;
753 char type_signature
[SIMD_MAX_BUILTIN_ARGS
] = { 0 };
754 aarch64_simd_builtin_datum
*d
= &aarch64_simd_builtin_data
[i
];
761 /* We must track two variables here. op_num is
762 the operand number as in the RTL pattern. This is
763 required to access the mode (e.g. V4SF mode) of the
764 argument, from which the base type can be derived.
765 arg_num is an index in to the qualifiers data, which
766 gives qualifiers to the type (e.g. const unsigned).
767 The reason these two variables may differ by one is the
768 void return type. While all return types take the 0th entry
769 in the qualifiers array, there is no operand for them in the
771 int op_num
= insn_data
[d
->code
].n_operands
- 1;
772 int arg_num
= d
->qualifiers
[0] & qualifier_void
775 tree return_type
= void_type_node
, args
= void_list_node
;
778 /* Build a function type directly from the insn_data for this
779 builtin. The build_function_type () function takes care of
780 removing duplicates for us. */
781 for (; op_num
>= 0; arg_num
--, op_num
--)
783 machine_mode op_mode
= insn_data
[d
->code
].operand
[op_num
].mode
;
784 enum aarch64_type_qualifiers qualifiers
= d
->qualifiers
[arg_num
];
786 if (qualifiers
& qualifier_unsigned
)
788 type_signature
[op_num
] = 'u';
789 print_type_signature_p
= true;
791 else if (qualifiers
& qualifier_poly
)
793 type_signature
[op_num
] = 'p';
794 print_type_signature_p
= true;
797 type_signature
[op_num
] = 's';
799 /* Skip an internal operand for vget_{low, high}. */
800 if (qualifiers
& qualifier_internal
)
803 /* Some builtins have different user-facing types
804 for certain arguments, encoded in d->mode. */
805 if (qualifiers
& qualifier_map_mode
)
808 /* For pointers, we want a pointer to the basic type
810 if (qualifiers
& qualifier_pointer
&& VECTOR_MODE_P (op_mode
))
811 op_mode
= GET_MODE_INNER (op_mode
);
813 eltype
= aarch64_simd_builtin_type
815 (qualifiers
& qualifier_unsigned
) != 0,
816 (qualifiers
& qualifier_poly
) != 0);
817 gcc_assert (eltype
!= NULL
);
819 /* Add qualifiers. */
820 if (qualifiers
& qualifier_const
)
821 eltype
= build_qualified_type (eltype
, TYPE_QUAL_CONST
);
823 if (qualifiers
& qualifier_pointer
)
824 eltype
= build_pointer_type (eltype
);
826 /* If we have reached arg_num == 0, we are at a non-void
827 return type. Otherwise, we are still processing
830 return_type
= eltype
;
832 args
= tree_cons (NULL_TREE
, eltype
, args
);
835 ftype
= build_function_type (return_type
, args
);
837 gcc_assert (ftype
!= NULL
);
839 if (print_type_signature_p
)
840 snprintf (namebuf
, sizeof (namebuf
), "__builtin_aarch64_%s_%s",
841 d
->name
, type_signature
);
843 snprintf (namebuf
, sizeof (namebuf
), "__builtin_aarch64_%s",
846 fndecl
= add_builtin_function (namebuf
, ftype
, fcode
, BUILT_IN_MD
,
848 aarch64_builtin_decls
[fcode
] = fndecl
;
853 aarch64_init_crc32_builtins ()
855 tree usi_type
= aarch64_simd_builtin_std_type (SImode
, qualifier_unsigned
);
858 for (i
= 0; i
< ARRAY_SIZE (aarch64_crc_builtin_data
); ++i
)
860 aarch64_crc_builtin_datum
* d
= &aarch64_crc_builtin_data
[i
];
861 tree argtype
= aarch64_simd_builtin_std_type (d
->mode
,
863 tree ftype
= build_function_type_list (usi_type
, usi_type
, argtype
, NULL_TREE
);
864 tree fndecl
= add_builtin_function (d
->name
, ftype
, d
->fcode
,
865 BUILT_IN_MD
, NULL
, NULL_TREE
);
867 aarch64_builtin_decls
[d
->fcode
] = fndecl
;
871 /* Add builtins for reciprocal square root. */
874 aarch64_init_builtin_rsqrt (void)
879 tree V2SF_type_node
= build_vector_type (float_type_node
, 2);
880 tree V2DF_type_node
= build_vector_type (double_type_node
, 2);
881 tree V4SF_type_node
= build_vector_type (float_type_node
, 4);
883 struct builtin_decls_data
886 const char *builtin_name
;
890 builtin_decls_data bdda
[] =
892 { double_type_node
, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF
},
893 { float_type_node
, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF
},
894 { V2DF_type_node
, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF
},
895 { V2SF_type_node
, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF
},
896 { V4SF_type_node
, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF
}
899 builtin_decls_data
*bdd
= bdda
;
900 builtin_decls_data
*bdd_end
= bdd
+ (sizeof (bdda
) / sizeof (builtin_decls_data
));
902 for (; bdd
< bdd_end
; bdd
++)
904 ftype
= build_function_type_list (bdd
->type_node
, bdd
->type_node
, NULL_TREE
);
905 fndecl
= add_builtin_function (bdd
->builtin_name
,
906 ftype
, bdd
->function_code
, BUILT_IN_MD
, NULL
, NULL_TREE
);
907 aarch64_builtin_decls
[bdd
->function_code
] = fndecl
;
911 /* Initialize the backend types that support the user-visible __fp16
912 type, also initialize a pointer to that type, to be used when
916 aarch64_init_fp16_types (void)
918 aarch64_fp16_type_node
= make_node (REAL_TYPE
);
919 TYPE_PRECISION (aarch64_fp16_type_node
) = 16;
920 layout_type (aarch64_fp16_type_node
);
922 (*lang_hooks
.types
.register_builtin_type
) (aarch64_fp16_type_node
, "__fp16");
923 aarch64_fp16_ptr_type_node
= build_pointer_type (aarch64_fp16_type_node
);
927 aarch64_init_builtins (void)
930 = build_function_type_list (void_type_node
, unsigned_type_node
, NULL
);
932 = build_function_type_list (unsigned_type_node
, NULL
);
934 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR
]
935 = add_builtin_function ("__builtin_aarch64_get_fpcr", ftype_get_fpr
,
936 AARCH64_BUILTIN_GET_FPCR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
937 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR
]
938 = add_builtin_function ("__builtin_aarch64_set_fpcr", ftype_set_fpr
,
939 AARCH64_BUILTIN_SET_FPCR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
940 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR
]
941 = add_builtin_function ("__builtin_aarch64_get_fpsr", ftype_get_fpr
,
942 AARCH64_BUILTIN_GET_FPSR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
943 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR
]
944 = add_builtin_function ("__builtin_aarch64_set_fpsr", ftype_set_fpr
,
945 AARCH64_BUILTIN_SET_FPSR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
947 aarch64_init_fp16_types ();
950 aarch64_init_simd_builtins ();
952 aarch64_init_crc32_builtins ();
953 aarch64_init_builtin_rsqrt ();
957 aarch64_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
959 if (code
>= AARCH64_BUILTIN_MAX
)
960 return error_mark_node
;
962 return aarch64_builtin_decls
[code
];
967 SIMD_ARG_COPY_TO_REG
,
970 SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX
,
976 aarch64_simd_expand_args (rtx target
, int icode
, int have_retval
,
977 tree exp
, builtin_simd_arg
*args
,
978 enum machine_mode builtin_mode
)
981 rtx op
[SIMD_MAX_BUILTIN_ARGS
+ 1]; /* First element for result operand. */
986 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
988 || GET_MODE (target
) != tmode
989 || !(*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
990 target
= gen_reg_rtx (tmode
);
996 builtin_simd_arg thisarg
= args
[opc
- have_retval
];
998 if (thisarg
== SIMD_ARG_STOP
)
1002 tree arg
= CALL_EXPR_ARG (exp
, opc
- have_retval
);
1003 enum machine_mode mode
= insn_data
[icode
].operand
[opc
].mode
;
1004 op
[opc
] = expand_normal (arg
);
1008 case SIMD_ARG_COPY_TO_REG
:
1009 if (POINTER_TYPE_P (TREE_TYPE (arg
)))
1010 op
[opc
] = convert_memory_address (Pmode
, op
[opc
]);
1011 /*gcc_assert (GET_MODE (op[opc]) == mode); */
1012 if (!(*insn_data
[icode
].operand
[opc
].predicate
)
1014 op
[opc
] = copy_to_mode_reg (mode
, op
[opc
]);
1017 case SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX
:
1018 gcc_assert (opc
> 1);
1019 if (CONST_INT_P (op
[opc
]))
1021 aarch64_simd_lane_bounds (op
[opc
], 0,
1022 GET_MODE_NUNITS (builtin_mode
),
1024 /* Keep to GCC-vector-extension lane indices in the RTL. */
1026 GEN_INT (ENDIAN_LANE_N (builtin_mode
, INTVAL (op
[opc
])));
1030 case SIMD_ARG_LANE_INDEX
:
1031 /* Must be a previous operand into which this is an index. */
1032 gcc_assert (opc
> 0);
1033 if (CONST_INT_P (op
[opc
]))
1035 machine_mode vmode
= insn_data
[icode
].operand
[opc
- 1].mode
;
1036 aarch64_simd_lane_bounds (op
[opc
],
1037 0, GET_MODE_NUNITS (vmode
), exp
);
1038 /* Keep to GCC-vector-extension lane indices in the RTL. */
1039 op
[opc
] = GEN_INT (ENDIAN_LANE_N (vmode
, INTVAL (op
[opc
])));
1041 /* Fall through - if the lane index isn't a constant then
1042 the next case will error. */
1044 case SIMD_ARG_CONSTANT
:
1046 if (!(*insn_data
[icode
].operand
[opc
].predicate
)
1049 error ("%Kargument %d must be a constant immediate",
1050 exp
, opc
+ 1 - have_retval
);
1066 pat
= GEN_FCN (icode
) (op
[0]);
1070 pat
= GEN_FCN (icode
) (op
[0], op
[1]);
1074 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2]);
1078 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3]);
1082 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3], op
[4]);
1086 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3], op
[4], op
[5]);
1101 /* Expand an AArch64 AdvSIMD builtin(intrinsic). */
1103 aarch64_simd_expand_builtin (int fcode
, tree exp
, rtx target
)
1105 if (fcode
== AARCH64_SIMD_BUILTIN_LANE_CHECK
)
1107 rtx totalsize
= expand_normal (CALL_EXPR_ARG (exp
, 0));
1108 rtx elementsize
= expand_normal (CALL_EXPR_ARG (exp
, 1));
1109 if (CONST_INT_P (totalsize
) && CONST_INT_P (elementsize
)
1110 && UINTVAL (elementsize
) != 0
1111 && UINTVAL (totalsize
) != 0)
1113 rtx lane_idx
= expand_normal (CALL_EXPR_ARG (exp
, 2));
1114 if (CONST_INT_P (lane_idx
))
1115 aarch64_simd_lane_bounds (lane_idx
, 0,
1117 / UINTVAL (elementsize
),
1120 error ("%Klane index must be a constant immediate", exp
);
1123 error ("%Ktotal size and element size must be a non-zero constant immediate", exp
);
1124 /* Don't generate any RTL. */
1127 aarch64_simd_builtin_datum
*d
=
1128 &aarch64_simd_builtin_data
[fcode
- AARCH64_SIMD_PATTERN_START
];
1129 enum insn_code icode
= d
->code
;
1130 builtin_simd_arg args
[SIMD_MAX_BUILTIN_ARGS
+ 1];
1131 int num_args
= insn_data
[d
->code
].n_operands
;
1135 is_void
= !!(d
->qualifiers
[0] & qualifier_void
);
1137 num_args
+= is_void
;
1139 for (k
= 1; k
< num_args
; k
++)
1141 /* We have four arrays of data, each indexed in a different fashion.
1142 qualifiers - element 0 always describes the function return type.
1143 operands - element 0 is either the operand for return value (if
1144 the function has a non-void return type) or the operand for the
1146 expr_args - element 0 always holds the first argument.
1147 args - element 0 is always used for the return type. */
1148 int qualifiers_k
= k
;
1149 int operands_k
= k
- is_void
;
1150 int expr_args_k
= k
- 1;
1152 if (d
->qualifiers
[qualifiers_k
] & qualifier_lane_index
)
1153 args
[k
] = SIMD_ARG_LANE_INDEX
;
1154 else if (d
->qualifiers
[qualifiers_k
] & qualifier_struct_load_store_lane_index
)
1155 args
[k
] = SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX
;
1156 else if (d
->qualifiers
[qualifiers_k
] & qualifier_immediate
)
1157 args
[k
] = SIMD_ARG_CONSTANT
;
1158 else if (d
->qualifiers
[qualifiers_k
] & qualifier_maybe_immediate
)
1161 = expand_normal (CALL_EXPR_ARG (exp
,
1163 /* Handle constants only if the predicate allows it. */
1164 bool op_const_int_p
=
1166 && (*insn_data
[icode
].operand
[operands_k
].predicate
)
1167 (arg
, insn_data
[icode
].operand
[operands_k
].mode
));
1168 args
[k
] = op_const_int_p
? SIMD_ARG_CONSTANT
: SIMD_ARG_COPY_TO_REG
;
1171 args
[k
] = SIMD_ARG_COPY_TO_REG
;
1174 args
[k
] = SIMD_ARG_STOP
;
1176 /* The interface to aarch64_simd_expand_args expects a 0 if
1177 the function is void, and a 1 if it is not. */
1178 return aarch64_simd_expand_args
1179 (target
, icode
, !is_void
, exp
, &args
[1], d
->mode
);
1183 aarch64_crc32_expand_builtin (int fcode
, tree exp
, rtx target
)
1186 aarch64_crc_builtin_datum
*d
1187 = &aarch64_crc_builtin_data
[fcode
- (AARCH64_CRC32_BUILTIN_BASE
+ 1)];
1188 enum insn_code icode
= d
->icode
;
1189 tree arg0
= CALL_EXPR_ARG (exp
, 0);
1190 tree arg1
= CALL_EXPR_ARG (exp
, 1);
1191 rtx op0
= expand_normal (arg0
);
1192 rtx op1
= expand_normal (arg1
);
1193 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
1194 machine_mode mode0
= insn_data
[icode
].operand
[1].mode
;
1195 machine_mode mode1
= insn_data
[icode
].operand
[2].mode
;
1198 || GET_MODE (target
) != tmode
1199 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
1200 target
= gen_reg_rtx (tmode
);
1202 gcc_assert ((GET_MODE (op0
) == mode0
|| GET_MODE (op0
) == VOIDmode
)
1203 && (GET_MODE (op1
) == mode1
|| GET_MODE (op1
) == VOIDmode
));
1205 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
1206 op0
= copy_to_mode_reg (mode0
, op0
);
1207 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
1208 op1
= copy_to_mode_reg (mode1
, op1
);
1210 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
1218 /* Function to expand reciprocal square root builtins. */
1221 aarch64_expand_builtin_rsqrt (int fcode
, tree exp
, rtx target
)
1223 tree arg0
= CALL_EXPR_ARG (exp
, 0);
1224 rtx op0
= expand_normal (arg0
);
1226 rtx (*gen
) (rtx
, rtx
);
1230 case AARCH64_BUILTIN_RSQRT_DF
:
1233 case AARCH64_BUILTIN_RSQRT_SF
:
1236 case AARCH64_BUILTIN_RSQRT_V2DF
:
1237 gen
= gen_rsqrtv2df2
;
1239 case AARCH64_BUILTIN_RSQRT_V2SF
:
1240 gen
= gen_rsqrtv2sf2
;
1242 case AARCH64_BUILTIN_RSQRT_V4SF
:
1243 gen
= gen_rsqrtv4sf2
;
1245 default: gcc_unreachable ();
1249 target
= gen_reg_rtx (GET_MODE (op0
));
1251 emit_insn (gen (target
, op0
));
1256 /* Expand an expression EXP that calls a built-in function,
1257 with result going to TARGET if that's convenient. */
1259 aarch64_expand_builtin (tree exp
,
1261 rtx subtarget ATTRIBUTE_UNUSED
,
1262 machine_mode mode ATTRIBUTE_UNUSED
,
1263 int ignore ATTRIBUTE_UNUSED
)
1265 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1266 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1273 case AARCH64_BUILTIN_GET_FPCR
:
1274 case AARCH64_BUILTIN_SET_FPCR
:
1275 case AARCH64_BUILTIN_GET_FPSR
:
1276 case AARCH64_BUILTIN_SET_FPSR
:
1277 if ((fcode
== AARCH64_BUILTIN_GET_FPCR
)
1278 || (fcode
== AARCH64_BUILTIN_GET_FPSR
))
1280 icode
= (fcode
== AARCH64_BUILTIN_GET_FPSR
) ?
1281 CODE_FOR_get_fpsr
: CODE_FOR_get_fpcr
;
1282 target
= gen_reg_rtx (SImode
);
1283 pat
= GEN_FCN (icode
) (target
);
1288 icode
= (fcode
== AARCH64_BUILTIN_SET_FPSR
) ?
1289 CODE_FOR_set_fpsr
: CODE_FOR_set_fpcr
;
1290 arg0
= CALL_EXPR_ARG (exp
, 0);
1291 op0
= force_reg (SImode
, expand_normal (arg0
));
1292 pat
= GEN_FCN (icode
) (op0
);
1298 if (fcode
>= AARCH64_SIMD_BUILTIN_BASE
&& fcode
<= AARCH64_SIMD_BUILTIN_MAX
)
1299 return aarch64_simd_expand_builtin (fcode
, exp
, target
);
1300 else if (fcode
>= AARCH64_CRC32_BUILTIN_BASE
&& fcode
<= AARCH64_CRC32_BUILTIN_MAX
)
1301 return aarch64_crc32_expand_builtin (fcode
, exp
, target
);
1303 if (fcode
== AARCH64_BUILTIN_RSQRT_DF
1304 || fcode
== AARCH64_BUILTIN_RSQRT_SF
1305 || fcode
== AARCH64_BUILTIN_RSQRT_V2DF
1306 || fcode
== AARCH64_BUILTIN_RSQRT_V2SF
1307 || fcode
== AARCH64_BUILTIN_RSQRT_V4SF
)
1308 return aarch64_expand_builtin_rsqrt (fcode
, exp
, target
);
1314 aarch64_builtin_vectorized_function (unsigned int fn
, tree type_out
,
1317 machine_mode in_mode
, out_mode
;
1320 if (TREE_CODE (type_out
) != VECTOR_TYPE
1321 || TREE_CODE (type_in
) != VECTOR_TYPE
)
1324 out_mode
= TYPE_MODE (TREE_TYPE (type_out
));
1325 out_n
= TYPE_VECTOR_SUBPARTS (type_out
);
1326 in_mode
= TYPE_MODE (TREE_TYPE (type_in
));
1327 in_n
= TYPE_VECTOR_SUBPARTS (type_in
);
1329 #undef AARCH64_CHECK_BUILTIN_MODE
1330 #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
1331 #define AARCH64_FIND_FRINT_VARIANT(N) \
1332 (AARCH64_CHECK_BUILTIN_MODE (2, D) \
1333 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
1334 : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
1335 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
1336 : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
1337 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
1341 #undef AARCH64_CHECK_BUILTIN_MODE
1342 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1343 (out_mode == N##Fmode && out_n == C \
1344 && in_mode == N##Fmode && in_n == C)
1346 return AARCH64_FIND_FRINT_VARIANT (floor
);
1348 return AARCH64_FIND_FRINT_VARIANT (ceil
);
1350 return AARCH64_FIND_FRINT_VARIANT (btrunc
);
1352 return AARCH64_FIND_FRINT_VARIANT (round
);
1354 return AARCH64_FIND_FRINT_VARIANT (nearbyint
);
1356 return AARCH64_FIND_FRINT_VARIANT (sqrt
);
1357 #undef AARCH64_CHECK_BUILTIN_MODE
1358 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1359 (out_mode == SImode && out_n == C \
1360 && in_mode == N##Imode && in_n == C)
1363 if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1364 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_clzv4si
];
1369 if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1370 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si
];
1371 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1372 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si
];
1375 #undef AARCH64_CHECK_BUILTIN_MODE
1376 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1377 (out_mode == N##Imode && out_n == C \
1378 && in_mode == N##Fmode && in_n == C)
1383 enum aarch64_builtins builtin
;
1384 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1385 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di
;
1386 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1387 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si
;
1388 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1389 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si
;
1393 return aarch64_builtin_decls
[builtin
];
1399 enum aarch64_builtins builtin
;
1400 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1401 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di
;
1402 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1403 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si
;
1404 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1405 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si
;
1409 return aarch64_builtin_decls
[builtin
];
1415 enum aarch64_builtins builtin
;
1416 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1417 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di
;
1418 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1419 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si
;
1420 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1421 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si
;
1425 return aarch64_builtin_decls
[builtin
];
1427 case CFN_BUILT_IN_BSWAP16
:
1428 #undef AARCH64_CHECK_BUILTIN_MODE
1429 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1430 (out_mode == N##Imode && out_n == C \
1431 && in_mode == N##Imode && in_n == C)
1432 if (AARCH64_CHECK_BUILTIN_MODE (4, H
))
1433 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4hi
];
1434 else if (AARCH64_CHECK_BUILTIN_MODE (8, H
))
1435 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv8hi
];
1438 case CFN_BUILT_IN_BSWAP32
:
1439 if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1440 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2si
];
1441 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1442 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4si
];
1445 case CFN_BUILT_IN_BSWAP64
:
1446 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1447 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2di
];
1457 /* Return builtin for reciprocal square root. */
1460 aarch64_builtin_rsqrt (unsigned int fn
)
1462 if (fn
== AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df
)
1463 return aarch64_builtin_decls
[AARCH64_BUILTIN_RSQRT_V2DF
];
1464 if (fn
== AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf
)
1465 return aarch64_builtin_decls
[AARCH64_BUILTIN_RSQRT_V2SF
];
1466 if (fn
== AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf
)
1467 return aarch64_builtin_decls
[AARCH64_BUILTIN_RSQRT_V4SF
];
1472 #define VAR1(T, N, MAP, A) \
1473 case AARCH64_SIMD_BUILTIN_##T##_##N##A:
1476 aarch64_fold_builtin (tree fndecl
, int n_args ATTRIBUTE_UNUSED
, tree
*args
,
1477 bool ignore ATTRIBUTE_UNUSED
)
1479 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1480 tree type
= TREE_TYPE (TREE_TYPE (fndecl
));
1484 BUILTIN_VDQF (UNOP
, abs
, 2)
1485 return fold_build1 (ABS_EXPR
, type
, args
[0]);
1486 VAR1 (UNOP
, floatv2si
, 2, v2sf
)
1487 VAR1 (UNOP
, floatv4si
, 2, v4sf
)
1488 VAR1 (UNOP
, floatv2di
, 2, v2df
)
1489 return fold_build1 (FLOAT_EXPR
, type
, args
[0]);
1498 aarch64_gimple_fold_builtin (gimple_stmt_iterator
*gsi
)
1500 bool changed
= false;
1501 gimple
*stmt
= gsi_stmt (*gsi
);
1502 tree call
= gimple_call_fn (stmt
);
1504 gimple
*new_stmt
= NULL
;
1508 fndecl
= gimple_call_fndecl (stmt
);
1511 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1512 unsigned nargs
= gimple_call_num_args (stmt
);
1513 tree
*args
= (nargs
> 0
1514 ? gimple_call_arg_ptr (stmt
, 0)
1515 : &error_mark_node
);
1517 /* We use gimple's REDUC_(PLUS|MIN|MAX)_EXPRs for float, signed int
1518 and unsigned int; it will distinguish according to the types of
1519 the arguments to the __builtin. */
1522 BUILTIN_VALL (UNOP
, reduc_plus_scal_
, 10)
1523 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
1524 REDUC_PLUS_EXPR
, args
[0]);
1526 BUILTIN_VDQIF (UNOP
, reduc_smax_scal_
, 10)
1527 BUILTIN_VDQ_BHSI (UNOPU
, reduc_umax_scal_
, 10)
1528 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
1529 REDUC_MAX_EXPR
, args
[0]);
1531 BUILTIN_VDQIF (UNOP
, reduc_smin_scal_
, 10)
1532 BUILTIN_VDQ_BHSI (UNOPU
, reduc_umin_scal_
, 10)
1533 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
1534 REDUC_MIN_EXPR
, args
[0]);
1536 BUILTIN_GPF (BINOP
, fmulx
, 0)
1538 gcc_assert (nargs
== 2);
1539 bool a0_cst_p
= TREE_CODE (args
[0]) == REAL_CST
;
1540 bool a1_cst_p
= TREE_CODE (args
[1]) == REAL_CST
;
1541 if (a0_cst_p
|| a1_cst_p
)
1543 if (a0_cst_p
&& a1_cst_p
)
1545 tree t0
= TREE_TYPE (args
[0]);
1546 real_value a0
= (TREE_REAL_CST (args
[0]));
1547 real_value a1
= (TREE_REAL_CST (args
[1]));
1548 if (real_equal (&a1
, &dconst0
))
1550 /* According to real_equal (), +0 equals -0. */
1551 if (real_equal (&a0
, &dconst0
) && real_isinf (&a1
))
1553 real_value res
= dconst2
;
1554 res
.sign
= a0
.sign
^ a1
.sign
;
1556 gimple_build_assign (gimple_call_lhs (stmt
),
1558 build_real (t0
, res
));
1562 gimple_build_assign (gimple_call_lhs (stmt
),
1566 else /* a0_cst_p ^ a1_cst_p. */
1568 real_value const_part
= a0_cst_p
1569 ? TREE_REAL_CST (args
[0]) : TREE_REAL_CST (args
[1]);
1570 if (!real_equal (&const_part
, &dconst0
)
1571 && !real_isinf (&const_part
))
1573 gimple_build_assign (gimple_call_lhs (stmt
),
1574 MULT_EXPR
, args
[0], args
[1]);
1579 gimple_set_vuse (new_stmt
, gimple_vuse (stmt
));
1580 gimple_set_vdef (new_stmt
, gimple_vdef (stmt
));
1592 gsi_replace (gsi
, new_stmt
, true);
1600 aarch64_atomic_assign_expand_fenv (tree
*hold
, tree
*clear
, tree
*update
)
1602 const unsigned AARCH64_FE_INVALID
= 1;
1603 const unsigned AARCH64_FE_DIVBYZERO
= 2;
1604 const unsigned AARCH64_FE_OVERFLOW
= 4;
1605 const unsigned AARCH64_FE_UNDERFLOW
= 8;
1606 const unsigned AARCH64_FE_INEXACT
= 16;
1607 const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT
= (AARCH64_FE_INVALID
1608 | AARCH64_FE_DIVBYZERO
1609 | AARCH64_FE_OVERFLOW
1610 | AARCH64_FE_UNDERFLOW
1611 | AARCH64_FE_INEXACT
);
1612 const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT
= 8;
1613 tree fenv_cr
, fenv_sr
, get_fpcr
, set_fpcr
, mask_cr
, mask_sr
;
1614 tree ld_fenv_cr
, ld_fenv_sr
, masked_fenv_cr
, masked_fenv_sr
, hold_fnclex_cr
;
1615 tree hold_fnclex_sr
, new_fenv_var
, reload_fenv
, restore_fnenv
, get_fpsr
, set_fpsr
;
1616 tree update_call
, atomic_feraiseexcept
, hold_fnclex
, masked_fenv
, ld_fenv
;
1618 /* Generate the equivalence of :
1619 unsigned int fenv_cr;
1620 fenv_cr = __builtin_aarch64_get_fpcr ();
1622 unsigned int fenv_sr;
1623 fenv_sr = __builtin_aarch64_get_fpsr ();
1625 Now set all exceptions to non-stop
1626 unsigned int mask_cr
1627 = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
1628 unsigned int masked_cr;
1629 masked_cr = fenv_cr & mask_cr;
1631 And clear all exception flags
1632 unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
1633 unsigned int masked_cr;
1634 masked_sr = fenv_sr & mask_sr;
1636 __builtin_aarch64_set_cr (masked_cr);
1637 __builtin_aarch64_set_sr (masked_sr); */
1639 fenv_cr
= create_tmp_var_raw (unsigned_type_node
);
1640 fenv_sr
= create_tmp_var_raw (unsigned_type_node
);
1642 get_fpcr
= aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR
];
1643 set_fpcr
= aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR
];
1644 get_fpsr
= aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR
];
1645 set_fpsr
= aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR
];
1647 mask_cr
= build_int_cst (unsigned_type_node
,
1648 ~(AARCH64_FE_ALL_EXCEPT
<< AARCH64_FE_EXCEPT_SHIFT
));
1649 mask_sr
= build_int_cst (unsigned_type_node
,
1650 ~(AARCH64_FE_ALL_EXCEPT
));
1652 ld_fenv_cr
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1653 fenv_cr
, build_call_expr (get_fpcr
, 0));
1654 ld_fenv_sr
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1655 fenv_sr
, build_call_expr (get_fpsr
, 0));
1657 masked_fenv_cr
= build2 (BIT_AND_EXPR
, unsigned_type_node
, fenv_cr
, mask_cr
);
1658 masked_fenv_sr
= build2 (BIT_AND_EXPR
, unsigned_type_node
, fenv_sr
, mask_sr
);
1660 hold_fnclex_cr
= build_call_expr (set_fpcr
, 1, masked_fenv_cr
);
1661 hold_fnclex_sr
= build_call_expr (set_fpsr
, 1, masked_fenv_sr
);
1663 hold_fnclex
= build2 (COMPOUND_EXPR
, void_type_node
, hold_fnclex_cr
,
1665 masked_fenv
= build2 (COMPOUND_EXPR
, void_type_node
, masked_fenv_cr
,
1667 ld_fenv
= build2 (COMPOUND_EXPR
, void_type_node
, ld_fenv_cr
, ld_fenv_sr
);
1669 *hold
= build2 (COMPOUND_EXPR
, void_type_node
,
1670 build2 (COMPOUND_EXPR
, void_type_node
, masked_fenv
, ld_fenv
),
1673 /* Store the value of masked_fenv to clear the exceptions:
1674 __builtin_aarch64_set_fpsr (masked_fenv_sr); */
1676 *clear
= build_call_expr (set_fpsr
, 1, masked_fenv_sr
);
1678 /* Generate the equivalent of :
1679 unsigned int new_fenv_var;
1680 new_fenv_var = __builtin_aarch64_get_fpsr ();
1682 __builtin_aarch64_set_fpsr (fenv_sr);
1684 __atomic_feraiseexcept (new_fenv_var); */
1686 new_fenv_var
= create_tmp_var_raw (unsigned_type_node
);
1687 reload_fenv
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1688 new_fenv_var
, build_call_expr (get_fpsr
, 0));
1689 restore_fnenv
= build_call_expr (set_fpsr
, 1, fenv_sr
);
1690 atomic_feraiseexcept
= builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT
);
1691 update_call
= build_call_expr (atomic_feraiseexcept
, 1,
1692 fold_convert (integer_type_node
, new_fenv_var
));
1693 *update
= build2 (COMPOUND_EXPR
, void_type_node
,
1694 build2 (COMPOUND_EXPR
, void_type_node
,
1695 reload_fenv
, restore_fnenv
), update_call
);
1699 #undef AARCH64_CHECK_BUILTIN_MODE
1700 #undef AARCH64_FIND_FRINT_VARIANT
1719 #include "gt-aarch64-builtins.h"