]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/aarch64/aarch64-builtins.c
Implement support for AArch64 Crypto AES.
[thirdparty/gcc.git] / gcc / config / aarch64 / aarch64-builtins.c
CommitLineData
43e9d192 1/* Builtins' description for AArch64 SIMD architecture.
d1e082c2 2 Copyright (C) 2011-2013 Free Software Foundation, Inc.
43e9d192
IB
3 Contributed by ARM Ltd.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "rtl.h"
26#include "tree.h"
d8a2d370
DN
27#include "stor-layout.h"
28#include "stringpool.h"
29#include "calls.h"
43e9d192
IB
30#include "expr.h"
31#include "tm_p.h"
32#include "recog.h"
33#include "langhooks.h"
34#include "diagnostic-core.h"
35#include "optabs.h"
2fb9a547
AM
36#include "pointer-set.h"
37#include "hash-table.h"
38#include "vec.h"
39#include "ggc.h"
40#include "basic-block.h"
41#include "tree-ssa-alias.h"
42#include "internal-fn.h"
43#include "gimple-fold.h"
44#include "tree-eh.h"
45#include "gimple-expr.h"
46#include "is-a.h"
0ac198d3 47#include "gimple.h"
5be5c238 48#include "gimple-iterator.h"
43e9d192 49
342be7f7 50enum aarch64_simd_builtin_type_mode
43e9d192 51{
342be7f7
JG
52 T_V8QI,
53 T_V4HI,
54 T_V2SI,
55 T_V2SF,
56 T_DI,
57 T_DF,
58 T_V16QI,
59 T_V8HI,
60 T_V4SI,
61 T_V4SF,
62 T_V2DI,
63 T_V2DF,
64 T_TI,
65 T_EI,
66 T_OI,
67 T_XI,
68 T_SI,
0050faf8 69 T_SF,
342be7f7
JG
70 T_HI,
71 T_QI,
72 T_MAX
43e9d192
IB
73};
74
75#define v8qi_UP T_V8QI
76#define v4hi_UP T_V4HI
77#define v2si_UP T_V2SI
78#define v2sf_UP T_V2SF
79#define di_UP T_DI
80#define df_UP T_DF
81#define v16qi_UP T_V16QI
82#define v8hi_UP T_V8HI
83#define v4si_UP T_V4SI
84#define v4sf_UP T_V4SF
85#define v2di_UP T_V2DI
86#define v2df_UP T_V2DF
87#define ti_UP T_TI
88#define ei_UP T_EI
89#define oi_UP T_OI
90#define xi_UP T_XI
91#define si_UP T_SI
0050faf8 92#define sf_UP T_SF
43e9d192
IB
93#define hi_UP T_HI
94#define qi_UP T_QI
95
96#define UP(X) X##_UP
97
b5828b4b
JG
98#define SIMD_MAX_BUILTIN_ARGS 5
99
100enum aarch64_type_qualifiers
43e9d192 101{
b5828b4b
JG
102 /* T foo. */
103 qualifier_none = 0x0,
104 /* unsigned T foo. */
105 qualifier_unsigned = 0x1, /* 1 << 0 */
106 /* const T foo. */
107 qualifier_const = 0x2, /* 1 << 1 */
108 /* T *foo. */
109 qualifier_pointer = 0x4, /* 1 << 2 */
110 /* const T *foo. */
111 qualifier_const_pointer = 0x6, /* qualifier_const | qualifier_pointer */
112 /* Used when expanding arguments if an operand could
113 be an immediate. */
114 qualifier_immediate = 0x8, /* 1 << 3 */
115 qualifier_maybe_immediate = 0x10, /* 1 << 4 */
116 /* void foo (...). */
117 qualifier_void = 0x20, /* 1 << 5 */
118 /* Some patterns may have internal operands, this qualifier is an
119 instruction to the initialisation code to skip this operand. */
120 qualifier_internal = 0x40, /* 1 << 6 */
121 /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
122 rather than using the type of the operand. */
123 qualifier_map_mode = 0x80, /* 1 << 7 */
124 /* qualifier_pointer | qualifier_map_mode */
125 qualifier_pointer_map_mode = 0x84,
126 /* qualifier_const_pointer | qualifier_map_mode */
6db1ec94
JG
127 qualifier_const_pointer_map_mode = 0x86,
128 /* Polynomial types. */
129 qualifier_poly = 0x100
b5828b4b 130};
43e9d192
IB
131
132typedef struct
133{
134 const char *name;
342be7f7
JG
135 enum aarch64_simd_builtin_type_mode mode;
136 const enum insn_code code;
137 unsigned int fcode;
b5828b4b 138 enum aarch64_type_qualifiers *qualifiers;
43e9d192
IB
139} aarch64_simd_builtin_datum;
140
b5828b4b
JG
141static enum aarch64_type_qualifiers
142aarch64_types_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
143 = { qualifier_none, qualifier_none };
144#define TYPES_UNOP (aarch64_types_unop_qualifiers)
5a7a4e80
TB
145static enum aarch64_type_qualifiers
146aarch64_types_unopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
147 = { qualifier_unsigned, qualifier_unsigned };
148#define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
b5828b4b
JG
149#define TYPES_CREATE (aarch64_types_unop_qualifiers)
150#define TYPES_REINTERP (aarch64_types_unop_qualifiers)
151static enum aarch64_type_qualifiers
152aarch64_types_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
153 = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
154#define TYPES_BINOP (aarch64_types_binop_qualifiers)
155static enum aarch64_type_qualifiers
5a7a4e80
TB
156aarch64_types_binopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
157 = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
158#define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
159static enum aarch64_type_qualifiers
b5828b4b
JG
160aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
161 = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
162#define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
163static enum aarch64_type_qualifiers
164aarch64_types_quadop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
165 = { qualifier_none, qualifier_none, qualifier_none,
166 qualifier_none, qualifier_none };
167#define TYPES_QUADOP (aarch64_types_quadop_qualifiers)
168
169static enum aarch64_type_qualifiers
170aarch64_types_getlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
171 = { qualifier_none, qualifier_none, qualifier_immediate };
172#define TYPES_GETLANE (aarch64_types_getlane_qualifiers)
173#define TYPES_SHIFTIMM (aarch64_types_getlane_qualifiers)
174static enum aarch64_type_qualifiers
175aarch64_types_setlane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
176 = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate };
177#define TYPES_SETLANE (aarch64_types_setlane_qualifiers)
178#define TYPES_SHIFTINSERT (aarch64_types_setlane_qualifiers)
179#define TYPES_SHIFTACC (aarch64_types_setlane_qualifiers)
180
181static enum aarch64_type_qualifiers
182aarch64_types_combine_qualifiers[SIMD_MAX_BUILTIN_ARGS]
183 = { qualifier_none, qualifier_none, qualifier_none };
184#define TYPES_COMBINE (aarch64_types_combine_qualifiers)
185
186static enum aarch64_type_qualifiers
187aarch64_types_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
188 = { qualifier_none, qualifier_const_pointer_map_mode };
189#define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
190#define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
191
46e778c4
JG
192static enum aarch64_type_qualifiers
193aarch64_types_bsl_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
194 = { qualifier_poly, qualifier_unsigned,
195 qualifier_poly, qualifier_poly };
196#define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
197static enum aarch64_type_qualifiers
198aarch64_types_bsl_s_qualifiers[SIMD_MAX_BUILTIN_ARGS]
199 = { qualifier_none, qualifier_unsigned,
200 qualifier_none, qualifier_none };
201#define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
202static enum aarch64_type_qualifiers
203aarch64_types_bsl_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
204 = { qualifier_unsigned, qualifier_unsigned,
205 qualifier_unsigned, qualifier_unsigned };
206#define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
207
b5828b4b
JG
208/* The first argument (return type) of a store should be void type,
209 which we represent with qualifier_void. Their first operand will be
210 a DImode pointer to the location to store to, so we must use
211 qualifier_map_mode | qualifier_pointer to build a pointer to the
212 element type of the vector. */
213static enum aarch64_type_qualifiers
214aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
215 = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
216#define TYPES_STORE1 (aarch64_types_store1_qualifiers)
217#define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
218
0ddec79f
JG
219#define CF0(N, X) CODE_FOR_aarch64_##N##X
220#define CF1(N, X) CODE_FOR_##N##X##1
221#define CF2(N, X) CODE_FOR_##N##X##2
222#define CF3(N, X) CODE_FOR_##N##X##3
223#define CF4(N, X) CODE_FOR_##N##X##4
224#define CF10(N, X) CODE_FOR_##N##X
225
226#define VAR1(T, N, MAP, A) \
b5828b4b 227 {#N, UP (A), CF##MAP (N, A), 0, TYPES_##T},
0ddec79f
JG
228#define VAR2(T, N, MAP, A, B) \
229 VAR1 (T, N, MAP, A) \
230 VAR1 (T, N, MAP, B)
231#define VAR3(T, N, MAP, A, B, C) \
232 VAR2 (T, N, MAP, A, B) \
233 VAR1 (T, N, MAP, C)
234#define VAR4(T, N, MAP, A, B, C, D) \
235 VAR3 (T, N, MAP, A, B, C) \
236 VAR1 (T, N, MAP, D)
237#define VAR5(T, N, MAP, A, B, C, D, E) \
238 VAR4 (T, N, MAP, A, B, C, D) \
239 VAR1 (T, N, MAP, E)
240#define VAR6(T, N, MAP, A, B, C, D, E, F) \
241 VAR5 (T, N, MAP, A, B, C, D, E) \
242 VAR1 (T, N, MAP, F)
243#define VAR7(T, N, MAP, A, B, C, D, E, F, G) \
244 VAR6 (T, N, MAP, A, B, C, D, E, F) \
245 VAR1 (T, N, MAP, G)
246#define VAR8(T, N, MAP, A, B, C, D, E, F, G, H) \
247 VAR7 (T, N, MAP, A, B, C, D, E, F, G) \
248 VAR1 (T, N, MAP, H)
249#define VAR9(T, N, MAP, A, B, C, D, E, F, G, H, I) \
250 VAR8 (T, N, MAP, A, B, C, D, E, F, G, H) \
251 VAR1 (T, N, MAP, I)
252#define VAR10(T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
253 VAR9 (T, N, MAP, A, B, C, D, E, F, G, H, I) \
254 VAR1 (T, N, MAP, J)
255#define VAR11(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
256 VAR10 (T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
257 VAR1 (T, N, MAP, K)
258#define VAR12(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L) \
259 VAR11 (T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
260 VAR1 (T, N, MAP, L)
342be7f7
JG
261
262/* BUILTIN_<ITERATOR> macros should expand to cover the same range of
263 modes as is given for each define_mode_iterator in
264 config/aarch64/iterators.md. */
265
0ddec79f
JG
266#define BUILTIN_DX(T, N, MAP) \
267 VAR2 (T, N, MAP, di, df)
268#define BUILTIN_GPF(T, N, MAP) \
269 VAR2 (T, N, MAP, sf, df)
270#define BUILTIN_SDQ_I(T, N, MAP) \
271 VAR4 (T, N, MAP, qi, hi, si, di)
272#define BUILTIN_SD_HSI(T, N, MAP) \
273 VAR2 (T, N, MAP, hi, si)
274#define BUILTIN_V2F(T, N, MAP) \
275 VAR2 (T, N, MAP, v2sf, v2df)
276#define BUILTIN_VALL(T, N, MAP) \
277 VAR10 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, \
278 v4si, v2di, v2sf, v4sf, v2df)
bb60efd9
JG
279#define BUILTIN_VALLDI(T, N, MAP) \
280 VAR11 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, \
281 v4si, v2di, v2sf, v4sf, v2df, di)
46e778c4
JG
282#define BUILTIN_VALLDIF(T, N, MAP) \
283 VAR12 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, \
284 v4si, v2di, v2sf, v4sf, v2df, di, df)
0ddec79f
JG
285#define BUILTIN_VB(T, N, MAP) \
286 VAR2 (T, N, MAP, v8qi, v16qi)
287#define BUILTIN_VD(T, N, MAP) \
288 VAR4 (T, N, MAP, v8qi, v4hi, v2si, v2sf)
289#define BUILTIN_VDC(T, N, MAP) \
290 VAR6 (T, N, MAP, v8qi, v4hi, v2si, v2sf, di, df)
291#define BUILTIN_VDIC(T, N, MAP) \
292 VAR3 (T, N, MAP, v8qi, v4hi, v2si)
293#define BUILTIN_VDN(T, N, MAP) \
294 VAR3 (T, N, MAP, v4hi, v2si, di)
295#define BUILTIN_VDQ(T, N, MAP) \
296 VAR7 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di)
297#define BUILTIN_VDQF(T, N, MAP) \
298 VAR3 (T, N, MAP, v2sf, v4sf, v2df)
299#define BUILTIN_VDQH(T, N, MAP) \
300 VAR2 (T, N, MAP, v4hi, v8hi)
301#define BUILTIN_VDQHS(T, N, MAP) \
302 VAR4 (T, N, MAP, v4hi, v8hi, v2si, v4si)
303#define BUILTIN_VDQIF(T, N, MAP) \
304 VAR9 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2sf, v4sf, v2df)
305#define BUILTIN_VDQM(T, N, MAP) \
306 VAR6 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si)
307#define BUILTIN_VDQV(T, N, MAP) \
308 VAR5 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v4si)
46e778c4
JG
309#define BUILTIN_VDQQH(T, N, MAP) \
310 VAR4 (T, N, MAP, v8qi, v16qi, v4hi, v8hi)
0ddec79f
JG
311#define BUILTIN_VDQ_BHSI(T, N, MAP) \
312 VAR6 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si)
313#define BUILTIN_VDQ_I(T, N, MAP) \
314 VAR7 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di)
315#define BUILTIN_VDW(T, N, MAP) \
316 VAR3 (T, N, MAP, v8qi, v4hi, v2si)
317#define BUILTIN_VD_BHSI(T, N, MAP) \
318 VAR3 (T, N, MAP, v8qi, v4hi, v2si)
319#define BUILTIN_VD_HSI(T, N, MAP) \
320 VAR2 (T, N, MAP, v4hi, v2si)
321#define BUILTIN_VD_RE(T, N, MAP) \
322 VAR6 (T, N, MAP, v8qi, v4hi, v2si, v2sf, di, df)
323#define BUILTIN_VQ(T, N, MAP) \
324 VAR6 (T, N, MAP, v16qi, v8hi, v4si, v2di, v4sf, v2df)
325#define BUILTIN_VQN(T, N, MAP) \
326 VAR3 (T, N, MAP, v8hi, v4si, v2di)
327#define BUILTIN_VQW(T, N, MAP) \
328 VAR3 (T, N, MAP, v16qi, v8hi, v4si)
329#define BUILTIN_VQ_HSI(T, N, MAP) \
330 VAR2 (T, N, MAP, v8hi, v4si)
331#define BUILTIN_VQ_S(T, N, MAP) \
332 VAR6 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si)
333#define BUILTIN_VSDQ_HSI(T, N, MAP) \
334 VAR6 (T, N, MAP, v4hi, v8hi, v2si, v4si, hi, si)
335#define BUILTIN_VSDQ_I(T, N, MAP) \
336 VAR11 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, qi, hi, si, di)
337#define BUILTIN_VSDQ_I_BHSI(T, N, MAP) \
338 VAR10 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, qi, hi, si)
339#define BUILTIN_VSDQ_I_DI(T, N, MAP) \
340 VAR8 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si, v2di, di)
341#define BUILTIN_VSD_HSI(T, N, MAP) \
342 VAR4 (T, N, MAP, v4hi, v2si, hi, si)
343#define BUILTIN_VSQN_HSDI(T, N, MAP) \
344 VAR6 (T, N, MAP, v8hi, v4si, v2di, hi, si, di)
345#define BUILTIN_VSTRUCT(T, N, MAP) \
346 VAR3 (T, N, MAP, oi, ci, xi)
43e9d192
IB
347
348static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
342be7f7
JG
349#include "aarch64-simd-builtins.def"
350};
351
352#undef VAR1
0ddec79f 353#define VAR1(T, N, MAP, A) \
e993fea1 354 AARCH64_SIMD_BUILTIN_##T##_##N##A,
342be7f7
JG
355
356enum aarch64_builtins
357{
358 AARCH64_BUILTIN_MIN,
359 AARCH64_SIMD_BUILTIN_BASE,
360#include "aarch64-simd-builtins.def"
361 AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_BUILTIN_BASE
362 + ARRAY_SIZE (aarch64_simd_builtin_data),
363 AARCH64_BUILTIN_MAX
43e9d192
IB
364};
365
119103ca
JG
366static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX];
367
43e9d192
IB
368#define NUM_DREG_TYPES 6
369#define NUM_QREG_TYPES 6
370
b5828b4b
JG
371/* Return a tree for a signed or unsigned argument of either
372 the mode specified by MODE, or the inner mode of MODE. */
373tree
6db1ec94
JG
374aarch64_build_scalar_type (enum machine_mode mode,
375 bool unsigned_p,
376 bool poly_p)
b5828b4b
JG
377{
378#undef INT_TYPES
379#define INT_TYPES \
380 AARCH64_TYPE_BUILDER (QI) \
381 AARCH64_TYPE_BUILDER (HI) \
382 AARCH64_TYPE_BUILDER (SI) \
383 AARCH64_TYPE_BUILDER (DI) \
384 AARCH64_TYPE_BUILDER (EI) \
385 AARCH64_TYPE_BUILDER (OI) \
386 AARCH64_TYPE_BUILDER (CI) \
387 AARCH64_TYPE_BUILDER (XI) \
388 AARCH64_TYPE_BUILDER (TI) \
389
390/* Statically declare all the possible types we might need. */
391#undef AARCH64_TYPE_BUILDER
392#define AARCH64_TYPE_BUILDER(X) \
6db1ec94 393 static tree X##_aarch64_type_node_p = NULL; \
b5828b4b
JG
394 static tree X##_aarch64_type_node_s = NULL; \
395 static tree X##_aarch64_type_node_u = NULL;
396
397 INT_TYPES
398
399 static tree float_aarch64_type_node = NULL;
400 static tree double_aarch64_type_node = NULL;
401
402 gcc_assert (!VECTOR_MODE_P (mode));
403
404/* If we've already initialised this type, don't initialise it again,
405 otherwise ask for a new type of the correct size. */
406#undef AARCH64_TYPE_BUILDER
407#define AARCH64_TYPE_BUILDER(X) \
408 case X##mode: \
409 if (unsigned_p) \
410 return (X##_aarch64_type_node_u \
411 ? X##_aarch64_type_node_u \
412 : X##_aarch64_type_node_u \
413 = make_unsigned_type (GET_MODE_PRECISION (mode))); \
6db1ec94
JG
414 else if (poly_p) \
415 return (X##_aarch64_type_node_p \
416 ? X##_aarch64_type_node_p \
417 : X##_aarch64_type_node_p \
418 = make_unsigned_type (GET_MODE_PRECISION (mode))); \
b5828b4b
JG
419 else \
420 return (X##_aarch64_type_node_s \
421 ? X##_aarch64_type_node_s \
422 : X##_aarch64_type_node_s \
423 = make_signed_type (GET_MODE_PRECISION (mode))); \
424 break;
425
426 switch (mode)
427 {
428 INT_TYPES
429 case SFmode:
430 if (!float_aarch64_type_node)
431 {
432 float_aarch64_type_node = make_node (REAL_TYPE);
433 TYPE_PRECISION (float_aarch64_type_node) = FLOAT_TYPE_SIZE;
434 layout_type (float_aarch64_type_node);
435 }
436 return float_aarch64_type_node;
437 break;
438 case DFmode:
439 if (!double_aarch64_type_node)
440 {
441 double_aarch64_type_node = make_node (REAL_TYPE);
442 TYPE_PRECISION (double_aarch64_type_node) = DOUBLE_TYPE_SIZE;
443 layout_type (double_aarch64_type_node);
444 }
445 return double_aarch64_type_node;
446 break;
447 default:
448 gcc_unreachable ();
449 }
450}
451
452tree
6db1ec94
JG
453aarch64_build_vector_type (enum machine_mode mode,
454 bool unsigned_p,
455 bool poly_p)
b5828b4b
JG
456{
457 tree eltype;
458
459#define VECTOR_TYPES \
460 AARCH64_TYPE_BUILDER (V16QI) \
461 AARCH64_TYPE_BUILDER (V8HI) \
462 AARCH64_TYPE_BUILDER (V4SI) \
463 AARCH64_TYPE_BUILDER (V2DI) \
464 AARCH64_TYPE_BUILDER (V8QI) \
465 AARCH64_TYPE_BUILDER (V4HI) \
466 AARCH64_TYPE_BUILDER (V2SI) \
467 \
468 AARCH64_TYPE_BUILDER (V4SF) \
469 AARCH64_TYPE_BUILDER (V2DF) \
470 AARCH64_TYPE_BUILDER (V2SF) \
471/* Declare our "cache" of values. */
472#undef AARCH64_TYPE_BUILDER
473#define AARCH64_TYPE_BUILDER(X) \
474 static tree X##_aarch64_type_node_s = NULL; \
6db1ec94
JG
475 static tree X##_aarch64_type_node_u = NULL; \
476 static tree X##_aarch64_type_node_p = NULL;
b5828b4b
JG
477
478 VECTOR_TYPES
479
480 gcc_assert (VECTOR_MODE_P (mode));
481
482#undef AARCH64_TYPE_BUILDER
483#define AARCH64_TYPE_BUILDER(X) \
484 case X##mode: \
485 if (unsigned_p) \
486 return X##_aarch64_type_node_u \
487 ? X##_aarch64_type_node_u \
488 : X##_aarch64_type_node_u \
489 = build_vector_type_for_mode (aarch64_build_scalar_type \
490 (GET_MODE_INNER (mode), \
6db1ec94
JG
491 unsigned_p, poly_p), mode); \
492 else if (poly_p) \
493 return X##_aarch64_type_node_p \
494 ? X##_aarch64_type_node_p \
495 : X##_aarch64_type_node_p \
496 = build_vector_type_for_mode (aarch64_build_scalar_type \
497 (GET_MODE_INNER (mode), \
498 unsigned_p, poly_p), mode); \
b5828b4b
JG
499 else \
500 return X##_aarch64_type_node_s \
501 ? X##_aarch64_type_node_s \
502 : X##_aarch64_type_node_s \
503 = build_vector_type_for_mode (aarch64_build_scalar_type \
504 (GET_MODE_INNER (mode), \
6db1ec94 505 unsigned_p, poly_p), mode); \
b5828b4b
JG
506 break;
507
508 switch (mode)
509 {
510 default:
6db1ec94
JG
511 eltype = aarch64_build_scalar_type (GET_MODE_INNER (mode),
512 unsigned_p, poly_p);
b5828b4b
JG
513 return build_vector_type_for_mode (eltype, mode);
514 break;
515 VECTOR_TYPES
516 }
517}
518
519tree
6db1ec94 520aarch64_build_type (enum machine_mode mode, bool unsigned_p, bool poly_p)
b5828b4b
JG
521{
522 if (VECTOR_MODE_P (mode))
6db1ec94 523 return aarch64_build_vector_type (mode, unsigned_p, poly_p);
b5828b4b 524 else
6db1ec94
JG
525 return aarch64_build_scalar_type (mode, unsigned_p, poly_p);
526}
527
528tree
529aarch64_build_signed_type (enum machine_mode mode)
530{
531 return aarch64_build_type (mode, false, false);
532}
533
534tree
535aarch64_build_unsigned_type (enum machine_mode mode)
536{
537 return aarch64_build_type (mode, true, false);
538}
539
540tree
541aarch64_build_poly_type (enum machine_mode mode)
542{
543 return aarch64_build_type (mode, false, true);
b5828b4b
JG
544}
545
af55e82d 546static void
342be7f7 547aarch64_init_simd_builtins (void)
43e9d192 548{
342be7f7 549 unsigned int i, fcode = AARCH64_SIMD_BUILTIN_BASE + 1;
43e9d192 550
6db1ec94
JG
551 /* Signed scalar type nodes. */
552 tree aarch64_simd_intQI_type_node = aarch64_build_signed_type (QImode);
553 tree aarch64_simd_intHI_type_node = aarch64_build_signed_type (HImode);
554 tree aarch64_simd_intSI_type_node = aarch64_build_signed_type (SImode);
555 tree aarch64_simd_intDI_type_node = aarch64_build_signed_type (DImode);
556 tree aarch64_simd_intTI_type_node = aarch64_build_signed_type (TImode);
557 tree aarch64_simd_intEI_type_node = aarch64_build_signed_type (EImode);
558 tree aarch64_simd_intOI_type_node = aarch64_build_signed_type (OImode);
559 tree aarch64_simd_intCI_type_node = aarch64_build_signed_type (CImode);
560 tree aarch64_simd_intXI_type_node = aarch64_build_signed_type (XImode);
561
562 /* Unsigned scalar type nodes. */
563 tree aarch64_simd_intUQI_type_node = aarch64_build_unsigned_type (QImode);
564 tree aarch64_simd_intUHI_type_node = aarch64_build_unsigned_type (HImode);
565 tree aarch64_simd_intUSI_type_node = aarch64_build_unsigned_type (SImode);
566 tree aarch64_simd_intUDI_type_node = aarch64_build_unsigned_type (DImode);
567
568 /* Poly scalar type nodes. */
569 tree aarch64_simd_polyQI_type_node = aarch64_build_poly_type (QImode);
570 tree aarch64_simd_polyHI_type_node = aarch64_build_poly_type (HImode);
b5828b4b
JG
571
572 /* Float type nodes. */
6db1ec94
JG
573 tree aarch64_simd_float_type_node = aarch64_build_signed_type (SFmode);
574 tree aarch64_simd_double_type_node = aarch64_build_signed_type (DFmode);
43e9d192
IB
575
576 /* Define typedefs which exactly correspond to the modes we are basing vector
577 types on. If you change these names you'll need to change
578 the table used by aarch64_mangle_type too. */
579 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intQI_type_node,
580 "__builtin_aarch64_simd_qi");
581 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intHI_type_node,
582 "__builtin_aarch64_simd_hi");
583 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intSI_type_node,
584 "__builtin_aarch64_simd_si");
585 (*lang_hooks.types.register_builtin_type) (aarch64_simd_float_type_node,
586 "__builtin_aarch64_simd_sf");
587 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intDI_type_node,
588 "__builtin_aarch64_simd_di");
589 (*lang_hooks.types.register_builtin_type) (aarch64_simd_double_type_node,
590 "__builtin_aarch64_simd_df");
591 (*lang_hooks.types.register_builtin_type) (aarch64_simd_polyQI_type_node,
592 "__builtin_aarch64_simd_poly8");
593 (*lang_hooks.types.register_builtin_type) (aarch64_simd_polyHI_type_node,
594 "__builtin_aarch64_simd_poly16");
b5828b4b 595 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intTI_type_node,
43e9d192 596 "__builtin_aarch64_simd_ti");
b5828b4b 597 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intEI_type_node,
43e9d192 598 "__builtin_aarch64_simd_ei");
b5828b4b 599 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intOI_type_node,
43e9d192 600 "__builtin_aarch64_simd_oi");
b5828b4b 601 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intCI_type_node,
43e9d192 602 "__builtin_aarch64_simd_ci");
b5828b4b 603 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intXI_type_node,
43e9d192
IB
604 "__builtin_aarch64_simd_xi");
605
b5828b4b
JG
606 /* Unsigned integer types for various mode sizes. */
607 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intUQI_type_node,
608 "__builtin_aarch64_simd_uqi");
609 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intUHI_type_node,
610 "__builtin_aarch64_simd_uhi");
611 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intUSI_type_node,
612 "__builtin_aarch64_simd_usi");
613 (*lang_hooks.types.register_builtin_type) (aarch64_simd_intUDI_type_node,
614 "__builtin_aarch64_simd_udi");
43e9d192 615
342be7f7 616 for (i = 0; i < ARRAY_SIZE (aarch64_simd_builtin_data); i++, fcode++)
43e9d192 617 {
b5828b4b
JG
618 bool print_type_signature_p = false;
619 char type_signature[SIMD_MAX_BUILTIN_ARGS] = { 0 };
43e9d192 620 aarch64_simd_builtin_datum *d = &aarch64_simd_builtin_data[i];
342be7f7 621 const char *const modenames[] =
b5828b4b
JG
622 {
623 "v8qi", "v4hi", "v2si", "v2sf", "di", "df",
624 "v16qi", "v8hi", "v4si", "v4sf", "v2di", "v2df",
625 "ti", "ei", "oi", "xi", "si", "sf", "hi", "qi"
626 };
627 const enum machine_mode modes[] =
628 {
629 V8QImode, V4HImode, V2SImode, V2SFmode, DImode, DFmode,
630 V16QImode, V8HImode, V4SImode, V4SFmode, V2DImode,
631 V2DFmode, TImode, EImode, OImode, XImode, SImode,
632 SFmode, HImode, QImode
633 };
342be7f7
JG
634 char namebuf[60];
635 tree ftype = NULL;
119103ca 636 tree fndecl = NULL;
342be7f7
JG
637
638 gcc_assert (ARRAY_SIZE (modenames) == T_MAX);
43e9d192 639
342be7f7 640 d->fcode = fcode;
43e9d192 641
b5828b4b
JG
642 /* We must track two variables here. op_num is
643 the operand number as in the RTL pattern. This is
644 required to access the mode (e.g. V4SF mode) of the
645 argument, from which the base type can be derived.
646 arg_num is an index in to the qualifiers data, which
647 gives qualifiers to the type (e.g. const unsigned).
648 The reason these two variables may differ by one is the
649 void return type. While all return types take the 0th entry
650 in the qualifiers array, there is no operand for them in the
651 RTL pattern. */
652 int op_num = insn_data[d->code].n_operands - 1;
653 int arg_num = d->qualifiers[0] & qualifier_void
654 ? op_num + 1
655 : op_num;
656 tree return_type = void_type_node, args = void_list_node;
657 tree eltype;
658
659 /* Build a function type directly from the insn_data for this
660 builtin. The build_function_type () function takes care of
661 removing duplicates for us. */
662 for (; op_num >= 0; arg_num--, op_num--)
43e9d192 663 {
b5828b4b
JG
664 enum machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
665 enum aarch64_type_qualifiers qualifiers = d->qualifiers[arg_num];
43e9d192 666
b5828b4b
JG
667 if (qualifiers & qualifier_unsigned)
668 {
669 type_signature[arg_num] = 'u';
670 print_type_signature_p = true;
671 }
6db1ec94
JG
672 else if (qualifiers & qualifier_poly)
673 {
674 type_signature[arg_num] = 'p';
675 print_type_signature_p = true;
676 }
b5828b4b
JG
677 else
678 type_signature[arg_num] = 's';
679
680 /* Skip an internal operand for vget_{low, high}. */
681 if (qualifiers & qualifier_internal)
682 continue;
683
684 /* Some builtins have different user-facing types
685 for certain arguments, encoded in d->mode. */
686 if (qualifiers & qualifier_map_mode)
687 op_mode = modes[d->mode];
688
689 /* For pointers, we want a pointer to the basic type
690 of the vector. */
691 if (qualifiers & qualifier_pointer && VECTOR_MODE_P (op_mode))
692 op_mode = GET_MODE_INNER (op_mode);
693
694 eltype = aarch64_build_type (op_mode,
6db1ec94
JG
695 qualifiers & qualifier_unsigned,
696 qualifiers & qualifier_poly);
b5828b4b
JG
697
698 /* Add qualifiers. */
699 if (qualifiers & qualifier_const)
700 eltype = build_qualified_type (eltype, TYPE_QUAL_CONST);
701
702 if (qualifiers & qualifier_pointer)
703 eltype = build_pointer_type (eltype);
704
705 /* If we have reached arg_num == 0, we are at a non-void
706 return type. Otherwise, we are still processing
707 arguments. */
708 if (arg_num == 0)
709 return_type = eltype;
710 else
711 args = tree_cons (NULL_TREE, eltype, args);
712 }
342be7f7 713
b5828b4b 714 ftype = build_function_type (return_type, args);
43e9d192 715
342be7f7 716 gcc_assert (ftype != NULL);
43e9d192 717
b5828b4b
JG
718 if (print_type_signature_p)
719 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s%s_%s",
720 d->name, modenames[d->mode], type_signature);
721 else
722 snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s%s",
723 d->name, modenames[d->mode]);
43e9d192 724
119103ca
JG
725 fndecl = add_builtin_function (namebuf, ftype, fcode, BUILT_IN_MD,
726 NULL, NULL_TREE);
727 aarch64_builtin_decls[fcode] = fndecl;
43e9d192
IB
728 }
729}
730
342be7f7
JG
731void
732aarch64_init_builtins (void)
43e9d192 733{
342be7f7
JG
734 if (TARGET_SIMD)
735 aarch64_init_simd_builtins ();
43e9d192
IB
736}
737
119103ca
JG
738tree
739aarch64_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
740{
741 if (code >= AARCH64_BUILTIN_MAX)
742 return error_mark_node;
743
744 return aarch64_builtin_decls[code];
745}
746
43e9d192
IB
747typedef enum
748{
749 SIMD_ARG_COPY_TO_REG,
750 SIMD_ARG_CONSTANT,
751 SIMD_ARG_STOP
752} builtin_simd_arg;
753
43e9d192
IB
754static rtx
755aarch64_simd_expand_args (rtx target, int icode, int have_retval,
756 tree exp, ...)
757{
758 va_list ap;
759 rtx pat;
760 tree arg[SIMD_MAX_BUILTIN_ARGS];
761 rtx op[SIMD_MAX_BUILTIN_ARGS];
762 enum machine_mode tmode = insn_data[icode].operand[0].mode;
763 enum machine_mode mode[SIMD_MAX_BUILTIN_ARGS];
764 int argc = 0;
765
766 if (have_retval
767 && (!target
768 || GET_MODE (target) != tmode
769 || !(*insn_data[icode].operand[0].predicate) (target, tmode)))
770 target = gen_reg_rtx (tmode);
771
772 va_start (ap, exp);
773
774 for (;;)
775 {
776 builtin_simd_arg thisarg = (builtin_simd_arg) va_arg (ap, int);
777
778 if (thisarg == SIMD_ARG_STOP)
779 break;
780 else
781 {
782 arg[argc] = CALL_EXPR_ARG (exp, argc);
783 op[argc] = expand_normal (arg[argc]);
784 mode[argc] = insn_data[icode].operand[argc + have_retval].mode;
785
786 switch (thisarg)
787 {
788 case SIMD_ARG_COPY_TO_REG:
2888c331
YZ
789 if (POINTER_TYPE_P (TREE_TYPE (arg[argc])))
790 op[argc] = convert_memory_address (Pmode, op[argc]);
43e9d192
IB
791 /*gcc_assert (GET_MODE (op[argc]) == mode[argc]); */
792 if (!(*insn_data[icode].operand[argc + have_retval].predicate)
793 (op[argc], mode[argc]))
794 op[argc] = copy_to_mode_reg (mode[argc], op[argc]);
795 break;
796
797 case SIMD_ARG_CONSTANT:
798 if (!(*insn_data[icode].operand[argc + have_retval].predicate)
799 (op[argc], mode[argc]))
800 error_at (EXPR_LOCATION (exp), "incompatible type for argument %d, "
801 "expected %<const int%>", argc + 1);
802 break;
803
804 case SIMD_ARG_STOP:
805 gcc_unreachable ();
806 }
807
808 argc++;
809 }
810 }
811
812 va_end (ap);
813
814 if (have_retval)
815 switch (argc)
816 {
817 case 1:
818 pat = GEN_FCN (icode) (target, op[0]);
819 break;
820
821 case 2:
822 pat = GEN_FCN (icode) (target, op[0], op[1]);
823 break;
824
825 case 3:
826 pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
827 break;
828
829 case 4:
830 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
831 break;
832
833 case 5:
834 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3], op[4]);
835 break;
836
837 default:
838 gcc_unreachable ();
839 }
840 else
841 switch (argc)
842 {
843 case 1:
844 pat = GEN_FCN (icode) (op[0]);
845 break;
846
847 case 2:
848 pat = GEN_FCN (icode) (op[0], op[1]);
849 break;
850
851 case 3:
852 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
853 break;
854
855 case 4:
856 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
857 break;
858
859 case 5:
860 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
861 break;
862
863 default:
864 gcc_unreachable ();
865 }
866
867 if (!pat)
868 return 0;
869
870 emit_insn (pat);
871
872 return target;
873}
874
875/* Expand an AArch64 AdvSIMD builtin(intrinsic). */
876rtx
877aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
878{
342be7f7
JG
879 aarch64_simd_builtin_datum *d =
880 &aarch64_simd_builtin_data[fcode - (AARCH64_SIMD_BUILTIN_BASE + 1)];
342be7f7 881 enum insn_code icode = d->code;
b5828b4b
JG
882 builtin_simd_arg args[SIMD_MAX_BUILTIN_ARGS];
883 int num_args = insn_data[d->code].n_operands;
884 int is_void = 0;
885 int k;
43e9d192 886
b5828b4b 887 is_void = !!(d->qualifiers[0] & qualifier_void);
43e9d192 888
b5828b4b
JG
889 num_args += is_void;
890
891 for (k = 1; k < num_args; k++)
892 {
893 /* We have four arrays of data, each indexed in a different fashion.
894 qualifiers - element 0 always describes the function return type.
895 operands - element 0 is either the operand for return value (if
896 the function has a non-void return type) or the operand for the
897 first argument.
898 expr_args - element 0 always holds the first argument.
899 args - element 0 is always used for the return type. */
900 int qualifiers_k = k;
901 int operands_k = k - is_void;
902 int expr_args_k = k - 1;
903
904 if (d->qualifiers[qualifiers_k] & qualifier_immediate)
905 args[k] = SIMD_ARG_CONSTANT;
906 else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
907 {
908 rtx arg
909 = expand_normal (CALL_EXPR_ARG (exp,
910 (expr_args_k)));
911 /* Handle constants only if the predicate allows it. */
912 bool op_const_int_p =
913 (CONST_INT_P (arg)
914 && (*insn_data[icode].operand[operands_k].predicate)
915 (arg, insn_data[icode].operand[operands_k].mode));
916 args[k] = op_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG;
917 }
918 else
919 args[k] = SIMD_ARG_COPY_TO_REG;
43e9d192 920
43e9d192 921 }
b5828b4b
JG
922 args[k] = SIMD_ARG_STOP;
923
924 /* The interface to aarch64_simd_expand_args expects a 0 if
925 the function is void, and a 1 if it is not. */
926 return aarch64_simd_expand_args
927 (target, icode, !is_void, exp,
928 args[1],
929 args[2],
930 args[3],
931 args[4],
932 SIMD_ARG_STOP);
43e9d192 933}
342be7f7
JG
934
935/* Expand an expression EXP that calls a built-in function,
936 with result going to TARGET if that's convenient. */
937rtx
938aarch64_expand_builtin (tree exp,
939 rtx target,
940 rtx subtarget ATTRIBUTE_UNUSED,
941 enum machine_mode mode ATTRIBUTE_UNUSED,
942 int ignore ATTRIBUTE_UNUSED)
943{
944 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
945 int fcode = DECL_FUNCTION_CODE (fndecl);
946
947 if (fcode >= AARCH64_SIMD_BUILTIN_BASE)
948 return aarch64_simd_expand_builtin (fcode, exp, target);
949
950 return NULL_RTX;
951}
42fc9a7f
JG
952
953tree
954aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
955{
956 enum machine_mode in_mode, out_mode;
957 int in_n, out_n;
958
959 if (TREE_CODE (type_out) != VECTOR_TYPE
960 || TREE_CODE (type_in) != VECTOR_TYPE)
961 return NULL_TREE;
962
963 out_mode = TYPE_MODE (TREE_TYPE (type_out));
964 out_n = TYPE_VECTOR_SUBPARTS (type_out);
965 in_mode = TYPE_MODE (TREE_TYPE (type_in));
966 in_n = TYPE_VECTOR_SUBPARTS (type_in);
967
968#undef AARCH64_CHECK_BUILTIN_MODE
969#define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
970#define AARCH64_FIND_FRINT_VARIANT(N) \
971 (AARCH64_CHECK_BUILTIN_MODE (2, D) \
e993fea1 972 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
42fc9a7f 973 : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
e993fea1 974 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
42fc9a7f 975 : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
e993fea1 976 ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
42fc9a7f
JG
977 : NULL_TREE)))
978 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
979 {
980 enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
981 switch (fn)
982 {
983#undef AARCH64_CHECK_BUILTIN_MODE
984#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
985 (out_mode == N##Fmode && out_n == C \
986 && in_mode == N##Fmode && in_n == C)
987 case BUILT_IN_FLOOR:
988 case BUILT_IN_FLOORF:
0659ce6f 989 return AARCH64_FIND_FRINT_VARIANT (floor);
42fc9a7f
JG
990 case BUILT_IN_CEIL:
991 case BUILT_IN_CEILF:
0659ce6f 992 return AARCH64_FIND_FRINT_VARIANT (ceil);
42fc9a7f
JG
993 case BUILT_IN_TRUNC:
994 case BUILT_IN_TRUNCF:
0659ce6f 995 return AARCH64_FIND_FRINT_VARIANT (btrunc);
42fc9a7f
JG
996 case BUILT_IN_ROUND:
997 case BUILT_IN_ROUNDF:
0659ce6f 998 return AARCH64_FIND_FRINT_VARIANT (round);
42fc9a7f
JG
999 case BUILT_IN_NEARBYINT:
1000 case BUILT_IN_NEARBYINTF:
0659ce6f 1001 return AARCH64_FIND_FRINT_VARIANT (nearbyint);
4dcd1054
JG
1002 case BUILT_IN_SQRT:
1003 case BUILT_IN_SQRTF:
1004 return AARCH64_FIND_FRINT_VARIANT (sqrt);
42fc9a7f 1005#undef AARCH64_CHECK_BUILTIN_MODE
b5574232
VP
1006#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1007 (out_mode == SImode && out_n == C \
1008 && in_mode == N##Imode && in_n == C)
1009 case BUILT_IN_CLZ:
1010 {
1011 if (AARCH64_CHECK_BUILTIN_MODE (4, S))
e993fea1 1012 return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_clzv4si];
b5574232
VP
1013 return NULL_TREE;
1014 }
1015#undef AARCH64_CHECK_BUILTIN_MODE
42fc9a7f
JG
1016#define AARCH64_CHECK_BUILTIN_MODE(C, N) \
1017 (out_mode == N##Imode && out_n == C \
1018 && in_mode == N##Fmode && in_n == C)
1019 case BUILT_IN_LFLOOR:
0386b123 1020 case BUILT_IN_IFLOORF:
ce966824 1021 {
e993fea1 1022 enum aarch64_builtins builtin;
ce966824 1023 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
e993fea1 1024 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di;
ce966824 1025 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
e993fea1 1026 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si;
ce966824 1027 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
e993fea1
JG
1028 builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si;
1029 else
1030 return NULL_TREE;
1031
1032 return aarch64_builtin_decls[builtin];
ce966824 1033 }
42fc9a7f 1034 case BUILT_IN_LCEIL:
0386b123 1035 case BUILT_IN_ICEILF:
ce966824 1036 {
e993fea1 1037 enum aarch64_builtins builtin;
ce966824 1038 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
e993fea1 1039 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di;
ce966824 1040 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
e993fea1 1041 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si;
ce966824 1042 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
e993fea1
JG
1043 builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si;
1044 else
1045 return NULL_TREE;
1046
1047 return aarch64_builtin_decls[builtin];
ce966824 1048 }
0386b123
JG
1049 case BUILT_IN_LROUND:
1050 case BUILT_IN_IROUNDF:
1051 {
e993fea1 1052 enum aarch64_builtins builtin;
0386b123 1053 if (AARCH64_CHECK_BUILTIN_MODE (2, D))
e993fea1 1054 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di;
0386b123 1055 else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
e993fea1 1056 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si;
0386b123 1057 else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
e993fea1
JG
1058 builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si;
1059 else
1060 return NULL_TREE;
1061
1062 return aarch64_builtin_decls[builtin];
0386b123
JG
1063 }
1064
42fc9a7f
JG
1065 default:
1066 return NULL_TREE;
1067 }
1068 }
1069
1070 return NULL_TREE;
1071}
0ac198d3
JG
1072
1073#undef VAR1
1074#define VAR1(T, N, MAP, A) \
e993fea1 1075 case AARCH64_SIMD_BUILTIN_##T##_##N##A:
0ac198d3 1076
9697e620
JG
1077tree
1078aarch64_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
1079 bool ignore ATTRIBUTE_UNUSED)
1080{
1081 int fcode = DECL_FUNCTION_CODE (fndecl);
1082 tree type = TREE_TYPE (TREE_TYPE (fndecl));
1083
1084 switch (fcode)
1085 {
d05d0709 1086 BUILTIN_VALLDI (UNOP, abs, 2)
9697e620
JG
1087 return fold_build1 (ABS_EXPR, type, args[0]);
1088 break;
bb60efd9
JG
1089 BUILTIN_VALLDI (BINOP, cmge, 0)
1090 return fold_build2 (GE_EXPR, type, args[0], args[1]);
1091 break;
1092 BUILTIN_VALLDI (BINOP, cmgt, 0)
1093 return fold_build2 (GT_EXPR, type, args[0], args[1]);
1094 break;
1095 BUILTIN_VALLDI (BINOP, cmeq, 0)
1096 return fold_build2 (EQ_EXPR, type, args[0], args[1]);
1097 break;
1098 BUILTIN_VSDQ_I_DI (BINOP, cmtst, 0)
1099 {
1100 tree and_node = fold_build2 (BIT_AND_EXPR, type, args[0], args[1]);
1101 tree vec_zero_node = build_zero_cst (type);
1102 return fold_build2 (NE_EXPR, type, and_node, vec_zero_node);
1103 break;
1104 }
1709ff9b
JG
1105 VAR1 (UNOP, floatv2si, 2, v2sf)
1106 VAR1 (UNOP, floatv4si, 2, v4sf)
1107 VAR1 (UNOP, floatv2di, 2, v2df)
1108 return fold_build1 (FLOAT_EXPR, type, args[0]);
9697e620
JG
1109 default:
1110 break;
1111 }
1112
1113 return NULL_TREE;
1114}
1115
0ac198d3
JG
1116bool
1117aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi)
1118{
1119 bool changed = false;
1120 gimple stmt = gsi_stmt (*gsi);
1121 tree call = gimple_call_fn (stmt);
1122 tree fndecl;
1123 gimple new_stmt = NULL;
1124 if (call)
1125 {
1126 fndecl = gimple_call_fndecl (stmt);
1127 if (fndecl)
1128 {
1129 int fcode = DECL_FUNCTION_CODE (fndecl);
1130 int nargs = gimple_call_num_args (stmt);
1131 tree *args = (nargs > 0
1132 ? gimple_call_arg_ptr (stmt, 0)
1133 : &error_mark_node);
1134
1135 switch (fcode)
1136 {
36054fab 1137 BUILTIN_VALL (UNOP, reduc_splus_, 10)
0ac198d3
JG
1138 new_stmt = gimple_build_assign_with_ops (
1139 REDUC_PLUS_EXPR,
1140 gimple_call_lhs (stmt),
1141 args[0],
1142 NULL_TREE);
1143 break;
1598945b
JG
1144 BUILTIN_VDQIF (UNOP, reduc_smax_, 10)
1145 new_stmt = gimple_build_assign_with_ops (
1146 REDUC_MAX_EXPR,
1147 gimple_call_lhs (stmt),
1148 args[0],
1149 NULL_TREE);
1150 break;
1151 BUILTIN_VDQIF (UNOP, reduc_smin_, 10)
1152 new_stmt = gimple_build_assign_with_ops (
1153 REDUC_MIN_EXPR,
1154 gimple_call_lhs (stmt),
1155 args[0],
1156 NULL_TREE);
1157 break;
1158
0ac198d3
JG
1159 default:
1160 break;
1161 }
1162 }
1163 }
1164
1165 if (new_stmt)
1166 {
1167 gsi_replace (gsi, new_stmt, true);
1168 changed = true;
1169 }
1170
1171 return changed;
1172}
1173
42fc9a7f
JG
1174#undef AARCH64_CHECK_BUILTIN_MODE
1175#undef AARCH64_FIND_FRINT_VARIANT
0ddec79f
JG
1176#undef BUILTIN_DX
1177#undef BUILTIN_SDQ_I
1178#undef BUILTIN_SD_HSI
1179#undef BUILTIN_V2F
1180#undef BUILTIN_VALL
1181#undef BUILTIN_VB
1182#undef BUILTIN_VD
1183#undef BUILTIN_VDC
1184#undef BUILTIN_VDIC
1185#undef BUILTIN_VDN
1186#undef BUILTIN_VDQ
1187#undef BUILTIN_VDQF
1188#undef BUILTIN_VDQH
1189#undef BUILTIN_VDQHS
1190#undef BUILTIN_VDQIF
1191#undef BUILTIN_VDQM
1192#undef BUILTIN_VDQV
1193#undef BUILTIN_VDQ_BHSI
1194#undef BUILTIN_VDQ_I
1195#undef BUILTIN_VDW
1196#undef BUILTIN_VD_BHSI
1197#undef BUILTIN_VD_HSI
1198#undef BUILTIN_VD_RE
1199#undef BUILTIN_VQ
1200#undef BUILTIN_VQN
1201#undef BUILTIN_VQW
1202#undef BUILTIN_VQ_HSI
1203#undef BUILTIN_VQ_S
1204#undef BUILTIN_VSDQ_HSI
1205#undef BUILTIN_VSDQ_I
1206#undef BUILTIN_VSDQ_I_BHSI
1207#undef BUILTIN_VSDQ_I_DI
1208#undef BUILTIN_VSD_HSI
1209#undef BUILTIN_VSQN_HSDI
1210#undef BUILTIN_VSTRUCT
1211#undef CF0
1212#undef CF1
1213#undef CF2
1214#undef CF3
1215#undef CF4
1216#undef CF10
1217#undef VAR1
1218#undef VAR2
1219#undef VAR3
1220#undef VAR4
1221#undef VAR5
1222#undef VAR6
1223#undef VAR7
1224#undef VAR8
1225#undef VAR9
1226#undef VAR10
1227#undef VAR11
1228