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