1 /* Builtins' description for AArch64 SIMD architecture.
2 Copyright (C) 2011-2015 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"
27 #include "basic-block.h"
33 #include "fold-const.h"
34 #include "stor-layout.h"
35 #include "stringpool.h"
38 #include "insn-config.h"
48 #include "langhooks.h"
49 #include "diagnostic-core.h"
50 #include "insn-codes.h"
56 #include "cfgcleanup.h"
57 #include "internal-fn.h"
58 #include "gimple-fold.h"
60 #include "gimple-iterator.h"
62 #define v8qi_UP V8QImode
63 #define v4hi_UP V4HImode
64 #define v2si_UP V2SImode
65 #define v2sf_UP V2SFmode
66 #define v1df_UP V1DFmode
69 #define v16qi_UP V16QImode
70 #define v8hi_UP V8HImode
71 #define v4si_UP V4SImode
72 #define v4sf_UP V4SFmode
73 #define v2di_UP V2DImode
74 #define v2df_UP V2DFmode
86 #define SIMD_MAX_BUILTIN_ARGS 5
88 enum aarch64_type_qualifiers
93 qualifier_unsigned
= 0x1, /* 1 << 0 */
95 qualifier_const
= 0x2, /* 1 << 1 */
97 qualifier_pointer
= 0x4, /* 1 << 2 */
98 /* Used when expanding arguments if an operand could
100 qualifier_immediate
= 0x8, /* 1 << 3 */
101 qualifier_maybe_immediate
= 0x10, /* 1 << 4 */
102 /* void foo (...). */
103 qualifier_void
= 0x20, /* 1 << 5 */
104 /* Some patterns may have internal operands, this qualifier is an
105 instruction to the initialisation code to skip this operand. */
106 qualifier_internal
= 0x40, /* 1 << 6 */
107 /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
108 rather than using the type of the operand. */
109 qualifier_map_mode
= 0x80, /* 1 << 7 */
110 /* qualifier_pointer | qualifier_map_mode */
111 qualifier_pointer_map_mode
= 0x84,
112 /* qualifier_const | qualifier_pointer | qualifier_map_mode */
113 qualifier_const_pointer_map_mode
= 0x86,
114 /* Polynomial types. */
115 qualifier_poly
= 0x100,
116 /* Lane indices - must be in range, and flipped for bigendian. */
117 qualifier_lane_index
= 0x200
124 const enum insn_code code
;
126 enum aarch64_type_qualifiers
*qualifiers
;
127 } aarch64_simd_builtin_datum
;
129 static enum aarch64_type_qualifiers
130 aarch64_types_unop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
131 = { qualifier_none
, qualifier_none
};
132 #define TYPES_UNOP (aarch64_types_unop_qualifiers)
133 static enum aarch64_type_qualifiers
134 aarch64_types_unopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
135 = { qualifier_unsigned
, qualifier_unsigned
};
136 #define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
137 static enum aarch64_type_qualifiers
138 aarch64_types_binop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
139 = { qualifier_none
, qualifier_none
, qualifier_maybe_immediate
};
140 #define TYPES_BINOP (aarch64_types_binop_qualifiers)
141 static enum aarch64_type_qualifiers
142 aarch64_types_binopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
143 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
};
144 #define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
145 static enum aarch64_type_qualifiers
146 aarch64_types_binop_uus_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
147 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_none
};
148 #define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
149 static enum aarch64_type_qualifiers
150 aarch64_types_binop_ssu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
151 = { qualifier_none
, qualifier_none
, qualifier_unsigned
};
152 #define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
153 static enum aarch64_type_qualifiers
154 aarch64_types_binopp_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
155 = { qualifier_poly
, qualifier_poly
, qualifier_poly
};
156 #define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
158 static enum aarch64_type_qualifiers
159 aarch64_types_ternop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
160 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_none
};
161 #define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
162 static enum aarch64_type_qualifiers
163 aarch64_types_ternop_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
164 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_lane_index
};
165 #define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
166 static enum aarch64_type_qualifiers
167 aarch64_types_ternopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
168 = { qualifier_unsigned
, qualifier_unsigned
,
169 qualifier_unsigned
, qualifier_unsigned
};
170 #define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
172 static enum aarch64_type_qualifiers
173 aarch64_types_quadop_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
174 = { qualifier_none
, qualifier_none
, qualifier_none
,
175 qualifier_none
, qualifier_lane_index
};
176 #define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
178 static enum aarch64_type_qualifiers
179 aarch64_types_binop_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
180 = { qualifier_none
, qualifier_none
, qualifier_immediate
};
181 #define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
182 #define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
183 static enum aarch64_type_qualifiers
184 aarch64_types_shift_to_unsigned_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
185 = { qualifier_unsigned
, qualifier_none
, qualifier_immediate
};
186 #define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
187 static enum aarch64_type_qualifiers
188 aarch64_types_unsigned_shift_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
189 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_immediate
};
190 #define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
192 static enum aarch64_type_qualifiers
193 aarch64_types_ternop_imm_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
194 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_immediate
};
195 #define TYPES_SETREG (aarch64_types_ternop_imm_qualifiers)
196 #define TYPES_SHIFTINSERT (aarch64_types_ternop_imm_qualifiers)
197 #define TYPES_SHIFTACC (aarch64_types_ternop_imm_qualifiers)
199 static enum aarch64_type_qualifiers
200 aarch64_types_unsigned_shiftacc_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
201 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
,
202 qualifier_immediate
};
203 #define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
206 static enum aarch64_type_qualifiers
207 aarch64_types_combine_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
208 = { qualifier_none
, qualifier_none
, qualifier_none
};
209 #define TYPES_COMBINE (aarch64_types_combine_qualifiers)
211 static enum aarch64_type_qualifiers
212 aarch64_types_load1_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
213 = { qualifier_none
, qualifier_const_pointer_map_mode
};
214 #define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
215 #define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
216 static enum aarch64_type_qualifiers
217 aarch64_types_loadstruct_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
218 = { qualifier_none
, qualifier_const_pointer_map_mode
,
219 qualifier_none
, qualifier_none
};
220 #define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
222 static enum aarch64_type_qualifiers
223 aarch64_types_bsl_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
224 = { qualifier_poly
, qualifier_unsigned
,
225 qualifier_poly
, qualifier_poly
};
226 #define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
227 static enum aarch64_type_qualifiers
228 aarch64_types_bsl_s_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
229 = { qualifier_none
, qualifier_unsigned
,
230 qualifier_none
, qualifier_none
};
231 #define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
232 static enum aarch64_type_qualifiers
233 aarch64_types_bsl_u_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
234 = { qualifier_unsigned
, qualifier_unsigned
,
235 qualifier_unsigned
, qualifier_unsigned
};
236 #define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
238 /* The first argument (return type) of a store should be void type,
239 which we represent with qualifier_void. Their first operand will be
240 a DImode pointer to the location to store to, so we must use
241 qualifier_map_mode | qualifier_pointer to build a pointer to the
242 element type of the vector. */
243 static enum aarch64_type_qualifiers
244 aarch64_types_store1_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
245 = { qualifier_void
, qualifier_pointer_map_mode
, qualifier_none
};
246 #define TYPES_STORE1 (aarch64_types_store1_qualifiers)
247 #define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
248 static enum aarch64_type_qualifiers
249 aarch64_types_storestruct_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
250 = { qualifier_void
, qualifier_pointer_map_mode
,
251 qualifier_none
, qualifier_none
};
252 #define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
254 #define CF0(N, X) CODE_FOR_aarch64_##N##X
255 #define CF1(N, X) CODE_FOR_##N##X##1
256 #define CF2(N, X) CODE_FOR_##N##X##2
257 #define CF3(N, X) CODE_FOR_##N##X##3
258 #define CF4(N, X) CODE_FOR_##N##X##4
259 #define CF10(N, X) CODE_FOR_##N##X
261 #define VAR1(T, N, MAP, A) \
262 {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T},
263 #define VAR2(T, N, MAP, A, B) \
264 VAR1 (T, N, MAP, A) \
266 #define VAR3(T, N, MAP, A, B, C) \
267 VAR2 (T, N, MAP, A, B) \
269 #define VAR4(T, N, MAP, A, B, C, D) \
270 VAR3 (T, N, MAP, A, B, C) \
272 #define VAR5(T, N, MAP, A, B, C, D, E) \
273 VAR4 (T, N, MAP, A, B, C, D) \
275 #define VAR6(T, N, MAP, A, B, C, D, E, F) \
276 VAR5 (T, N, MAP, A, B, C, D, E) \
278 #define VAR7(T, N, MAP, A, B, C, D, E, F, G) \
279 VAR6 (T, N, MAP, A, B, C, D, E, F) \
281 #define VAR8(T, N, MAP, A, B, C, D, E, F, G, H) \
282 VAR7 (T, N, MAP, A, B, C, D, E, F, G) \
284 #define VAR9(T, N, MAP, A, B, C, D, E, F, G, H, I) \
285 VAR8 (T, N, MAP, A, B, C, D, E, F, G, H) \
287 #define VAR10(T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
288 VAR9 (T, N, MAP, A, B, C, D, E, F, G, H, I) \
290 #define VAR11(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
291 VAR10 (T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
293 #define VAR12(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L) \
294 VAR11 (T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
297 #include "aarch64-builtin-iterators.h"
299 static aarch64_simd_builtin_datum aarch64_simd_builtin_data
[] = {
300 #include "aarch64-simd-builtins.def"
303 /* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
304 #define AARCH64_CRC32_BUILTINS \
305 CRC32_BUILTIN (crc32b, QI) \
306 CRC32_BUILTIN (crc32h, HI) \
307 CRC32_BUILTIN (crc32w, SI) \
308 CRC32_BUILTIN (crc32x, DI) \
309 CRC32_BUILTIN (crc32cb, QI) \
310 CRC32_BUILTIN (crc32ch, HI) \
311 CRC32_BUILTIN (crc32cw, SI) \
312 CRC32_BUILTIN (crc32cx, DI)
318 const enum insn_code icode
;
320 } aarch64_crc_builtin_datum
;
322 #define CRC32_BUILTIN(N, M) \
326 #define VAR1(T, N, MAP, A) \
327 AARCH64_SIMD_BUILTIN_##T##_##N##A,
329 enum aarch64_builtins
333 AARCH64_BUILTIN_GET_FPCR
,
334 AARCH64_BUILTIN_SET_FPCR
,
335 AARCH64_BUILTIN_GET_FPSR
,
336 AARCH64_BUILTIN_SET_FPSR
,
338 AARCH64_SIMD_BUILTIN_BASE
,
339 AARCH64_SIMD_BUILTIN_LANE_CHECK
,
340 #include "aarch64-simd-builtins.def"
341 /* The first enum element which is based on an insn_data pattern. */
342 AARCH64_SIMD_PATTERN_START
= AARCH64_SIMD_BUILTIN_LANE_CHECK
+ 1,
343 AARCH64_SIMD_BUILTIN_MAX
= AARCH64_SIMD_PATTERN_START
344 + ARRAY_SIZE (aarch64_simd_builtin_data
) - 1,
345 AARCH64_CRC32_BUILTIN_BASE
,
346 AARCH64_CRC32_BUILTINS
347 AARCH64_CRC32_BUILTIN_MAX
,
352 #define CRC32_BUILTIN(N, M) \
353 {"__builtin_aarch64_"#N, M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
355 static aarch64_crc_builtin_datum aarch64_crc_builtin_data
[] = {
356 AARCH64_CRC32_BUILTINS
361 static GTY(()) tree aarch64_builtin_decls
[AARCH64_BUILTIN_MAX
];
363 #define NUM_DREG_TYPES 6
364 #define NUM_QREG_TYPES 6
366 /* Internal scalar builtin types. These types are used to support
367 neon intrinsic builtins. They are _not_ user-visible types. Therefore
368 the mangling for these types are implementation defined. */
369 const char *aarch64_scalar_builtin_types
[] = {
370 "__builtin_aarch64_simd_qi",
371 "__builtin_aarch64_simd_hi",
372 "__builtin_aarch64_simd_si",
373 "__builtin_aarch64_simd_sf",
374 "__builtin_aarch64_simd_di",
375 "__builtin_aarch64_simd_df",
376 "__builtin_aarch64_simd_poly8",
377 "__builtin_aarch64_simd_poly16",
378 "__builtin_aarch64_simd_poly64",
379 "__builtin_aarch64_simd_poly128",
380 "__builtin_aarch64_simd_ti",
381 "__builtin_aarch64_simd_uqi",
382 "__builtin_aarch64_simd_uhi",
383 "__builtin_aarch64_simd_usi",
384 "__builtin_aarch64_simd_udi",
385 "__builtin_aarch64_simd_ei",
386 "__builtin_aarch64_simd_oi",
387 "__builtin_aarch64_simd_ci",
388 "__builtin_aarch64_simd_xi",
392 #define ENTRY(E, M, Q, G) E,
393 enum aarch64_simd_type
395 #include "aarch64-simd-builtin-types.def"
396 ARM_NEON_H_TYPES_LAST
400 struct aarch64_simd_type_info
402 enum aarch64_simd_type type
;
404 /* Internal type name. */
407 /* Internal type name(mangled). The mangled names conform to the
408 AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
409 Appendix A). To qualify for emission with the mangled names defined in
410 that document, a vector type must not only be of the correct mode but also
411 be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
412 types are registered by aarch64_init_simd_builtin_types (). In other
413 words, vector types defined in other ways e.g. via vector_size attribute
414 will get default mangled names. */
423 /* Machine mode the internal type maps to. */
424 enum machine_mode mode
;
427 enum aarch64_type_qualifiers q
;
430 #define ENTRY(E, M, Q, G) \
431 {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, M##mode, qualifier_##Q},
432 static struct aarch64_simd_type_info aarch64_simd_types
[] = {
433 #include "aarch64-simd-builtin-types.def"
437 static tree aarch64_simd_intOI_type_node
= NULL_TREE
;
438 static tree aarch64_simd_intEI_type_node
= NULL_TREE
;
439 static tree aarch64_simd_intCI_type_node
= NULL_TREE
;
440 static tree aarch64_simd_intXI_type_node
= NULL_TREE
;
443 aarch64_mangle_builtin_scalar_type (const_tree type
)
447 while (aarch64_scalar_builtin_types
[i
] != NULL
)
449 const char *name
= aarch64_scalar_builtin_types
[i
];
451 if (TREE_CODE (TYPE_NAME (type
)) == TYPE_DECL
452 && DECL_NAME (TYPE_NAME (type
))
453 && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
))), name
))
454 return aarch64_scalar_builtin_types
[i
];
461 aarch64_mangle_builtin_vector_type (const_tree type
)
464 int nelts
= sizeof (aarch64_simd_types
) / sizeof (aarch64_simd_types
[0]);
466 for (i
= 0; i
< nelts
; i
++)
467 if (aarch64_simd_types
[i
].mode
== TYPE_MODE (type
)
469 && TREE_CODE (TYPE_NAME (type
)) == TYPE_DECL
470 && DECL_NAME (TYPE_NAME (type
))
472 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type
))),
473 aarch64_simd_types
[i
].name
))
474 return aarch64_simd_types
[i
].mangle
;
480 aarch64_mangle_builtin_type (const_tree type
)
483 /* Walk through all the AArch64 builtins types tables to filter out the
485 if ((mangle
= aarch64_mangle_builtin_vector_type (type
))
486 || (mangle
= aarch64_mangle_builtin_scalar_type (type
)))
493 aarch64_simd_builtin_std_type (enum machine_mode mode
,
494 enum aarch64_type_qualifiers q
)
496 #define QUAL_TYPE(M) \
497 ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
501 return QUAL_TYPE (QI
);
503 return QUAL_TYPE (HI
);
505 return QUAL_TYPE (SI
);
507 return QUAL_TYPE (DI
);
509 return QUAL_TYPE (TI
);
511 return aarch64_simd_intOI_type_node
;
513 return aarch64_simd_intEI_type_node
;
515 return aarch64_simd_intCI_type_node
;
517 return aarch64_simd_intXI_type_node
;
519 return float_type_node
;
521 return double_type_node
;
529 aarch64_lookup_simd_builtin_type (enum machine_mode mode
,
530 enum aarch64_type_qualifiers q
)
533 int nelts
= sizeof (aarch64_simd_types
) / sizeof (aarch64_simd_types
[0]);
535 /* Non-poly scalar modes map to standard types not in the table. */
536 if (q
!= qualifier_poly
&& !VECTOR_MODE_P (mode
))
537 return aarch64_simd_builtin_std_type (mode
, q
);
539 for (i
= 0; i
< nelts
; i
++)
540 if (aarch64_simd_types
[i
].mode
== mode
541 && aarch64_simd_types
[i
].q
== q
)
542 return aarch64_simd_types
[i
].itype
;
548 aarch64_simd_builtin_type (enum machine_mode mode
,
549 bool unsigned_p
, bool poly_p
)
552 return aarch64_lookup_simd_builtin_type (mode
, qualifier_poly
);
554 return aarch64_lookup_simd_builtin_type (mode
, qualifier_unsigned
);
556 return aarch64_lookup_simd_builtin_type (mode
, qualifier_none
);
560 aarch64_init_simd_builtin_types (void)
563 int nelts
= sizeof (aarch64_simd_types
) / sizeof (aarch64_simd_types
[0]);
566 /* Init all the element types built by the front-end. */
567 aarch64_simd_types
[Int8x8_t
].eltype
= intQI_type_node
;
568 aarch64_simd_types
[Int8x16_t
].eltype
= intQI_type_node
;
569 aarch64_simd_types
[Int16x4_t
].eltype
= intHI_type_node
;
570 aarch64_simd_types
[Int16x8_t
].eltype
= intHI_type_node
;
571 aarch64_simd_types
[Int32x2_t
].eltype
= intSI_type_node
;
572 aarch64_simd_types
[Int32x4_t
].eltype
= intSI_type_node
;
573 aarch64_simd_types
[Int64x1_t
].eltype
= intDI_type_node
;
574 aarch64_simd_types
[Int64x2_t
].eltype
= intDI_type_node
;
575 aarch64_simd_types
[Uint8x8_t
].eltype
= unsigned_intQI_type_node
;
576 aarch64_simd_types
[Uint8x16_t
].eltype
= unsigned_intQI_type_node
;
577 aarch64_simd_types
[Uint16x4_t
].eltype
= unsigned_intHI_type_node
;
578 aarch64_simd_types
[Uint16x8_t
].eltype
= unsigned_intHI_type_node
;
579 aarch64_simd_types
[Uint32x2_t
].eltype
= unsigned_intSI_type_node
;
580 aarch64_simd_types
[Uint32x4_t
].eltype
= unsigned_intSI_type_node
;
581 aarch64_simd_types
[Uint64x1_t
].eltype
= unsigned_intDI_type_node
;
582 aarch64_simd_types
[Uint64x2_t
].eltype
= unsigned_intDI_type_node
;
584 /* Poly types are a world of their own. */
585 aarch64_simd_types
[Poly8_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
=
586 build_distinct_type_copy (unsigned_intQI_type_node
);
587 aarch64_simd_types
[Poly16_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
=
588 build_distinct_type_copy (unsigned_intHI_type_node
);
589 aarch64_simd_types
[Poly64_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
=
590 build_distinct_type_copy (unsigned_intDI_type_node
);
591 aarch64_simd_types
[Poly128_t
].eltype
= aarch64_simd_types
[Poly128_t
].itype
=
592 build_distinct_type_copy (unsigned_intTI_type_node
);
593 /* Init poly vector element types with scalar poly types. */
594 aarch64_simd_types
[Poly8x8_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
;
595 aarch64_simd_types
[Poly8x16_t
].eltype
= aarch64_simd_types
[Poly8_t
].itype
;
596 aarch64_simd_types
[Poly16x4_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
;
597 aarch64_simd_types
[Poly16x8_t
].eltype
= aarch64_simd_types
[Poly16_t
].itype
;
598 aarch64_simd_types
[Poly64x1_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
;
599 aarch64_simd_types
[Poly64x2_t
].eltype
= aarch64_simd_types
[Poly64_t
].itype
;
601 /* Continue with standard types. */
602 aarch64_simd_types
[Float32x2_t
].eltype
= float_type_node
;
603 aarch64_simd_types
[Float32x4_t
].eltype
= float_type_node
;
604 aarch64_simd_types
[Float64x1_t
].eltype
= double_type_node
;
605 aarch64_simd_types
[Float64x2_t
].eltype
= double_type_node
;
607 for (i
= 0; i
< nelts
; i
++)
609 tree eltype
= aarch64_simd_types
[i
].eltype
;
610 enum machine_mode mode
= aarch64_simd_types
[i
].mode
;
612 if (aarch64_simd_types
[i
].itype
== NULL
)
613 aarch64_simd_types
[i
].itype
=
614 build_distinct_type_copy
615 (build_vector_type (eltype
, GET_MODE_NUNITS (mode
)));
617 tdecl
= add_builtin_type (aarch64_simd_types
[i
].name
,
618 aarch64_simd_types
[i
].itype
);
619 TYPE_NAME (aarch64_simd_types
[i
].itype
) = tdecl
;
620 SET_TYPE_STRUCTURAL_EQUALITY (aarch64_simd_types
[i
].itype
);
623 #define AARCH64_BUILD_SIGNED_TYPE(mode) \
624 make_signed_type (GET_MODE_PRECISION (mode));
625 aarch64_simd_intOI_type_node
= AARCH64_BUILD_SIGNED_TYPE (OImode
);
626 aarch64_simd_intEI_type_node
= AARCH64_BUILD_SIGNED_TYPE (EImode
);
627 aarch64_simd_intCI_type_node
= AARCH64_BUILD_SIGNED_TYPE (CImode
);
628 aarch64_simd_intXI_type_node
= AARCH64_BUILD_SIGNED_TYPE (XImode
);
629 #undef AARCH64_BUILD_SIGNED_TYPE
631 tdecl
= add_builtin_type
632 ("__builtin_aarch64_simd_ei" , aarch64_simd_intEI_type_node
);
633 TYPE_NAME (aarch64_simd_intEI_type_node
) = tdecl
;
634 tdecl
= add_builtin_type
635 ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node
);
636 TYPE_NAME (aarch64_simd_intOI_type_node
) = tdecl
;
637 tdecl
= add_builtin_type
638 ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node
);
639 TYPE_NAME (aarch64_simd_intCI_type_node
) = tdecl
;
640 tdecl
= add_builtin_type
641 ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node
);
642 TYPE_NAME (aarch64_simd_intXI_type_node
) = tdecl
;
646 aarch64_init_simd_builtin_scalar_types (void)
648 /* Define typedefs for all the standard scalar types. */
649 (*lang_hooks
.types
.register_builtin_type
) (intQI_type_node
,
650 "__builtin_aarch64_simd_qi");
651 (*lang_hooks
.types
.register_builtin_type
) (intHI_type_node
,
652 "__builtin_aarch64_simd_hi");
653 (*lang_hooks
.types
.register_builtin_type
) (intSI_type_node
,
654 "__builtin_aarch64_simd_si");
655 (*lang_hooks
.types
.register_builtin_type
) (float_type_node
,
656 "__builtin_aarch64_simd_sf");
657 (*lang_hooks
.types
.register_builtin_type
) (intDI_type_node
,
658 "__builtin_aarch64_simd_di");
659 (*lang_hooks
.types
.register_builtin_type
) (double_type_node
,
660 "__builtin_aarch64_simd_df");
661 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intQI_type_node
,
662 "__builtin_aarch64_simd_poly8");
663 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intHI_type_node
,
664 "__builtin_aarch64_simd_poly16");
665 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intDI_type_node
,
666 "__builtin_aarch64_simd_poly64");
667 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intTI_type_node
,
668 "__builtin_aarch64_simd_poly128");
669 (*lang_hooks
.types
.register_builtin_type
) (intTI_type_node
,
670 "__builtin_aarch64_simd_ti");
671 /* Unsigned integer types for various mode sizes. */
672 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intQI_type_node
,
673 "__builtin_aarch64_simd_uqi");
674 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intHI_type_node
,
675 "__builtin_aarch64_simd_uhi");
676 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intSI_type_node
,
677 "__builtin_aarch64_simd_usi");
678 (*lang_hooks
.types
.register_builtin_type
) (unsigned_intDI_type_node
,
679 "__builtin_aarch64_simd_udi");
683 aarch64_init_simd_builtins (void)
685 unsigned int i
, fcode
= AARCH64_SIMD_PATTERN_START
;
687 aarch64_init_simd_builtin_types ();
689 /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
690 Therefore we need to preserve the old __builtin scalar types. It can be
691 removed once all the intrinsics become strongly typed using the qualifier
693 aarch64_init_simd_builtin_scalar_types ();
695 tree lane_check_fpr
= build_function_type_list (void_type_node
,
700 aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_LANE_CHECK
] =
701 add_builtin_function ("__builtin_aarch64_im_lane_boundsi", lane_check_fpr
,
702 AARCH64_SIMD_BUILTIN_LANE_CHECK
, BUILT_IN_MD
,
705 for (i
= 0; i
< ARRAY_SIZE (aarch64_simd_builtin_data
); i
++, fcode
++)
707 bool print_type_signature_p
= false;
708 char type_signature
[SIMD_MAX_BUILTIN_ARGS
] = { 0 };
709 aarch64_simd_builtin_datum
*d
= &aarch64_simd_builtin_data
[i
];
716 /* We must track two variables here. op_num is
717 the operand number as in the RTL pattern. This is
718 required to access the mode (e.g. V4SF mode) of the
719 argument, from which the base type can be derived.
720 arg_num is an index in to the qualifiers data, which
721 gives qualifiers to the type (e.g. const unsigned).
722 The reason these two variables may differ by one is the
723 void return type. While all return types take the 0th entry
724 in the qualifiers array, there is no operand for them in the
726 int op_num
= insn_data
[d
->code
].n_operands
- 1;
727 int arg_num
= d
->qualifiers
[0] & qualifier_void
730 tree return_type
= void_type_node
, args
= void_list_node
;
733 /* Build a function type directly from the insn_data for this
734 builtin. The build_function_type () function takes care of
735 removing duplicates for us. */
736 for (; op_num
>= 0; arg_num
--, op_num
--)
738 machine_mode op_mode
= insn_data
[d
->code
].operand
[op_num
].mode
;
739 enum aarch64_type_qualifiers qualifiers
= d
->qualifiers
[arg_num
];
741 if (qualifiers
& qualifier_unsigned
)
743 type_signature
[arg_num
] = 'u';
744 print_type_signature_p
= true;
746 else if (qualifiers
& qualifier_poly
)
748 type_signature
[arg_num
] = 'p';
749 print_type_signature_p
= true;
752 type_signature
[arg_num
] = 's';
754 /* Skip an internal operand for vget_{low, high}. */
755 if (qualifiers
& qualifier_internal
)
758 /* Some builtins have different user-facing types
759 for certain arguments, encoded in d->mode. */
760 if (qualifiers
& qualifier_map_mode
)
763 /* For pointers, we want a pointer to the basic type
765 if (qualifiers
& qualifier_pointer
&& VECTOR_MODE_P (op_mode
))
766 op_mode
= GET_MODE_INNER (op_mode
);
768 eltype
= aarch64_simd_builtin_type
770 (qualifiers
& qualifier_unsigned
) != 0,
771 (qualifiers
& qualifier_poly
) != 0);
772 gcc_assert (eltype
!= NULL
);
774 /* Add qualifiers. */
775 if (qualifiers
& qualifier_const
)
776 eltype
= build_qualified_type (eltype
, TYPE_QUAL_CONST
);
778 if (qualifiers
& qualifier_pointer
)
779 eltype
= build_pointer_type (eltype
);
781 /* If we have reached arg_num == 0, we are at a non-void
782 return type. Otherwise, we are still processing
785 return_type
= eltype
;
787 args
= tree_cons (NULL_TREE
, eltype
, args
);
790 ftype
= build_function_type (return_type
, args
);
792 gcc_assert (ftype
!= NULL
);
794 if (print_type_signature_p
)
795 snprintf (namebuf
, sizeof (namebuf
), "__builtin_aarch64_%s_%s",
796 d
->name
, type_signature
);
798 snprintf (namebuf
, sizeof (namebuf
), "__builtin_aarch64_%s",
801 fndecl
= add_builtin_function (namebuf
, ftype
, fcode
, BUILT_IN_MD
,
803 aarch64_builtin_decls
[fcode
] = fndecl
;
808 aarch64_init_crc32_builtins ()
810 tree usi_type
= aarch64_simd_builtin_std_type (SImode
, qualifier_unsigned
);
813 for (i
= 0; i
< ARRAY_SIZE (aarch64_crc_builtin_data
); ++i
)
815 aarch64_crc_builtin_datum
* d
= &aarch64_crc_builtin_data
[i
];
816 tree argtype
= aarch64_simd_builtin_std_type (d
->mode
,
818 tree ftype
= build_function_type_list (usi_type
, usi_type
, argtype
, NULL_TREE
);
819 tree fndecl
= add_builtin_function (d
->name
, ftype
, d
->fcode
,
820 BUILT_IN_MD
, NULL
, NULL_TREE
);
822 aarch64_builtin_decls
[d
->fcode
] = fndecl
;
827 aarch64_init_builtins (void)
830 = build_function_type_list (void_type_node
, unsigned_type_node
, NULL
);
832 = build_function_type_list (unsigned_type_node
, NULL
);
834 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR
]
835 = add_builtin_function ("__builtin_aarch64_get_fpcr", ftype_get_fpr
,
836 AARCH64_BUILTIN_GET_FPCR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
837 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR
]
838 = add_builtin_function ("__builtin_aarch64_set_fpcr", ftype_set_fpr
,
839 AARCH64_BUILTIN_SET_FPCR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
840 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR
]
841 = add_builtin_function ("__builtin_aarch64_get_fpsr", ftype_get_fpr
,
842 AARCH64_BUILTIN_GET_FPSR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
843 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR
]
844 = add_builtin_function ("__builtin_aarch64_set_fpsr", ftype_set_fpr
,
845 AARCH64_BUILTIN_SET_FPSR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
848 aarch64_init_simd_builtins ();
850 aarch64_init_crc32_builtins ();
854 aarch64_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
856 if (code
>= AARCH64_BUILTIN_MAX
)
857 return error_mark_node
;
859 return aarch64_builtin_decls
[code
];
864 SIMD_ARG_COPY_TO_REG
,
871 aarch64_simd_expand_args (rtx target
, int icode
, int have_retval
,
872 tree exp
, builtin_simd_arg
*args
)
875 rtx op
[SIMD_MAX_BUILTIN_ARGS
+ 1]; /* First element for result operand. */
880 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
882 || GET_MODE (target
) != tmode
883 || !(*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
884 target
= gen_reg_rtx (tmode
);
890 builtin_simd_arg thisarg
= args
[opc
- have_retval
];
892 if (thisarg
== SIMD_ARG_STOP
)
896 tree arg
= CALL_EXPR_ARG (exp
, opc
- have_retval
);
897 enum machine_mode mode
= insn_data
[icode
].operand
[opc
].mode
;
898 op
[opc
] = expand_normal (arg
);
902 case SIMD_ARG_COPY_TO_REG
:
903 if (POINTER_TYPE_P (TREE_TYPE (arg
)))
904 op
[opc
] = convert_memory_address (Pmode
, op
[opc
]);
905 /*gcc_assert (GET_MODE (op[opc]) == mode); */
906 if (!(*insn_data
[icode
].operand
[opc
].predicate
)
908 op
[opc
] = copy_to_mode_reg (mode
, op
[opc
]);
911 case SIMD_ARG_LANE_INDEX
:
912 /* Must be a previous operand into which this is an index. */
913 gcc_assert (opc
> 0);
914 if (CONST_INT_P (op
[opc
]))
916 machine_mode vmode
= insn_data
[icode
].operand
[opc
- 1].mode
;
917 aarch64_simd_lane_bounds (op
[opc
],
918 0, GET_MODE_NUNITS (vmode
), exp
);
919 /* Keep to GCC-vector-extension lane indices in the RTL. */
920 op
[opc
] = GEN_INT (ENDIAN_LANE_N (vmode
, INTVAL (op
[opc
])));
922 /* Fall through - if the lane index isn't a constant then
923 the next case will error. */
924 case SIMD_ARG_CONSTANT
:
925 if (!(*insn_data
[icode
].operand
[opc
].predicate
)
928 error ("%Kargument %d must be a constant immediate",
929 exp
, opc
+ 1 - have_retval
);
945 pat
= GEN_FCN (icode
) (op
[0]);
949 pat
= GEN_FCN (icode
) (op
[0], op
[1]);
953 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2]);
957 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3]);
961 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3], op
[4]);
965 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3], op
[4], op
[5]);
980 /* Expand an AArch64 AdvSIMD builtin(intrinsic). */
982 aarch64_simd_expand_builtin (int fcode
, tree exp
, rtx target
)
984 if (fcode
== AARCH64_SIMD_BUILTIN_LANE_CHECK
)
986 rtx totalsize
= expand_normal (CALL_EXPR_ARG (exp
, 0));
987 rtx elementsize
= expand_normal (CALL_EXPR_ARG (exp
, 1));
988 if (CONST_INT_P (totalsize
) && CONST_INT_P (elementsize
)
989 && UINTVAL (elementsize
) != 0
990 && UINTVAL (totalsize
) != 0)
992 rtx lane_idx
= expand_normal (CALL_EXPR_ARG (exp
, 2));
993 if (CONST_INT_P (lane_idx
))
994 aarch64_simd_lane_bounds (lane_idx
, 0,
996 / UINTVAL (elementsize
),
999 error ("%Klane index must be a constant immediate", exp
);
1002 error ("%Ktotal size and element size must be a non-zero constant immediate", exp
);
1003 /* Don't generate any RTL. */
1006 aarch64_simd_builtin_datum
*d
=
1007 &aarch64_simd_builtin_data
[fcode
- AARCH64_SIMD_PATTERN_START
];
1008 enum insn_code icode
= d
->code
;
1009 builtin_simd_arg args
[SIMD_MAX_BUILTIN_ARGS
+ 1];
1010 int num_args
= insn_data
[d
->code
].n_operands
;
1014 is_void
= !!(d
->qualifiers
[0] & qualifier_void
);
1016 num_args
+= is_void
;
1018 for (k
= 1; k
< num_args
; k
++)
1020 /* We have four arrays of data, each indexed in a different fashion.
1021 qualifiers - element 0 always describes the function return type.
1022 operands - element 0 is either the operand for return value (if
1023 the function has a non-void return type) or the operand for the
1025 expr_args - element 0 always holds the first argument.
1026 args - element 0 is always used for the return type. */
1027 int qualifiers_k
= k
;
1028 int operands_k
= k
- is_void
;
1029 int expr_args_k
= k
- 1;
1031 if (d
->qualifiers
[qualifiers_k
] & qualifier_lane_index
)
1032 args
[k
] = SIMD_ARG_LANE_INDEX
;
1033 else if (d
->qualifiers
[qualifiers_k
] & qualifier_immediate
)
1034 args
[k
] = SIMD_ARG_CONSTANT
;
1035 else if (d
->qualifiers
[qualifiers_k
] & qualifier_maybe_immediate
)
1038 = expand_normal (CALL_EXPR_ARG (exp
,
1040 /* Handle constants only if the predicate allows it. */
1041 bool op_const_int_p
=
1043 && (*insn_data
[icode
].operand
[operands_k
].predicate
)
1044 (arg
, insn_data
[icode
].operand
[operands_k
].mode
));
1045 args
[k
] = op_const_int_p
? SIMD_ARG_CONSTANT
: SIMD_ARG_COPY_TO_REG
;
1048 args
[k
] = SIMD_ARG_COPY_TO_REG
;
1051 args
[k
] = SIMD_ARG_STOP
;
1053 /* The interface to aarch64_simd_expand_args expects a 0 if
1054 the function is void, and a 1 if it is not. */
1055 return aarch64_simd_expand_args
1056 (target
, icode
, !is_void
, exp
, &args
[1]);
1060 aarch64_crc32_expand_builtin (int fcode
, tree exp
, rtx target
)
1063 aarch64_crc_builtin_datum
*d
1064 = &aarch64_crc_builtin_data
[fcode
- (AARCH64_CRC32_BUILTIN_BASE
+ 1)];
1065 enum insn_code icode
= d
->icode
;
1066 tree arg0
= CALL_EXPR_ARG (exp
, 0);
1067 tree arg1
= CALL_EXPR_ARG (exp
, 1);
1068 rtx op0
= expand_normal (arg0
);
1069 rtx op1
= expand_normal (arg1
);
1070 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
1071 machine_mode mode0
= insn_data
[icode
].operand
[1].mode
;
1072 machine_mode mode1
= insn_data
[icode
].operand
[2].mode
;
1075 || GET_MODE (target
) != tmode
1076 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
1077 target
= gen_reg_rtx (tmode
);
1079 gcc_assert ((GET_MODE (op0
) == mode0
|| GET_MODE (op0
) == VOIDmode
)
1080 && (GET_MODE (op1
) == mode1
|| GET_MODE (op1
) == VOIDmode
));
1082 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
1083 op0
= copy_to_mode_reg (mode0
, op0
);
1084 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
1085 op1
= copy_to_mode_reg (mode1
, op1
);
1087 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
1095 /* Expand an expression EXP that calls a built-in function,
1096 with result going to TARGET if that's convenient. */
1098 aarch64_expand_builtin (tree exp
,
1100 rtx subtarget ATTRIBUTE_UNUSED
,
1101 machine_mode mode ATTRIBUTE_UNUSED
,
1102 int ignore ATTRIBUTE_UNUSED
)
1104 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1105 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1112 case AARCH64_BUILTIN_GET_FPCR
:
1113 case AARCH64_BUILTIN_SET_FPCR
:
1114 case AARCH64_BUILTIN_GET_FPSR
:
1115 case AARCH64_BUILTIN_SET_FPSR
:
1116 if ((fcode
== AARCH64_BUILTIN_GET_FPCR
)
1117 || (fcode
== AARCH64_BUILTIN_GET_FPSR
))
1119 icode
= (fcode
== AARCH64_BUILTIN_GET_FPSR
) ?
1120 CODE_FOR_get_fpsr
: CODE_FOR_get_fpcr
;
1121 target
= gen_reg_rtx (SImode
);
1122 pat
= GEN_FCN (icode
) (target
);
1127 icode
= (fcode
== AARCH64_BUILTIN_SET_FPSR
) ?
1128 CODE_FOR_set_fpsr
: CODE_FOR_set_fpcr
;
1129 arg0
= CALL_EXPR_ARG (exp
, 0);
1130 op0
= expand_normal (arg0
);
1131 pat
= GEN_FCN (icode
) (op0
);
1137 if (fcode
>= AARCH64_SIMD_BUILTIN_BASE
&& fcode
<= AARCH64_SIMD_BUILTIN_MAX
)
1138 return aarch64_simd_expand_builtin (fcode
, exp
, target
);
1139 else if (fcode
>= AARCH64_CRC32_BUILTIN_BASE
&& fcode
<= AARCH64_CRC32_BUILTIN_MAX
)
1140 return aarch64_crc32_expand_builtin (fcode
, exp
, target
);
1146 aarch64_builtin_vectorized_function (tree fndecl
, tree type_out
, tree type_in
)
1148 machine_mode in_mode
, out_mode
;
1151 if (TREE_CODE (type_out
) != VECTOR_TYPE
1152 || TREE_CODE (type_in
) != VECTOR_TYPE
)
1155 out_mode
= TYPE_MODE (TREE_TYPE (type_out
));
1156 out_n
= TYPE_VECTOR_SUBPARTS (type_out
);
1157 in_mode
= TYPE_MODE (TREE_TYPE (type_in
));
1158 in_n
= TYPE_VECTOR_SUBPARTS (type_in
);
1160 #undef AARCH64_CHECK_BUILTIN_MODE
1161 #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
1162 #define AARCH64_FIND_FRINT_VARIANT(N) \
1163 (AARCH64_CHECK_BUILTIN_MODE (2, D) \
1164 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
1165 : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
1166 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
1167 : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
1168 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
1170 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
1172 enum built_in_function fn
= DECL_FUNCTION_CODE (fndecl
);
1175 #undef AARCH64_CHECK_BUILTIN_MODE
1176 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1177 (out_mode == N##Fmode && out_n == C \
1178 && in_mode == N##Fmode && in_n == C)
1179 case BUILT_IN_FLOOR
:
1180 case BUILT_IN_FLOORF
:
1181 return AARCH64_FIND_FRINT_VARIANT (floor
);
1183 case BUILT_IN_CEILF
:
1184 return AARCH64_FIND_FRINT_VARIANT (ceil
);
1185 case BUILT_IN_TRUNC
:
1186 case BUILT_IN_TRUNCF
:
1187 return AARCH64_FIND_FRINT_VARIANT (btrunc
);
1188 case BUILT_IN_ROUND
:
1189 case BUILT_IN_ROUNDF
:
1190 return AARCH64_FIND_FRINT_VARIANT (round
);
1191 case BUILT_IN_NEARBYINT
:
1192 case BUILT_IN_NEARBYINTF
:
1193 return AARCH64_FIND_FRINT_VARIANT (nearbyint
);
1195 case BUILT_IN_SQRTF
:
1196 return AARCH64_FIND_FRINT_VARIANT (sqrt
);
1197 #undef AARCH64_CHECK_BUILTIN_MODE
1198 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1199 (out_mode == SImode && out_n == C \
1200 && in_mode == N##Imode && in_n == C)
1203 if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1204 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_clzv4si
];
1209 if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1210 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si
];
1211 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1212 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si
];
1215 #undef AARCH64_CHECK_BUILTIN_MODE
1216 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1217 (out_mode == N##Imode && out_n == C \
1218 && in_mode == N##Fmode && in_n == C)
1219 case BUILT_IN_LFLOOR
:
1220 case BUILT_IN_LFLOORF
:
1221 case BUILT_IN_LLFLOOR
:
1222 case BUILT_IN_IFLOORF
:
1224 enum aarch64_builtins builtin
;
1225 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1226 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di
;
1227 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1228 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si
;
1229 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1230 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si
;
1234 return aarch64_builtin_decls
[builtin
];
1236 case BUILT_IN_LCEIL
:
1237 case BUILT_IN_LCEILF
:
1238 case BUILT_IN_LLCEIL
:
1239 case BUILT_IN_ICEILF
:
1241 enum aarch64_builtins builtin
;
1242 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1243 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di
;
1244 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1245 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si
;
1246 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1247 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si
;
1251 return aarch64_builtin_decls
[builtin
];
1253 case BUILT_IN_LROUND
:
1254 case BUILT_IN_IROUNDF
:
1256 enum aarch64_builtins builtin
;
1257 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1258 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di
;
1259 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1260 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si
;
1261 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1262 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si
;
1266 return aarch64_builtin_decls
[builtin
];
1268 case BUILT_IN_BSWAP16
:
1269 #undef AARCH64_CHECK_BUILTIN_MODE
1270 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1271 (out_mode == N##Imode && out_n == C \
1272 && in_mode == N##Imode && in_n == C)
1273 if (AARCH64_CHECK_BUILTIN_MODE (4, H
))
1274 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4hi
];
1275 else if (AARCH64_CHECK_BUILTIN_MODE (8, H
))
1276 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv8hi
];
1279 case BUILT_IN_BSWAP32
:
1280 if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1281 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2si
];
1282 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1283 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4si
];
1286 case BUILT_IN_BSWAP64
:
1287 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1288 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2di
];
1300 #define VAR1(T, N, MAP, A) \
1301 case AARCH64_SIMD_BUILTIN_##T##_##N##A:
1304 aarch64_fold_builtin (tree fndecl
, int n_args ATTRIBUTE_UNUSED
, tree
*args
,
1305 bool ignore ATTRIBUTE_UNUSED
)
1307 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1308 tree type
= TREE_TYPE (TREE_TYPE (fndecl
));
1312 BUILTIN_VDQF (UNOP
, abs
, 2)
1313 return fold_build1 (ABS_EXPR
, type
, args
[0]);
1315 VAR1 (UNOP
, floatv2si
, 2, v2sf
)
1316 VAR1 (UNOP
, floatv4si
, 2, v4sf
)
1317 VAR1 (UNOP
, floatv2di
, 2, v2df
)
1318 return fold_build1 (FLOAT_EXPR
, type
, args
[0]);
1327 aarch64_gimple_fold_builtin (gimple_stmt_iterator
*gsi
)
1329 bool changed
= false;
1330 gimple stmt
= gsi_stmt (*gsi
);
1331 tree call
= gimple_call_fn (stmt
);
1333 gimple new_stmt
= NULL
;
1337 fndecl
= gimple_call_fndecl (stmt
);
1340 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1341 int nargs
= gimple_call_num_args (stmt
);
1342 tree
*args
= (nargs
> 0
1343 ? gimple_call_arg_ptr (stmt
, 0)
1344 : &error_mark_node
);
1346 /* We use gimple's REDUC_(PLUS|MIN|MAX)_EXPRs for float, signed int
1347 and unsigned int; it will distinguish according to the types of
1348 the arguments to the __builtin. */
1351 BUILTIN_VALL (UNOP
, reduc_plus_scal_
, 10)
1352 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
1353 REDUC_PLUS_EXPR
, args
[0]);
1355 BUILTIN_VDQIF (UNOP
, reduc_smax_scal_
, 10)
1356 BUILTIN_VDQ_BHSI (UNOPU
, reduc_umax_scal_
, 10)
1357 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
1358 REDUC_MAX_EXPR
, args
[0]);
1360 BUILTIN_VDQIF (UNOP
, reduc_smin_scal_
, 10)
1361 BUILTIN_VDQ_BHSI (UNOPU
, reduc_umin_scal_
, 10)
1362 new_stmt
= gimple_build_assign (gimple_call_lhs (stmt
),
1363 REDUC_MIN_EXPR
, args
[0]);
1374 gsi_replace (gsi
, new_stmt
, true);
1382 aarch64_atomic_assign_expand_fenv (tree
*hold
, tree
*clear
, tree
*update
)
1384 const unsigned AARCH64_FE_INVALID
= 1;
1385 const unsigned AARCH64_FE_DIVBYZERO
= 2;
1386 const unsigned AARCH64_FE_OVERFLOW
= 4;
1387 const unsigned AARCH64_FE_UNDERFLOW
= 8;
1388 const unsigned AARCH64_FE_INEXACT
= 16;
1389 const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT
= (AARCH64_FE_INVALID
1390 | AARCH64_FE_DIVBYZERO
1391 | AARCH64_FE_OVERFLOW
1392 | AARCH64_FE_UNDERFLOW
1393 | AARCH64_FE_INEXACT
);
1394 const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT
= 8;
1395 tree fenv_cr
, fenv_sr
, get_fpcr
, set_fpcr
, mask_cr
, mask_sr
;
1396 tree ld_fenv_cr
, ld_fenv_sr
, masked_fenv_cr
, masked_fenv_sr
, hold_fnclex_cr
;
1397 tree hold_fnclex_sr
, new_fenv_var
, reload_fenv
, restore_fnenv
, get_fpsr
, set_fpsr
;
1398 tree update_call
, atomic_feraiseexcept
, hold_fnclex
, masked_fenv
, ld_fenv
;
1400 /* Generate the equivalence of :
1401 unsigned int fenv_cr;
1402 fenv_cr = __builtin_aarch64_get_fpcr ();
1404 unsigned int fenv_sr;
1405 fenv_sr = __builtin_aarch64_get_fpsr ();
1407 Now set all exceptions to non-stop
1408 unsigned int mask_cr
1409 = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
1410 unsigned int masked_cr;
1411 masked_cr = fenv_cr & mask_cr;
1413 And clear all exception flags
1414 unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
1415 unsigned int masked_cr;
1416 masked_sr = fenv_sr & mask_sr;
1418 __builtin_aarch64_set_cr (masked_cr);
1419 __builtin_aarch64_set_sr (masked_sr); */
1421 fenv_cr
= create_tmp_var (unsigned_type_node
);
1422 fenv_sr
= create_tmp_var (unsigned_type_node
);
1424 get_fpcr
= aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR
];
1425 set_fpcr
= aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR
];
1426 get_fpsr
= aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR
];
1427 set_fpsr
= aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR
];
1429 mask_cr
= build_int_cst (unsigned_type_node
,
1430 ~(AARCH64_FE_ALL_EXCEPT
<< AARCH64_FE_EXCEPT_SHIFT
));
1431 mask_sr
= build_int_cst (unsigned_type_node
,
1432 ~(AARCH64_FE_ALL_EXCEPT
));
1434 ld_fenv_cr
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1435 fenv_cr
, build_call_expr (get_fpcr
, 0));
1436 ld_fenv_sr
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1437 fenv_sr
, build_call_expr (get_fpsr
, 0));
1439 masked_fenv_cr
= build2 (BIT_AND_EXPR
, unsigned_type_node
, fenv_cr
, mask_cr
);
1440 masked_fenv_sr
= build2 (BIT_AND_EXPR
, unsigned_type_node
, fenv_sr
, mask_sr
);
1442 hold_fnclex_cr
= build_call_expr (set_fpcr
, 1, masked_fenv_cr
);
1443 hold_fnclex_sr
= build_call_expr (set_fpsr
, 1, masked_fenv_sr
);
1445 hold_fnclex
= build2 (COMPOUND_EXPR
, void_type_node
, hold_fnclex_cr
,
1447 masked_fenv
= build2 (COMPOUND_EXPR
, void_type_node
, masked_fenv_cr
,
1449 ld_fenv
= build2 (COMPOUND_EXPR
, void_type_node
, ld_fenv_cr
, ld_fenv_sr
);
1451 *hold
= build2 (COMPOUND_EXPR
, void_type_node
,
1452 build2 (COMPOUND_EXPR
, void_type_node
, masked_fenv
, ld_fenv
),
1455 /* Store the value of masked_fenv to clear the exceptions:
1456 __builtin_aarch64_set_fpsr (masked_fenv_sr); */
1458 *clear
= build_call_expr (set_fpsr
, 1, masked_fenv_sr
);
1460 /* Generate the equivalent of :
1461 unsigned int new_fenv_var;
1462 new_fenv_var = __builtin_aarch64_get_fpsr ();
1464 __builtin_aarch64_set_fpsr (fenv_sr);
1466 __atomic_feraiseexcept (new_fenv_var); */
1468 new_fenv_var
= create_tmp_var (unsigned_type_node
);
1469 reload_fenv
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1470 new_fenv_var
, build_call_expr (get_fpsr
, 0));
1471 restore_fnenv
= build_call_expr (set_fpsr
, 1, fenv_sr
);
1472 atomic_feraiseexcept
= builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT
);
1473 update_call
= build_call_expr (atomic_feraiseexcept
, 1,
1474 fold_convert (integer_type_node
, new_fenv_var
));
1475 *update
= build2 (COMPOUND_EXPR
, void_type_node
,
1476 build2 (COMPOUND_EXPR
, void_type_node
,
1477 reload_fenv
, restore_fnenv
), update_call
);
1481 #undef AARCH64_CHECK_BUILTIN_MODE
1482 #undef AARCH64_FIND_FRINT_VARIANT
1501 #include "gt-aarch64-builtins.h"