1 /* Builtins' description for AArch64 SIMD architecture.
2 Copyright (C) 2011-2014 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 "stor-layout.h"
28 #include "stringpool.h"
33 #include "langhooks.h"
34 #include "diagnostic-core.h"
36 #include "pointer-set.h"
37 #include "hash-table.h"
40 #include "basic-block.h"
41 #include "tree-ssa-alias.h"
42 #include "internal-fn.h"
43 #include "gimple-fold.h"
45 #include "gimple-expr.h"
48 #include "gimple-iterator.h"
50 #define v8qi_UP V8QImode
51 #define v4hi_UP V4HImode
52 #define v2si_UP V2SImode
53 #define v2sf_UP V2SFmode
54 #define v1df_UP V1DFmode
57 #define v16qi_UP V16QImode
58 #define v8hi_UP V8HImode
59 #define v4si_UP V4SImode
60 #define v4sf_UP V4SFmode
61 #define v2di_UP V2DImode
62 #define v2df_UP V2DFmode
74 #define SIMD_MAX_BUILTIN_ARGS 5
76 enum aarch64_type_qualifiers
81 qualifier_unsigned
= 0x1, /* 1 << 0 */
83 qualifier_const
= 0x2, /* 1 << 1 */
85 qualifier_pointer
= 0x4, /* 1 << 2 */
87 qualifier_const_pointer
= 0x6, /* qualifier_const | qualifier_pointer */
88 /* Used when expanding arguments if an operand could
90 qualifier_immediate
= 0x8, /* 1 << 3 */
91 qualifier_maybe_immediate
= 0x10, /* 1 << 4 */
93 qualifier_void
= 0x20, /* 1 << 5 */
94 /* Some patterns may have internal operands, this qualifier is an
95 instruction to the initialisation code to skip this operand. */
96 qualifier_internal
= 0x40, /* 1 << 6 */
97 /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
98 rather than using the type of the operand. */
99 qualifier_map_mode
= 0x80, /* 1 << 7 */
100 /* qualifier_pointer | qualifier_map_mode */
101 qualifier_pointer_map_mode
= 0x84,
102 /* qualifier_const_pointer | qualifier_map_mode */
103 qualifier_const_pointer_map_mode
= 0x86,
104 /* Polynomial types. */
105 qualifier_poly
= 0x100
111 enum machine_mode mode
;
112 const enum insn_code code
;
114 enum aarch64_type_qualifiers
*qualifiers
;
115 } aarch64_simd_builtin_datum
;
117 /* The qualifier_internal allows generation of a unary builtin from
118 a pattern with a third pseudo-operand such as a match_scratch. */
119 static enum aarch64_type_qualifiers
120 aarch64_types_unop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
121 = { qualifier_none
, qualifier_none
, qualifier_internal
};
122 #define TYPES_UNOP (aarch64_types_unop_qualifiers)
123 static enum aarch64_type_qualifiers
124 aarch64_types_unopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
125 = { qualifier_unsigned
, qualifier_unsigned
};
126 #define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
127 #define TYPES_CREATE (aarch64_types_unop_qualifiers)
128 #define TYPES_REINTERP_SS (aarch64_types_unop_qualifiers)
129 static enum aarch64_type_qualifiers
130 aarch64_types_unop_su_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
131 = { qualifier_none
, qualifier_unsigned
};
132 #define TYPES_REINTERP_SU (aarch64_types_unop_su_qualifiers)
133 static enum aarch64_type_qualifiers
134 aarch64_types_unop_sp_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
135 = { qualifier_none
, qualifier_poly
};
136 #define TYPES_REINTERP_SP (aarch64_types_unop_sp_qualifiers)
137 static enum aarch64_type_qualifiers
138 aarch64_types_unop_us_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
139 = { qualifier_unsigned
, qualifier_none
};
140 #define TYPES_REINTERP_US (aarch64_types_unop_us_qualifiers)
141 static enum aarch64_type_qualifiers
142 aarch64_types_unop_ps_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
143 = { qualifier_poly
, qualifier_none
};
144 #define TYPES_REINTERP_PS (aarch64_types_unop_ps_qualifiers)
145 static enum aarch64_type_qualifiers
146 aarch64_types_binop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
147 = { qualifier_none
, qualifier_none
, qualifier_maybe_immediate
};
148 #define TYPES_BINOP (aarch64_types_binop_qualifiers)
149 static enum aarch64_type_qualifiers
150 aarch64_types_binopv_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
151 = { qualifier_void
, qualifier_none
, qualifier_none
};
152 #define TYPES_BINOPV (aarch64_types_binopv_qualifiers)
153 static enum aarch64_type_qualifiers
154 aarch64_types_binopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
155 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
};
156 #define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
157 static enum aarch64_type_qualifiers
158 aarch64_types_binop_uus_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
159 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_none
};
160 #define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
161 static enum aarch64_type_qualifiers
162 aarch64_types_binop_ssu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
163 = { qualifier_none
, qualifier_none
, qualifier_unsigned
};
164 #define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
165 static enum aarch64_type_qualifiers
166 aarch64_types_binopp_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
167 = { qualifier_poly
, qualifier_poly
, qualifier_poly
};
168 #define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
170 static enum aarch64_type_qualifiers
171 aarch64_types_ternop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
172 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_none
};
173 #define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
174 static enum aarch64_type_qualifiers
175 aarch64_types_ternopu_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
176 = { qualifier_unsigned
, qualifier_unsigned
,
177 qualifier_unsigned
, qualifier_unsigned
};
178 #define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
180 static enum aarch64_type_qualifiers
181 aarch64_types_quadop_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
182 = { qualifier_none
, qualifier_none
, qualifier_none
,
183 qualifier_none
, qualifier_none
};
184 #define TYPES_QUADOP (aarch64_types_quadop_qualifiers)
186 static enum aarch64_type_qualifiers
187 aarch64_types_getlane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
188 = { qualifier_none
, qualifier_none
, qualifier_immediate
};
189 #define TYPES_GETLANE (aarch64_types_getlane_qualifiers)
190 #define TYPES_SHIFTIMM (aarch64_types_getlane_qualifiers)
191 static enum aarch64_type_qualifiers
192 aarch64_types_shift_to_unsigned_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
193 = { qualifier_unsigned
, qualifier_none
, qualifier_immediate
};
194 #define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
195 static enum aarch64_type_qualifiers
196 aarch64_types_unsigned_shift_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
197 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_immediate
};
198 #define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
200 static enum aarch64_type_qualifiers
201 aarch64_types_setlane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
202 = { qualifier_none
, qualifier_none
, qualifier_none
, qualifier_immediate
};
203 #define TYPES_SETLANE (aarch64_types_setlane_qualifiers)
204 #define TYPES_SHIFTINSERT (aarch64_types_setlane_qualifiers)
205 #define TYPES_SHIFTACC (aarch64_types_setlane_qualifiers)
207 static enum aarch64_type_qualifiers
208 aarch64_types_unsigned_shiftacc_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
209 = { qualifier_unsigned
, qualifier_unsigned
, qualifier_unsigned
,
210 qualifier_immediate
};
211 #define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
214 static enum aarch64_type_qualifiers
215 aarch64_types_combine_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
216 = { qualifier_none
, qualifier_none
, qualifier_none
};
217 #define TYPES_COMBINE (aarch64_types_combine_qualifiers)
219 static enum aarch64_type_qualifiers
220 aarch64_types_load1_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
221 = { qualifier_none
, qualifier_const_pointer_map_mode
};
222 #define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
223 #define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
225 static enum aarch64_type_qualifiers
226 aarch64_types_bsl_p_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
227 = { qualifier_poly
, qualifier_unsigned
,
228 qualifier_poly
, qualifier_poly
};
229 #define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
230 static enum aarch64_type_qualifiers
231 aarch64_types_bsl_s_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
232 = { qualifier_none
, qualifier_unsigned
,
233 qualifier_none
, qualifier_none
};
234 #define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
235 static enum aarch64_type_qualifiers
236 aarch64_types_bsl_u_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
237 = { qualifier_unsigned
, qualifier_unsigned
,
238 qualifier_unsigned
, qualifier_unsigned
};
239 #define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
241 /* The first argument (return type) of a store should be void type,
242 which we represent with qualifier_void. Their first operand will be
243 a DImode pointer to the location to store to, so we must use
244 qualifier_map_mode | qualifier_pointer to build a pointer to the
245 element type of the vector. */
246 static enum aarch64_type_qualifiers
247 aarch64_types_store1_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
248 = { qualifier_void
, qualifier_pointer_map_mode
, qualifier_none
};
249 #define TYPES_STORE1 (aarch64_types_store1_qualifiers)
250 #define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
251 static enum aarch64_type_qualifiers
252 aarch64_types_storestruct_lane_qualifiers
[SIMD_MAX_BUILTIN_ARGS
]
253 = { qualifier_void
, qualifier_pointer_map_mode
,
254 qualifier_none
, qualifier_none
};
255 #define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
257 #define CF0(N, X) CODE_FOR_aarch64_##N##X
258 #define CF1(N, X) CODE_FOR_##N##X##1
259 #define CF2(N, X) CODE_FOR_##N##X##2
260 #define CF3(N, X) CODE_FOR_##N##X##3
261 #define CF4(N, X) CODE_FOR_##N##X##4
262 #define CF10(N, X) CODE_FOR_##N##X
264 #define VAR1(T, N, MAP, A) \
265 {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T},
266 #define VAR2(T, N, MAP, A, B) \
267 VAR1 (T, N, MAP, A) \
269 #define VAR3(T, N, MAP, A, B, C) \
270 VAR2 (T, N, MAP, A, B) \
272 #define VAR4(T, N, MAP, A, B, C, D) \
273 VAR3 (T, N, MAP, A, B, C) \
275 #define VAR5(T, N, MAP, A, B, C, D, E) \
276 VAR4 (T, N, MAP, A, B, C, D) \
278 #define VAR6(T, N, MAP, A, B, C, D, E, F) \
279 VAR5 (T, N, MAP, A, B, C, D, E) \
281 #define VAR7(T, N, MAP, A, B, C, D, E, F, G) \
282 VAR6 (T, N, MAP, A, B, C, D, E, F) \
284 #define VAR8(T, N, MAP, A, B, C, D, E, F, G, H) \
285 VAR7 (T, N, MAP, A, B, C, D, E, F, G) \
287 #define VAR9(T, N, MAP, A, B, C, D, E, F, G, H, I) \
288 VAR8 (T, N, MAP, A, B, C, D, E, F, G, H) \
290 #define VAR10(T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
291 VAR9 (T, N, MAP, A, B, C, D, E, F, G, H, I) \
293 #define VAR11(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
294 VAR10 (T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
296 #define VAR12(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L) \
297 VAR11 (T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
300 /* BUILTIN_<ITERATOR> macros should expand to cover the same range of
301 modes as is given for each define_mode_iterator in
302 config/aarch64/iterators.md. */
304 #define BUILTIN_DX(T, N, MAP) \
305 VAR2 (T, N, MAP, di, df)
306 #define BUILTIN_GPF(T, N, MAP) \
307 VAR2 (T, N, MAP, sf, df)
308 #define BUILTIN_SDQ_I(T, N, MAP) \
309 VAR4 (T, N, MAP, qi, hi, si, di)
310 #define BUILTIN_SD_HSI(T, N, MAP) \
311 VAR2 (T, N, MAP, hi, si)
312 #define BUILTIN_V2F(T, N, MAP) \
313 VAR2 (T, N, MAP, v2sf, v2df)
314 #define BUILTIN_VALL(T, N, MAP) \
315 VAR10 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, \
316 v4si, v2di, v2sf, v4sf, v2df)
317 #define BUILTIN_VALLDI(T, N, MAP) \
318 VAR11 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, \
319 v4si, v2di, v2sf, v4sf, v2df, di)
320 #define BUILTIN_VALLDIF(T, N, MAP) \
321 VAR12 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, \
322 v4si, v2di, v2sf, v4sf, v2df, di, df)
323 #define BUILTIN_VB(T, N, MAP) \
324 VAR2 (T, N, MAP, v8qi, v16qi)
325 #define BUILTIN_VD(T, N, MAP) \
326 VAR4 (T, N, MAP, v8qi, v4hi, v2si, v2sf)
327 #define BUILTIN_VD1(T, N, MAP) \
328 VAR5 (T, N, MAP, v8qi, v4hi, v2si, v2sf, v1df)
329 #define BUILTIN_VDC(T, N, MAP) \
330 VAR6 (T, N, MAP, v8qi, v4hi, v2si, v2sf, di, df)
331 #define BUILTIN_VDIC(T, N, MAP) \
332 VAR3 (T, N, MAP, v8qi, v4hi, v2si)
333 #define BUILTIN_VDN(T, N, MAP) \
334 VAR3 (T, N, MAP, v4hi, v2si, di)
335 #define BUILTIN_VDQ(T, N, MAP) \
336 VAR7 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di)
337 #define BUILTIN_VDQF(T, N, MAP) \
338 VAR3 (T, N, MAP, v2sf, v4sf, v2df)
339 #define BUILTIN_VDQF_DF(T, N, MAP) \
340 VAR4 (T, N, MAP, v2sf, v4sf, v2df, df)
341 #define BUILTIN_VDQH(T, N, MAP) \
342 VAR2 (T, N, MAP, v4hi, v8hi)
343 #define BUILTIN_VDQHS(T, N, MAP) \
344 VAR4 (T, N, MAP, v4hi, v8hi, v2si, v4si)
345 #define BUILTIN_VDQIF(T, N, MAP) \
346 VAR9 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2sf, v4sf, v2df)
347 #define BUILTIN_VDQM(T, N, MAP) \
348 VAR6 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si)
349 #define BUILTIN_VDQV(T, N, MAP) \
350 VAR5 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v4si)
351 #define BUILTIN_VDQQH(T, N, MAP) \
352 VAR4 (T, N, MAP, v8qi, v16qi, v4hi, v8hi)
353 #define BUILTIN_VDQ_BHSI(T, N, MAP) \
354 VAR6 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si)
355 #define BUILTIN_VDQ_I(T, N, MAP) \
356 VAR7 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di)
357 #define BUILTIN_VDW(T, N, MAP) \
358 VAR3 (T, N, MAP, v8qi, v4hi, v2si)
359 #define BUILTIN_VD_BHSI(T, N, MAP) \
360 VAR3 (T, N, MAP, v8qi, v4hi, v2si)
361 #define BUILTIN_VD_HSI(T, N, MAP) \
362 VAR2 (T, N, MAP, v4hi, v2si)
363 #define BUILTIN_VQ(T, N, MAP) \
364 VAR6 (T, N, MAP, v16qi, v8hi, v4si, v2di, v4sf, v2df)
365 #define BUILTIN_VQN(T, N, MAP) \
366 VAR3 (T, N, MAP, v8hi, v4si, v2di)
367 #define BUILTIN_VQW(T, N, MAP) \
368 VAR3 (T, N, MAP, v16qi, v8hi, v4si)
369 #define BUILTIN_VQ_HSI(T, N, MAP) \
370 VAR2 (T, N, MAP, v8hi, v4si)
371 #define BUILTIN_VQ_S(T, N, MAP) \
372 VAR6 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si)
373 #define BUILTIN_VSDQ_HSI(T, N, MAP) \
374 VAR6 (T, N, MAP, v4hi, v8hi, v2si, v4si, hi, si)
375 #define BUILTIN_VSDQ_I(T, N, MAP) \
376 VAR11 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, qi, hi, si, di)
377 #define BUILTIN_VSDQ_I_BHSI(T, N, MAP) \
378 VAR10 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, qi, hi, si)
379 #define BUILTIN_VSDQ_I_DI(T, N, MAP) \
380 VAR8 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, di)
381 #define BUILTIN_VSD_HSI(T, N, MAP) \
382 VAR4 (T, N, MAP, v4hi, v2si, hi, si)
383 #define BUILTIN_VSQN_HSDI(T, N, MAP) \
384 VAR6 (T, N, MAP, v8hi, v4si, v2di, hi, si, di)
385 #define BUILTIN_VSTRUCT(T, N, MAP) \
386 VAR3 (T, N, MAP, oi, ci, xi)
388 static aarch64_simd_builtin_datum aarch64_simd_builtin_data
[] = {
389 #include "aarch64-simd-builtins.def"
392 /* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
393 #define AARCH64_CRC32_BUILTINS \
394 CRC32_BUILTIN (crc32b, QI) \
395 CRC32_BUILTIN (crc32h, HI) \
396 CRC32_BUILTIN (crc32w, SI) \
397 CRC32_BUILTIN (crc32x, DI) \
398 CRC32_BUILTIN (crc32cb, QI) \
399 CRC32_BUILTIN (crc32ch, HI) \
400 CRC32_BUILTIN (crc32cw, SI) \
401 CRC32_BUILTIN (crc32cx, DI)
406 enum machine_mode mode
;
407 const enum insn_code icode
;
409 } aarch64_crc_builtin_datum
;
411 #define CRC32_BUILTIN(N, M) \
415 #define VAR1(T, N, MAP, A) \
416 AARCH64_SIMD_BUILTIN_##T##_##N##A,
418 enum aarch64_builtins
422 AARCH64_BUILTIN_GET_FPCR
,
423 AARCH64_BUILTIN_SET_FPCR
,
424 AARCH64_BUILTIN_GET_FPSR
,
425 AARCH64_BUILTIN_SET_FPSR
,
427 AARCH64_SIMD_BUILTIN_BASE
,
428 #include "aarch64-simd-builtins.def"
429 AARCH64_SIMD_BUILTIN_MAX
= AARCH64_SIMD_BUILTIN_BASE
430 + ARRAY_SIZE (aarch64_simd_builtin_data
),
431 AARCH64_CRC32_BUILTIN_BASE
,
432 AARCH64_CRC32_BUILTINS
433 AARCH64_CRC32_BUILTIN_MAX
,
438 #define CRC32_BUILTIN(N, M) \
439 {"__builtin_aarch64_"#N, M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
441 static aarch64_crc_builtin_datum aarch64_crc_builtin_data
[] = {
442 AARCH64_CRC32_BUILTINS
447 static GTY(()) tree aarch64_builtin_decls
[AARCH64_BUILTIN_MAX
];
449 #define NUM_DREG_TYPES 6
450 #define NUM_QREG_TYPES 6
452 /* Return a tree for a signed or unsigned argument of either
453 the mode specified by MODE, or the inner mode of MODE. */
455 aarch64_build_scalar_type (enum machine_mode mode
,
461 AARCH64_TYPE_BUILDER (QI) \
462 AARCH64_TYPE_BUILDER (HI) \
463 AARCH64_TYPE_BUILDER (SI) \
464 AARCH64_TYPE_BUILDER (DI) \
465 AARCH64_TYPE_BUILDER (EI) \
466 AARCH64_TYPE_BUILDER (OI) \
467 AARCH64_TYPE_BUILDER (CI) \
468 AARCH64_TYPE_BUILDER (XI) \
469 AARCH64_TYPE_BUILDER (TI) \
471 /* Statically declare all the possible types we might need. */
472 #undef AARCH64_TYPE_BUILDER
473 #define AARCH64_TYPE_BUILDER(X) \
474 static tree X##_aarch64_type_node_p = NULL; \
475 static tree X##_aarch64_type_node_s = NULL; \
476 static tree X##_aarch64_type_node_u = NULL;
480 static tree float_aarch64_type_node
= NULL
;
481 static tree double_aarch64_type_node
= NULL
;
483 gcc_assert (!VECTOR_MODE_P (mode
));
485 /* If we've already initialised this type, don't initialise it again,
486 otherwise ask for a new type of the correct size. */
487 #undef AARCH64_TYPE_BUILDER
488 #define AARCH64_TYPE_BUILDER(X) \
491 return (X##_aarch64_type_node_u \
492 ? X##_aarch64_type_node_u \
493 : X##_aarch64_type_node_u \
494 = make_unsigned_type (GET_MODE_PRECISION (mode))); \
496 return (X##_aarch64_type_node_p \
497 ? X##_aarch64_type_node_p \
498 : X##_aarch64_type_node_p \
499 = make_unsigned_type (GET_MODE_PRECISION (mode))); \
501 return (X##_aarch64_type_node_s \
502 ? X##_aarch64_type_node_s \
503 : X##_aarch64_type_node_s \
504 = make_signed_type (GET_MODE_PRECISION (mode))); \
511 if (!float_aarch64_type_node
)
513 float_aarch64_type_node
= make_node (REAL_TYPE
);
514 TYPE_PRECISION (float_aarch64_type_node
) = FLOAT_TYPE_SIZE
;
515 layout_type (float_aarch64_type_node
);
517 return float_aarch64_type_node
;
520 if (!double_aarch64_type_node
)
522 double_aarch64_type_node
= make_node (REAL_TYPE
);
523 TYPE_PRECISION (double_aarch64_type_node
) = DOUBLE_TYPE_SIZE
;
524 layout_type (double_aarch64_type_node
);
526 return double_aarch64_type_node
;
534 aarch64_build_vector_type (enum machine_mode mode
,
540 #define VECTOR_TYPES \
541 AARCH64_TYPE_BUILDER (V16QI) \
542 AARCH64_TYPE_BUILDER (V8HI) \
543 AARCH64_TYPE_BUILDER (V4SI) \
544 AARCH64_TYPE_BUILDER (V2DI) \
545 AARCH64_TYPE_BUILDER (V8QI) \
546 AARCH64_TYPE_BUILDER (V4HI) \
547 AARCH64_TYPE_BUILDER (V2SI) \
549 AARCH64_TYPE_BUILDER (V4SF) \
550 AARCH64_TYPE_BUILDER (V2DF) \
551 AARCH64_TYPE_BUILDER (V2SF) \
552 /* Declare our "cache" of values. */
553 #undef AARCH64_TYPE_BUILDER
554 #define AARCH64_TYPE_BUILDER(X) \
555 static tree X##_aarch64_type_node_s = NULL; \
556 static tree X##_aarch64_type_node_u = NULL; \
557 static tree X##_aarch64_type_node_p = NULL;
561 gcc_assert (VECTOR_MODE_P (mode
));
563 #undef AARCH64_TYPE_BUILDER
564 #define AARCH64_TYPE_BUILDER(X) \
567 return X##_aarch64_type_node_u \
568 ? X##_aarch64_type_node_u \
569 : X##_aarch64_type_node_u \
570 = build_vector_type_for_mode (aarch64_build_scalar_type \
571 (GET_MODE_INNER (mode), \
572 unsigned_p, poly_p), mode); \
574 return X##_aarch64_type_node_p \
575 ? X##_aarch64_type_node_p \
576 : X##_aarch64_type_node_p \
577 = build_vector_type_for_mode (aarch64_build_scalar_type \
578 (GET_MODE_INNER (mode), \
579 unsigned_p, poly_p), mode); \
581 return X##_aarch64_type_node_s \
582 ? X##_aarch64_type_node_s \
583 : X##_aarch64_type_node_s \
584 = build_vector_type_for_mode (aarch64_build_scalar_type \
585 (GET_MODE_INNER (mode), \
586 unsigned_p, poly_p), mode); \
592 eltype
= aarch64_build_scalar_type (GET_MODE_INNER (mode
),
594 return build_vector_type_for_mode (eltype
, mode
);
601 aarch64_build_type (enum machine_mode mode
, bool unsigned_p
, bool poly_p
)
603 if (VECTOR_MODE_P (mode
))
604 return aarch64_build_vector_type (mode
, unsigned_p
, poly_p
);
606 return aarch64_build_scalar_type (mode
, unsigned_p
, poly_p
);
610 aarch64_build_signed_type (enum machine_mode mode
)
612 return aarch64_build_type (mode
, false, false);
616 aarch64_build_unsigned_type (enum machine_mode mode
)
618 return aarch64_build_type (mode
, true, false);
622 aarch64_build_poly_type (enum machine_mode mode
)
624 return aarch64_build_type (mode
, false, true);
628 aarch64_init_simd_builtins (void)
630 unsigned int i
, fcode
= AARCH64_SIMD_BUILTIN_BASE
+ 1;
632 /* Signed scalar type nodes. */
633 tree aarch64_simd_intQI_type_node
= aarch64_build_signed_type (QImode
);
634 tree aarch64_simd_intHI_type_node
= aarch64_build_signed_type (HImode
);
635 tree aarch64_simd_intSI_type_node
= aarch64_build_signed_type (SImode
);
636 tree aarch64_simd_intDI_type_node
= aarch64_build_signed_type (DImode
);
637 tree aarch64_simd_intTI_type_node
= aarch64_build_signed_type (TImode
);
638 tree aarch64_simd_intEI_type_node
= aarch64_build_signed_type (EImode
);
639 tree aarch64_simd_intOI_type_node
= aarch64_build_signed_type (OImode
);
640 tree aarch64_simd_intCI_type_node
= aarch64_build_signed_type (CImode
);
641 tree aarch64_simd_intXI_type_node
= aarch64_build_signed_type (XImode
);
643 /* Unsigned scalar type nodes. */
644 tree aarch64_simd_intUQI_type_node
= aarch64_build_unsigned_type (QImode
);
645 tree aarch64_simd_intUHI_type_node
= aarch64_build_unsigned_type (HImode
);
646 tree aarch64_simd_intUSI_type_node
= aarch64_build_unsigned_type (SImode
);
647 tree aarch64_simd_intUDI_type_node
= aarch64_build_unsigned_type (DImode
);
649 /* Poly scalar type nodes. */
650 tree aarch64_simd_polyQI_type_node
= aarch64_build_poly_type (QImode
);
651 tree aarch64_simd_polyHI_type_node
= aarch64_build_poly_type (HImode
);
652 tree aarch64_simd_polyDI_type_node
= aarch64_build_poly_type (DImode
);
653 tree aarch64_simd_polyTI_type_node
= aarch64_build_poly_type (TImode
);
655 /* Float type nodes. */
656 tree aarch64_simd_float_type_node
= aarch64_build_signed_type (SFmode
);
657 tree aarch64_simd_double_type_node
= aarch64_build_signed_type (DFmode
);
659 /* Define typedefs which exactly correspond to the modes we are basing vector
660 types on. If you change these names you'll need to change
661 the table used by aarch64_mangle_type too. */
662 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intQI_type_node
,
663 "__builtin_aarch64_simd_qi");
664 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intHI_type_node
,
665 "__builtin_aarch64_simd_hi");
666 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intSI_type_node
,
667 "__builtin_aarch64_simd_si");
668 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_float_type_node
,
669 "__builtin_aarch64_simd_sf");
670 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intDI_type_node
,
671 "__builtin_aarch64_simd_di");
672 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_double_type_node
,
673 "__builtin_aarch64_simd_df");
674 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_polyQI_type_node
,
675 "__builtin_aarch64_simd_poly8");
676 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_polyHI_type_node
,
677 "__builtin_aarch64_simd_poly16");
678 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_polyDI_type_node
,
679 "__builtin_aarch64_simd_poly64");
680 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_polyTI_type_node
,
681 "__builtin_aarch64_simd_poly128");
682 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intTI_type_node
,
683 "__builtin_aarch64_simd_ti");
684 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intEI_type_node
,
685 "__builtin_aarch64_simd_ei");
686 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intOI_type_node
,
687 "__builtin_aarch64_simd_oi");
688 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intCI_type_node
,
689 "__builtin_aarch64_simd_ci");
690 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intXI_type_node
,
691 "__builtin_aarch64_simd_xi");
693 /* Unsigned integer types for various mode sizes. */
694 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intUQI_type_node
,
695 "__builtin_aarch64_simd_uqi");
696 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intUHI_type_node
,
697 "__builtin_aarch64_simd_uhi");
698 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intUSI_type_node
,
699 "__builtin_aarch64_simd_usi");
700 (*lang_hooks
.types
.register_builtin_type
) (aarch64_simd_intUDI_type_node
,
701 "__builtin_aarch64_simd_udi");
703 for (i
= 0; i
< ARRAY_SIZE (aarch64_simd_builtin_data
); i
++, fcode
++)
705 bool print_type_signature_p
= false;
706 char type_signature
[SIMD_MAX_BUILTIN_ARGS
] = { 0 };
707 aarch64_simd_builtin_datum
*d
= &aarch64_simd_builtin_data
[i
];
714 /* We must track two variables here. op_num is
715 the operand number as in the RTL pattern. This is
716 required to access the mode (e.g. V4SF mode) of the
717 argument, from which the base type can be derived.
718 arg_num is an index in to the qualifiers data, which
719 gives qualifiers to the type (e.g. const unsigned).
720 The reason these two variables may differ by one is the
721 void return type. While all return types take the 0th entry
722 in the qualifiers array, there is no operand for them in the
724 int op_num
= insn_data
[d
->code
].n_operands
- 1;
725 int arg_num
= d
->qualifiers
[0] & qualifier_void
728 tree return_type
= void_type_node
, args
= void_list_node
;
731 /* Build a function type directly from the insn_data for this
732 builtin. The build_function_type () function takes care of
733 removing duplicates for us. */
734 for (; op_num
>= 0; arg_num
--, op_num
--)
736 enum machine_mode op_mode
= insn_data
[d
->code
].operand
[op_num
].mode
;
737 enum aarch64_type_qualifiers qualifiers
= d
->qualifiers
[arg_num
];
739 if (qualifiers
& qualifier_unsigned
)
741 type_signature
[arg_num
] = 'u';
742 print_type_signature_p
= true;
744 else if (qualifiers
& qualifier_poly
)
746 type_signature
[arg_num
] = 'p';
747 print_type_signature_p
= true;
750 type_signature
[arg_num
] = 's';
752 /* Skip an internal operand for vget_{low, high}. */
753 if (qualifiers
& qualifier_internal
)
756 /* Some builtins have different user-facing types
757 for certain arguments, encoded in d->mode. */
758 if (qualifiers
& qualifier_map_mode
)
761 /* For pointers, we want a pointer to the basic type
763 if (qualifiers
& qualifier_pointer
&& VECTOR_MODE_P (op_mode
))
764 op_mode
= GET_MODE_INNER (op_mode
);
766 eltype
= aarch64_build_type (op_mode
,
767 qualifiers
& qualifier_unsigned
,
768 qualifiers
& qualifier_poly
);
770 /* Add qualifiers. */
771 if (qualifiers
& qualifier_const
)
772 eltype
= build_qualified_type (eltype
, TYPE_QUAL_CONST
);
774 if (qualifiers
& qualifier_pointer
)
775 eltype
= build_pointer_type (eltype
);
777 /* If we have reached arg_num == 0, we are at a non-void
778 return type. Otherwise, we are still processing
781 return_type
= eltype
;
783 args
= tree_cons (NULL_TREE
, eltype
, args
);
786 ftype
= build_function_type (return_type
, args
);
788 gcc_assert (ftype
!= NULL
);
790 if (print_type_signature_p
)
791 snprintf (namebuf
, sizeof (namebuf
), "__builtin_aarch64_%s_%s",
792 d
->name
, type_signature
);
794 snprintf (namebuf
, sizeof (namebuf
), "__builtin_aarch64_%s",
797 fndecl
= add_builtin_function (namebuf
, ftype
, fcode
, BUILT_IN_MD
,
799 aarch64_builtin_decls
[fcode
] = fndecl
;
804 aarch64_init_crc32_builtins ()
806 tree usi_type
= aarch64_build_unsigned_type (SImode
);
809 for (i
= 0; i
< ARRAY_SIZE (aarch64_crc_builtin_data
); ++i
)
811 aarch64_crc_builtin_datum
* d
= &aarch64_crc_builtin_data
[i
];
812 tree argtype
= aarch64_build_unsigned_type (d
->mode
);
813 tree ftype
= build_function_type_list (usi_type
, usi_type
, argtype
, NULL_TREE
);
814 tree fndecl
= add_builtin_function (d
->name
, ftype
, d
->fcode
,
815 BUILT_IN_MD
, NULL
, NULL_TREE
);
817 aarch64_builtin_decls
[d
->fcode
] = fndecl
;
822 aarch64_init_builtins (void)
825 = build_function_type_list (void_type_node
, unsigned_type_node
, NULL
);
827 = build_function_type_list (unsigned_type_node
, NULL
);
829 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR
]
830 = add_builtin_function ("__builtin_aarch64_get_fpcr", ftype_get_fpr
,
831 AARCH64_BUILTIN_GET_FPCR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
832 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR
]
833 = add_builtin_function ("__builtin_aarch64_set_fpcr", ftype_set_fpr
,
834 AARCH64_BUILTIN_SET_FPCR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
835 aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR
]
836 = add_builtin_function ("__builtin_aarch64_get_fpsr", ftype_get_fpr
,
837 AARCH64_BUILTIN_GET_FPSR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
838 aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR
]
839 = add_builtin_function ("__builtin_aarch64_set_fpsr", ftype_set_fpr
,
840 AARCH64_BUILTIN_SET_FPSR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
843 aarch64_init_simd_builtins ();
845 aarch64_init_crc32_builtins ();
849 aarch64_builtin_decl (unsigned code
, bool initialize_p ATTRIBUTE_UNUSED
)
851 if (code
>= AARCH64_BUILTIN_MAX
)
852 return error_mark_node
;
854 return aarch64_builtin_decls
[code
];
859 SIMD_ARG_COPY_TO_REG
,
865 aarch64_simd_expand_args (rtx target
, int icode
, int have_retval
,
870 tree arg
[SIMD_MAX_BUILTIN_ARGS
];
871 rtx op
[SIMD_MAX_BUILTIN_ARGS
];
872 enum machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
873 enum machine_mode mode
[SIMD_MAX_BUILTIN_ARGS
];
878 || GET_MODE (target
) != tmode
879 || !(*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
)))
880 target
= gen_reg_rtx (tmode
);
886 builtin_simd_arg thisarg
= (builtin_simd_arg
) va_arg (ap
, int);
888 if (thisarg
== SIMD_ARG_STOP
)
892 arg
[argc
] = CALL_EXPR_ARG (exp
, argc
);
893 op
[argc
] = expand_normal (arg
[argc
]);
894 mode
[argc
] = insn_data
[icode
].operand
[argc
+ have_retval
].mode
;
898 case SIMD_ARG_COPY_TO_REG
:
899 if (POINTER_TYPE_P (TREE_TYPE (arg
[argc
])))
900 op
[argc
] = convert_memory_address (Pmode
, op
[argc
]);
901 /*gcc_assert (GET_MODE (op[argc]) == mode[argc]); */
902 if (!(*insn_data
[icode
].operand
[argc
+ have_retval
].predicate
)
903 (op
[argc
], mode
[argc
]))
904 op
[argc
] = copy_to_mode_reg (mode
[argc
], op
[argc
]);
907 case SIMD_ARG_CONSTANT
:
908 if (!(*insn_data
[icode
].operand
[argc
+ have_retval
].predicate
)
909 (op
[argc
], mode
[argc
]))
910 error_at (EXPR_LOCATION (exp
), "incompatible type for argument %d, "
911 "expected %<const int%>", argc
+ 1);
928 pat
= GEN_FCN (icode
) (target
, op
[0]);
932 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1]);
936 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2]);
940 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2], op
[3]);
944 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2], op
[3], op
[4]);
954 pat
= GEN_FCN (icode
) (op
[0]);
958 pat
= GEN_FCN (icode
) (op
[0], op
[1]);
962 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2]);
966 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3]);
970 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3], op
[4]);
985 /* Expand an AArch64 AdvSIMD builtin(intrinsic). */
987 aarch64_simd_expand_builtin (int fcode
, tree exp
, rtx target
)
989 aarch64_simd_builtin_datum
*d
=
990 &aarch64_simd_builtin_data
[fcode
- (AARCH64_SIMD_BUILTIN_BASE
+ 1)];
991 enum insn_code icode
= d
->code
;
992 builtin_simd_arg args
[SIMD_MAX_BUILTIN_ARGS
];
993 int num_args
= insn_data
[d
->code
].n_operands
;
997 is_void
= !!(d
->qualifiers
[0] & qualifier_void
);
1001 for (k
= 1; k
< num_args
; k
++)
1003 /* We have four arrays of data, each indexed in a different fashion.
1004 qualifiers - element 0 always describes the function return type.
1005 operands - element 0 is either the operand for return value (if
1006 the function has a non-void return type) or the operand for the
1008 expr_args - element 0 always holds the first argument.
1009 args - element 0 is always used for the return type. */
1010 int qualifiers_k
= k
;
1011 int operands_k
= k
- is_void
;
1012 int expr_args_k
= k
- 1;
1014 if (d
->qualifiers
[qualifiers_k
] & qualifier_immediate
)
1015 args
[k
] = SIMD_ARG_CONSTANT
;
1016 else if (d
->qualifiers
[qualifiers_k
] & qualifier_maybe_immediate
)
1019 = expand_normal (CALL_EXPR_ARG (exp
,
1021 /* Handle constants only if the predicate allows it. */
1022 bool op_const_int_p
=
1024 && (*insn_data
[icode
].operand
[operands_k
].predicate
)
1025 (arg
, insn_data
[icode
].operand
[operands_k
].mode
));
1026 args
[k
] = op_const_int_p
? SIMD_ARG_CONSTANT
: SIMD_ARG_COPY_TO_REG
;
1029 args
[k
] = SIMD_ARG_COPY_TO_REG
;
1032 args
[k
] = SIMD_ARG_STOP
;
1034 /* The interface to aarch64_simd_expand_args expects a 0 if
1035 the function is void, and a 1 if it is not. */
1036 return aarch64_simd_expand_args
1037 (target
, icode
, !is_void
, exp
,
1046 aarch64_crc32_expand_builtin (int fcode
, tree exp
, rtx target
)
1049 aarch64_crc_builtin_datum
*d
1050 = &aarch64_crc_builtin_data
[fcode
- (AARCH64_CRC32_BUILTIN_BASE
+ 1)];
1051 enum insn_code icode
= d
->icode
;
1052 tree arg0
= CALL_EXPR_ARG (exp
, 0);
1053 tree arg1
= CALL_EXPR_ARG (exp
, 1);
1054 rtx op0
= expand_normal (arg0
);
1055 rtx op1
= expand_normal (arg1
);
1056 enum machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
1057 enum machine_mode mode0
= insn_data
[icode
].operand
[1].mode
;
1058 enum machine_mode mode1
= insn_data
[icode
].operand
[2].mode
;
1061 || GET_MODE (target
) != tmode
1062 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
1063 target
= gen_reg_rtx (tmode
);
1065 gcc_assert ((GET_MODE (op0
) == mode0
|| GET_MODE (op0
) == VOIDmode
)
1066 && (GET_MODE (op1
) == mode1
|| GET_MODE (op1
) == VOIDmode
));
1068 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
1069 op0
= copy_to_mode_reg (mode0
, op0
);
1070 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
1071 op1
= copy_to_mode_reg (mode1
, op1
);
1073 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
1080 /* Expand an expression EXP that calls a built-in function,
1081 with result going to TARGET if that's convenient. */
1083 aarch64_expand_builtin (tree exp
,
1085 rtx subtarget ATTRIBUTE_UNUSED
,
1086 enum machine_mode mode ATTRIBUTE_UNUSED
,
1087 int ignore ATTRIBUTE_UNUSED
)
1089 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
1090 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1097 case AARCH64_BUILTIN_GET_FPCR
:
1098 case AARCH64_BUILTIN_SET_FPCR
:
1099 case AARCH64_BUILTIN_GET_FPSR
:
1100 case AARCH64_BUILTIN_SET_FPSR
:
1101 if ((fcode
== AARCH64_BUILTIN_GET_FPCR
)
1102 || (fcode
== AARCH64_BUILTIN_GET_FPSR
))
1104 icode
= (fcode
== AARCH64_BUILTIN_GET_FPSR
) ?
1105 CODE_FOR_get_fpsr
: CODE_FOR_get_fpcr
;
1106 target
= gen_reg_rtx (SImode
);
1107 pat
= GEN_FCN (icode
) (target
);
1112 icode
= (fcode
== AARCH64_BUILTIN_SET_FPSR
) ?
1113 CODE_FOR_set_fpsr
: CODE_FOR_set_fpcr
;
1114 arg0
= CALL_EXPR_ARG (exp
, 0);
1115 op0
= expand_normal (arg0
);
1116 pat
= GEN_FCN (icode
) (op0
);
1122 if (fcode
>= AARCH64_SIMD_BUILTIN_BASE
&& fcode
<= AARCH64_SIMD_BUILTIN_MAX
)
1123 return aarch64_simd_expand_builtin (fcode
, exp
, target
);
1124 else if (fcode
>= AARCH64_CRC32_BUILTIN_BASE
&& fcode
<= AARCH64_CRC32_BUILTIN_MAX
)
1125 return aarch64_crc32_expand_builtin (fcode
, exp
, target
);
1131 aarch64_builtin_vectorized_function (tree fndecl
, tree type_out
, tree type_in
)
1133 enum machine_mode in_mode
, out_mode
;
1136 if (TREE_CODE (type_out
) != VECTOR_TYPE
1137 || TREE_CODE (type_in
) != VECTOR_TYPE
)
1140 out_mode
= TYPE_MODE (TREE_TYPE (type_out
));
1141 out_n
= TYPE_VECTOR_SUBPARTS (type_out
);
1142 in_mode
= TYPE_MODE (TREE_TYPE (type_in
));
1143 in_n
= TYPE_VECTOR_SUBPARTS (type_in
);
1145 #undef AARCH64_CHECK_BUILTIN_MODE
1146 #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
1147 #define AARCH64_FIND_FRINT_VARIANT(N) \
1148 (AARCH64_CHECK_BUILTIN_MODE (2, D) \
1149 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
1150 : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
1151 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
1152 : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
1153 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
1155 if (DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
)
1157 enum built_in_function fn
= DECL_FUNCTION_CODE (fndecl
);
1160 #undef AARCH64_CHECK_BUILTIN_MODE
1161 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1162 (out_mode == N##Fmode && out_n == C \
1163 && in_mode == N##Fmode && in_n == C)
1164 case BUILT_IN_FLOOR
:
1165 case BUILT_IN_FLOORF
:
1166 return AARCH64_FIND_FRINT_VARIANT (floor
);
1168 case BUILT_IN_CEILF
:
1169 return AARCH64_FIND_FRINT_VARIANT (ceil
);
1170 case BUILT_IN_TRUNC
:
1171 case BUILT_IN_TRUNCF
:
1172 return AARCH64_FIND_FRINT_VARIANT (btrunc
);
1173 case BUILT_IN_ROUND
:
1174 case BUILT_IN_ROUNDF
:
1175 return AARCH64_FIND_FRINT_VARIANT (round
);
1176 case BUILT_IN_NEARBYINT
:
1177 case BUILT_IN_NEARBYINTF
:
1178 return AARCH64_FIND_FRINT_VARIANT (nearbyint
);
1180 case BUILT_IN_SQRTF
:
1181 return AARCH64_FIND_FRINT_VARIANT (sqrt
);
1182 #undef AARCH64_CHECK_BUILTIN_MODE
1183 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1184 (out_mode == SImode && out_n == C \
1185 && in_mode == N##Imode && in_n == C)
1188 if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1189 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOP_clzv4si
];
1192 #undef AARCH64_CHECK_BUILTIN_MODE
1193 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1194 (out_mode == N##Imode && out_n == C \
1195 && in_mode == N##Fmode && in_n == C)
1196 case BUILT_IN_LFLOOR
:
1197 case BUILT_IN_LFLOORF
:
1198 case BUILT_IN_LLFLOOR
:
1199 case BUILT_IN_IFLOORF
:
1201 enum aarch64_builtins builtin
;
1202 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1203 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di
;
1204 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1205 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si
;
1206 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1207 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si
;
1211 return aarch64_builtin_decls
[builtin
];
1213 case BUILT_IN_LCEIL
:
1214 case BUILT_IN_LCEILF
:
1215 case BUILT_IN_LLCEIL
:
1216 case BUILT_IN_ICEILF
:
1218 enum aarch64_builtins builtin
;
1219 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1220 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di
;
1221 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1222 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si
;
1223 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1224 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si
;
1228 return aarch64_builtin_decls
[builtin
];
1230 case BUILT_IN_LROUND
:
1231 case BUILT_IN_IROUNDF
:
1233 enum aarch64_builtins builtin
;
1234 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1235 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di
;
1236 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1237 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si
;
1238 else if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1239 builtin
= AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si
;
1243 return aarch64_builtin_decls
[builtin
];
1245 case BUILT_IN_BSWAP16
:
1246 #undef AARCH64_CHECK_BUILTIN_MODE
1247 #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1248 (out_mode == N##Imode && out_n == C \
1249 && in_mode == N##Imode && in_n == C)
1250 if (AARCH64_CHECK_BUILTIN_MODE (4, H
))
1251 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4hi
];
1252 else if (AARCH64_CHECK_BUILTIN_MODE (8, H
))
1253 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv8hi
];
1256 case BUILT_IN_BSWAP32
:
1257 if (AARCH64_CHECK_BUILTIN_MODE (2, S
))
1258 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2si
];
1259 else if (AARCH64_CHECK_BUILTIN_MODE (4, S
))
1260 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4si
];
1263 case BUILT_IN_BSWAP64
:
1264 if (AARCH64_CHECK_BUILTIN_MODE (2, D
))
1265 return aarch64_builtin_decls
[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2di
];
1277 #define VAR1(T, N, MAP, A) \
1278 case AARCH64_SIMD_BUILTIN_##T##_##N##A:
1281 aarch64_fold_builtin (tree fndecl
, int n_args ATTRIBUTE_UNUSED
, tree
*args
,
1282 bool ignore ATTRIBUTE_UNUSED
)
1284 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1285 tree type
= TREE_TYPE (TREE_TYPE (fndecl
));
1289 BUILTIN_VALLDI (UNOP
, abs
, 2)
1290 return fold_build1 (ABS_EXPR
, type
, args
[0]);
1292 BUILTIN_VALLDI (BINOP
, cmge
, 0)
1293 return fold_build2 (GE_EXPR
, type
, args
[0], args
[1]);
1295 BUILTIN_VALLDI (BINOP
, cmgt
, 0)
1296 return fold_build2 (GT_EXPR
, type
, args
[0], args
[1]);
1298 BUILTIN_VALLDI (BINOP
, cmeq
, 0)
1299 return fold_build2 (EQ_EXPR
, type
, args
[0], args
[1]);
1301 BUILTIN_VSDQ_I_DI (BINOP
, cmtst
, 0)
1303 tree and_node
= fold_build2 (BIT_AND_EXPR
, type
, args
[0], args
[1]);
1304 tree vec_zero_node
= build_zero_cst (type
);
1305 return fold_build2 (NE_EXPR
, type
, and_node
, vec_zero_node
);
1308 VAR1 (REINTERP_SS
, reinterpretdi
, 0, v1df
)
1309 VAR1 (REINTERP_SS
, reinterpretv8qi
, 0, v1df
)
1310 VAR1 (REINTERP_SS
, reinterpretv4hi
, 0, v1df
)
1311 VAR1 (REINTERP_SS
, reinterpretv2si
, 0, v1df
)
1312 VAR1 (REINTERP_SS
, reinterpretv2sf
, 0, v1df
)
1313 BUILTIN_VD (REINTERP_SS
, reinterpretv1df
, 0)
1314 BUILTIN_VD (REINTERP_SU
, reinterpretv1df
, 0)
1315 VAR1 (REINTERP_US
, reinterpretdi
, 0, v1df
)
1316 VAR1 (REINTERP_US
, reinterpretv8qi
, 0, v1df
)
1317 VAR1 (REINTERP_US
, reinterpretv4hi
, 0, v1df
)
1318 VAR1 (REINTERP_US
, reinterpretv2si
, 0, v1df
)
1319 VAR1 (REINTERP_US
, reinterpretv2sf
, 0, v1df
)
1320 BUILTIN_VD (REINTERP_SP
, reinterpretv1df
, 0)
1321 VAR1 (REINTERP_PS
, reinterpretdi
, 0, v1df
)
1322 VAR1 (REINTERP_PS
, reinterpretv8qi
, 0, v1df
)
1323 VAR1 (REINTERP_PS
, reinterpretv4hi
, 0, v1df
)
1324 VAR1 (REINTERP_PS
, reinterpretv2sf
, 0, v1df
)
1325 return fold_build1 (VIEW_CONVERT_EXPR
, type
, args
[0]);
1326 VAR1 (UNOP
, floatv2si
, 2, v2sf
)
1327 VAR1 (UNOP
, floatv4si
, 2, v4sf
)
1328 VAR1 (UNOP
, floatv2di
, 2, v2df
)
1329 return fold_build1 (FLOAT_EXPR
, type
, args
[0]);
1338 aarch64_gimple_fold_builtin (gimple_stmt_iterator
*gsi
)
1340 bool changed
= false;
1341 gimple stmt
= gsi_stmt (*gsi
);
1342 tree call
= gimple_call_fn (stmt
);
1344 gimple new_stmt
= NULL
;
1346 /* The operations folded below are reduction operations. These are
1347 defined to leave their result in the 0'th element (from the perspective
1348 of GCC). The architectural instruction we are folding will leave the
1349 result in the 0'th element (from the perspective of the architecture).
1350 For big-endian systems, these perspectives are not aligned.
1352 It is therefore wrong to perform this fold on big-endian. There
1353 are some tricks we could play with shuffling, but the mid-end is
1354 inconsistent in the way it treats reduction operations, so we will
1355 end up in difficulty. Until we fix the ambiguity - just bail out. */
1356 if (BYTES_BIG_ENDIAN
)
1361 fndecl
= gimple_call_fndecl (stmt
);
1364 int fcode
= DECL_FUNCTION_CODE (fndecl
);
1365 int nargs
= gimple_call_num_args (stmt
);
1366 tree
*args
= (nargs
> 0
1367 ? gimple_call_arg_ptr (stmt
, 0)
1368 : &error_mark_node
);
1372 BUILTIN_VALL (UNOP
, reduc_splus_
, 10)
1373 new_stmt
= gimple_build_assign_with_ops (
1375 gimple_call_lhs (stmt
),
1379 BUILTIN_VDQIF (UNOP
, reduc_smax_
, 10)
1380 new_stmt
= gimple_build_assign_with_ops (
1382 gimple_call_lhs (stmt
),
1386 BUILTIN_VDQIF (UNOP
, reduc_smin_
, 10)
1387 new_stmt
= gimple_build_assign_with_ops (
1389 gimple_call_lhs (stmt
),
1402 gsi_replace (gsi
, new_stmt
, true);
1410 aarch64_atomic_assign_expand_fenv (tree
*hold
, tree
*clear
, tree
*update
)
1412 const unsigned AARCH64_FE_INVALID
= 1;
1413 const unsigned AARCH64_FE_DIVBYZERO
= 2;
1414 const unsigned AARCH64_FE_OVERFLOW
= 4;
1415 const unsigned AARCH64_FE_UNDERFLOW
= 8;
1416 const unsigned AARCH64_FE_INEXACT
= 16;
1417 const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT
= (AARCH64_FE_INVALID
1418 | AARCH64_FE_DIVBYZERO
1419 | AARCH64_FE_OVERFLOW
1420 | AARCH64_FE_UNDERFLOW
1421 | AARCH64_FE_INEXACT
);
1422 const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT
= 8;
1423 tree fenv_cr
, fenv_sr
, get_fpcr
, set_fpcr
, mask_cr
, mask_sr
;
1424 tree ld_fenv_cr
, ld_fenv_sr
, masked_fenv_cr
, masked_fenv_sr
, hold_fnclex_cr
;
1425 tree hold_fnclex_sr
, new_fenv_var
, reload_fenv
, restore_fnenv
, get_fpsr
, set_fpsr
;
1426 tree update_call
, atomic_feraiseexcept
, hold_fnclex
, masked_fenv
, ld_fenv
;
1428 /* Generate the equivalence of :
1429 unsigned int fenv_cr;
1430 fenv_cr = __builtin_aarch64_get_fpcr ();
1432 unsigned int fenv_sr;
1433 fenv_sr = __builtin_aarch64_get_fpsr ();
1435 Now set all exceptions to non-stop
1436 unsigned int mask_cr
1437 = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
1438 unsigned int masked_cr;
1439 masked_cr = fenv_cr & mask_cr;
1441 And clear all exception flags
1442 unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
1443 unsigned int masked_cr;
1444 masked_sr = fenv_sr & mask_sr;
1446 __builtin_aarch64_set_cr (masked_cr);
1447 __builtin_aarch64_set_sr (masked_sr); */
1449 fenv_cr
= create_tmp_var (unsigned_type_node
, NULL
);
1450 fenv_sr
= create_tmp_var (unsigned_type_node
, NULL
);
1452 get_fpcr
= aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPCR
];
1453 set_fpcr
= aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPCR
];
1454 get_fpsr
= aarch64_builtin_decls
[AARCH64_BUILTIN_GET_FPSR
];
1455 set_fpsr
= aarch64_builtin_decls
[AARCH64_BUILTIN_SET_FPSR
];
1457 mask_cr
= build_int_cst (unsigned_type_node
,
1458 ~(AARCH64_FE_ALL_EXCEPT
<< AARCH64_FE_EXCEPT_SHIFT
));
1459 mask_sr
= build_int_cst (unsigned_type_node
,
1460 ~(AARCH64_FE_ALL_EXCEPT
));
1462 ld_fenv_cr
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1463 fenv_cr
, build_call_expr (get_fpcr
, 0));
1464 ld_fenv_sr
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1465 fenv_sr
, build_call_expr (get_fpsr
, 0));
1467 masked_fenv_cr
= build2 (BIT_AND_EXPR
, unsigned_type_node
, fenv_cr
, mask_cr
);
1468 masked_fenv_sr
= build2 (BIT_AND_EXPR
, unsigned_type_node
, fenv_sr
, mask_sr
);
1470 hold_fnclex_cr
= build_call_expr (set_fpcr
, 1, masked_fenv_cr
);
1471 hold_fnclex_sr
= build_call_expr (set_fpsr
, 1, masked_fenv_sr
);
1473 hold_fnclex
= build2 (COMPOUND_EXPR
, void_type_node
, hold_fnclex_cr
,
1475 masked_fenv
= build2 (COMPOUND_EXPR
, void_type_node
, masked_fenv_cr
,
1477 ld_fenv
= build2 (COMPOUND_EXPR
, void_type_node
, ld_fenv_cr
, ld_fenv_sr
);
1479 *hold
= build2 (COMPOUND_EXPR
, void_type_node
,
1480 build2 (COMPOUND_EXPR
, void_type_node
, masked_fenv
, ld_fenv
),
1483 /* Store the value of masked_fenv to clear the exceptions:
1484 __builtin_aarch64_set_fpsr (masked_fenv_sr); */
1486 *clear
= build_call_expr (set_fpsr
, 1, masked_fenv_sr
);
1488 /* Generate the equivalent of :
1489 unsigned int new_fenv_var;
1490 new_fenv_var = __builtin_aarch64_get_fpsr ();
1492 __builtin_aarch64_set_fpsr (fenv_sr);
1494 __atomic_feraiseexcept (new_fenv_var); */
1496 new_fenv_var
= create_tmp_var (unsigned_type_node
, NULL
);
1497 reload_fenv
= build2 (MODIFY_EXPR
, unsigned_type_node
,
1498 new_fenv_var
, build_call_expr (get_fpsr
, 0));
1499 restore_fnenv
= build_call_expr (set_fpsr
, 1, fenv_sr
);
1500 atomic_feraiseexcept
= builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT
);
1501 update_call
= build_call_expr (atomic_feraiseexcept
, 1,
1502 fold_convert (integer_type_node
, new_fenv_var
));
1503 *update
= build2 (COMPOUND_EXPR
, void_type_node
,
1504 build2 (COMPOUND_EXPR
, void_type_node
,
1505 reload_fenv
, restore_fnenv
), update_call
);
1509 #undef AARCH64_CHECK_BUILTIN_MODE
1510 #undef AARCH64_FIND_FRINT_VARIANT
1512 #undef BUILTIN_SDQ_I
1513 #undef BUILTIN_SD_HSI
1525 #undef BUILTIN_VDQHS
1526 #undef BUILTIN_VDQIF
1529 #undef BUILTIN_VDQ_BHSI
1530 #undef BUILTIN_VDQ_I
1532 #undef BUILTIN_VD_BHSI
1533 #undef BUILTIN_VD_HSI
1537 #undef BUILTIN_VQ_HSI
1539 #undef BUILTIN_VSDQ_HSI
1540 #undef BUILTIN_VSDQ_I
1541 #undef BUILTIN_VSDQ_I_BHSI
1542 #undef BUILTIN_VSDQ_I_DI
1543 #undef BUILTIN_VSD_HSI
1544 #undef BUILTIN_VSQN_HSDI
1545 #undef BUILTIN_VSTRUCT