aarch64-builtins.cc revision 1.1 1 1.1 mrg /* Builtins' description for AArch64 SIMD architecture.
2 1.1 mrg Copyright (C) 2011-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by ARM Ltd.
4 1.1 mrg
5 1.1 mrg This file is part of GCC.
6 1.1 mrg
7 1.1 mrg GCC is free software; you can redistribute it and/or modify it
8 1.1 mrg under the terms of the GNU General Public License as published by
9 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
10 1.1 mrg any later version.
11 1.1 mrg
12 1.1 mrg GCC is distributed in the hope that it will be useful, but
13 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 1.1 mrg General Public License for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU General Public License
18 1.1 mrg along with GCC; see the file COPYING3. If not see
19 1.1 mrg <http://www.gnu.org/licenses/>. */
20 1.1 mrg
21 1.1 mrg #define IN_TARGET_CODE 1
22 1.1 mrg
23 1.1 mrg #include "config.h"
24 1.1 mrg #include "system.h"
25 1.1 mrg #include "coretypes.h"
26 1.1 mrg #include "tm.h"
27 1.1 mrg #include "function.h"
28 1.1 mrg #include "basic-block.h"
29 1.1 mrg #include "rtl.h"
30 1.1 mrg #include "tree.h"
31 1.1 mrg #include "gimple.h"
32 1.1 mrg #include "ssa.h"
33 1.1 mrg #include "memmodel.h"
34 1.1 mrg #include "tm_p.h"
35 1.1 mrg #include "expmed.h"
36 1.1 mrg #include "optabs.h"
37 1.1 mrg #include "recog.h"
38 1.1 mrg #include "diagnostic-core.h"
39 1.1 mrg #include "fold-const.h"
40 1.1 mrg #include "stor-layout.h"
41 1.1 mrg #include "explow.h"
42 1.1 mrg #include "expr.h"
43 1.1 mrg #include "langhooks.h"
44 1.1 mrg #include "gimple-iterator.h"
45 1.1 mrg #include "case-cfn-macros.h"
46 1.1 mrg #include "emit-rtl.h"
47 1.1 mrg #include "stringpool.h"
48 1.1 mrg #include "attribs.h"
49 1.1 mrg #include "gimple-fold.h"
50 1.1 mrg
51 1.1 mrg #define v8qi_UP E_V8QImode
52 1.1 mrg #define v8di_UP E_V8DImode
53 1.1 mrg #define v4hi_UP E_V4HImode
54 1.1 mrg #define v4hf_UP E_V4HFmode
55 1.1 mrg #define v2si_UP E_V2SImode
56 1.1 mrg #define v2sf_UP E_V2SFmode
57 1.1 mrg #define v1df_UP E_V1DFmode
58 1.1 mrg #define di_UP E_DImode
59 1.1 mrg #define df_UP E_DFmode
60 1.1 mrg #define v16qi_UP E_V16QImode
61 1.1 mrg #define v8hi_UP E_V8HImode
62 1.1 mrg #define v8hf_UP E_V8HFmode
63 1.1 mrg #define v4si_UP E_V4SImode
64 1.1 mrg #define v4sf_UP E_V4SFmode
65 1.1 mrg #define v2di_UP E_V2DImode
66 1.1 mrg #define v2df_UP E_V2DFmode
67 1.1 mrg #define ti_UP E_TImode
68 1.1 mrg #define oi_UP E_OImode
69 1.1 mrg #define ci_UP E_CImode
70 1.1 mrg #define xi_UP E_XImode
71 1.1 mrg #define si_UP E_SImode
72 1.1 mrg #define sf_UP E_SFmode
73 1.1 mrg #define hi_UP E_HImode
74 1.1 mrg #define hf_UP E_HFmode
75 1.1 mrg #define qi_UP E_QImode
76 1.1 mrg #define bf_UP E_BFmode
77 1.1 mrg #define v4bf_UP E_V4BFmode
78 1.1 mrg #define v8bf_UP E_V8BFmode
79 1.1 mrg #define v2x8qi_UP E_V2x8QImode
80 1.1 mrg #define v2x4hi_UP E_V2x4HImode
81 1.1 mrg #define v2x4hf_UP E_V2x4HFmode
82 1.1 mrg #define v2x4bf_UP E_V2x4BFmode
83 1.1 mrg #define v2x2si_UP E_V2x2SImode
84 1.1 mrg #define v2x2sf_UP E_V2x2SFmode
85 1.1 mrg #define v2x1di_UP E_V2x1DImode
86 1.1 mrg #define v2x1df_UP E_V2x1DFmode
87 1.1 mrg #define v2x16qi_UP E_V2x16QImode
88 1.1 mrg #define v2x8hi_UP E_V2x8HImode
89 1.1 mrg #define v2x8hf_UP E_V2x8HFmode
90 1.1 mrg #define v2x8bf_UP E_V2x8BFmode
91 1.1 mrg #define v2x4si_UP E_V2x4SImode
92 1.1 mrg #define v2x4sf_UP E_V2x4SFmode
93 1.1 mrg #define v2x2di_UP E_V2x2DImode
94 1.1 mrg #define v2x2df_UP E_V2x2DFmode
95 1.1 mrg #define v3x8qi_UP E_V3x8QImode
96 1.1 mrg #define v3x4hi_UP E_V3x4HImode
97 1.1 mrg #define v3x4hf_UP E_V3x4HFmode
98 1.1 mrg #define v3x4bf_UP E_V3x4BFmode
99 1.1 mrg #define v3x2si_UP E_V3x2SImode
100 1.1 mrg #define v3x2sf_UP E_V3x2SFmode
101 1.1 mrg #define v3x1di_UP E_V3x1DImode
102 1.1 mrg #define v3x1df_UP E_V3x1DFmode
103 1.1 mrg #define v3x16qi_UP E_V3x16QImode
104 1.1 mrg #define v3x8hi_UP E_V3x8HImode
105 1.1 mrg #define v3x8hf_UP E_V3x8HFmode
106 1.1 mrg #define v3x8bf_UP E_V3x8BFmode
107 1.1 mrg #define v3x4si_UP E_V3x4SImode
108 1.1 mrg #define v3x4sf_UP E_V3x4SFmode
109 1.1 mrg #define v3x2di_UP E_V3x2DImode
110 1.1 mrg #define v3x2df_UP E_V3x2DFmode
111 1.1 mrg #define v4x8qi_UP E_V4x8QImode
112 1.1 mrg #define v4x4hi_UP E_V4x4HImode
113 1.1 mrg #define v4x4hf_UP E_V4x4HFmode
114 1.1 mrg #define v4x4bf_UP E_V4x4BFmode
115 1.1 mrg #define v4x2si_UP E_V4x2SImode
116 1.1 mrg #define v4x2sf_UP E_V4x2SFmode
117 1.1 mrg #define v4x1di_UP E_V4x1DImode
118 1.1 mrg #define v4x1df_UP E_V4x1DFmode
119 1.1 mrg #define v4x16qi_UP E_V4x16QImode
120 1.1 mrg #define v4x8hi_UP E_V4x8HImode
121 1.1 mrg #define v4x8hf_UP E_V4x8HFmode
122 1.1 mrg #define v4x8bf_UP E_V4x8BFmode
123 1.1 mrg #define v4x4si_UP E_V4x4SImode
124 1.1 mrg #define v4x4sf_UP E_V4x4SFmode
125 1.1 mrg #define v4x2di_UP E_V4x2DImode
126 1.1 mrg #define v4x2df_UP E_V4x2DFmode
127 1.1 mrg #define UP(X) X##_UP
128 1.1 mrg
129 1.1 mrg #define SIMD_MAX_BUILTIN_ARGS 5
130 1.1 mrg
131 1.1 mrg enum aarch64_type_qualifiers
132 1.1 mrg {
133 1.1 mrg /* T foo. */
134 1.1 mrg qualifier_none = 0x0,
135 1.1 mrg /* unsigned T foo. */
136 1.1 mrg qualifier_unsigned = 0x1, /* 1 << 0 */
137 1.1 mrg /* const T foo. */
138 1.1 mrg qualifier_const = 0x2, /* 1 << 1 */
139 1.1 mrg /* T *foo. */
140 1.1 mrg qualifier_pointer = 0x4, /* 1 << 2 */
141 1.1 mrg /* Used when expanding arguments if an operand could
142 1.1 mrg be an immediate. */
143 1.1 mrg qualifier_immediate = 0x8, /* 1 << 3 */
144 1.1 mrg qualifier_maybe_immediate = 0x10, /* 1 << 4 */
145 1.1 mrg /* void foo (...). */
146 1.1 mrg qualifier_void = 0x20, /* 1 << 5 */
147 1.1 mrg /* Some patterns may have internal operands, this qualifier is an
148 1.1 mrg instruction to the initialisation code to skip this operand. */
149 1.1 mrg qualifier_internal = 0x40, /* 1 << 6 */
150 1.1 mrg /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
151 1.1 mrg rather than using the type of the operand. */
152 1.1 mrg qualifier_map_mode = 0x80, /* 1 << 7 */
153 1.1 mrg /* qualifier_pointer | qualifier_map_mode */
154 1.1 mrg qualifier_pointer_map_mode = 0x84,
155 1.1 mrg /* qualifier_const | qualifier_pointer | qualifier_map_mode */
156 1.1 mrg qualifier_const_pointer_map_mode = 0x86,
157 1.1 mrg /* Polynomial types. */
158 1.1 mrg qualifier_poly = 0x100,
159 1.1 mrg /* Lane indices - must be in range, and flipped for bigendian. */
160 1.1 mrg qualifier_lane_index = 0x200,
161 1.1 mrg /* Lane indices for single lane structure loads and stores. */
162 1.1 mrg qualifier_struct_load_store_lane_index = 0x400,
163 1.1 mrg /* Lane indices selected in pairs. - must be in range, and flipped for
164 1.1 mrg bigendian. */
165 1.1 mrg qualifier_lane_pair_index = 0x800,
166 1.1 mrg /* Lane indices selected in quadtuplets. - must be in range, and flipped for
167 1.1 mrg bigendian. */
168 1.1 mrg qualifier_lane_quadtup_index = 0x1000,
169 1.1 mrg };
170 1.1 mrg
171 1.1 mrg /* Flags that describe what a function might do. */
172 1.1 mrg const unsigned int FLAG_NONE = 0U;
173 1.1 mrg const unsigned int FLAG_READ_FPCR = 1U << 0;
174 1.1 mrg const unsigned int FLAG_RAISE_FP_EXCEPTIONS = 1U << 1;
175 1.1 mrg const unsigned int FLAG_READ_MEMORY = 1U << 2;
176 1.1 mrg const unsigned int FLAG_PREFETCH_MEMORY = 1U << 3;
177 1.1 mrg const unsigned int FLAG_WRITE_MEMORY = 1U << 4;
178 1.1 mrg
179 1.1 mrg /* Not all FP intrinsics raise FP exceptions or read FPCR register,
180 1.1 mrg use this flag to suppress it. */
181 1.1 mrg const unsigned int FLAG_AUTO_FP = 1U << 5;
182 1.1 mrg
183 1.1 mrg const unsigned int FLAG_FP = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS;
184 1.1 mrg const unsigned int FLAG_ALL = FLAG_READ_FPCR | FLAG_RAISE_FP_EXCEPTIONS
185 1.1 mrg | FLAG_READ_MEMORY | FLAG_PREFETCH_MEMORY | FLAG_WRITE_MEMORY;
186 1.1 mrg const unsigned int FLAG_STORE = FLAG_WRITE_MEMORY | FLAG_AUTO_FP;
187 1.1 mrg const unsigned int FLAG_LOAD = FLAG_READ_MEMORY | FLAG_AUTO_FP;
188 1.1 mrg
189 1.1 mrg typedef struct
190 1.1 mrg {
191 1.1 mrg const char *name;
192 1.1 mrg machine_mode mode;
193 1.1 mrg const enum insn_code code;
194 1.1 mrg unsigned int fcode;
195 1.1 mrg enum aarch64_type_qualifiers *qualifiers;
196 1.1 mrg unsigned int flags;
197 1.1 mrg } aarch64_simd_builtin_datum;
198 1.1 mrg
199 1.1 mrg static enum aarch64_type_qualifiers
200 1.1 mrg aarch64_types_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
201 1.1 mrg = { qualifier_none, qualifier_none };
202 1.1 mrg #define TYPES_UNOP (aarch64_types_unop_qualifiers)
203 1.1 mrg static enum aarch64_type_qualifiers
204 1.1 mrg aarch64_types_unopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
205 1.1 mrg = { qualifier_unsigned, qualifier_unsigned };
206 1.1 mrg #define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
207 1.1 mrg static enum aarch64_type_qualifiers
208 1.1 mrg aarch64_types_unopus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
209 1.1 mrg = { qualifier_unsigned, qualifier_none };
210 1.1 mrg #define TYPES_UNOPUS (aarch64_types_unopus_qualifiers)
211 1.1 mrg static enum aarch64_type_qualifiers
212 1.1 mrg aarch64_types_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
213 1.1 mrg = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
214 1.1 mrg #define TYPES_BINOP (aarch64_types_binop_qualifiers)
215 1.1 mrg static enum aarch64_type_qualifiers
216 1.1 mrg aarch64_types_binopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
217 1.1 mrg = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
218 1.1 mrg #define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
219 1.1 mrg static enum aarch64_type_qualifiers
220 1.1 mrg aarch64_types_binop_uus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
221 1.1 mrg = { qualifier_unsigned, qualifier_unsigned, qualifier_none };
222 1.1 mrg #define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
223 1.1 mrg static enum aarch64_type_qualifiers
224 1.1 mrg aarch64_types_binop_ssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
225 1.1 mrg = { qualifier_none, qualifier_none, qualifier_unsigned };
226 1.1 mrg #define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
227 1.1 mrg static enum aarch64_type_qualifiers
228 1.1 mrg aarch64_types_binop_uss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
229 1.1 mrg = { qualifier_unsigned, qualifier_none, qualifier_none };
230 1.1 mrg #define TYPES_BINOP_USS (aarch64_types_binop_uss_qualifiers)
231 1.1 mrg static enum aarch64_type_qualifiers
232 1.1 mrg aarch64_types_binopp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
233 1.1 mrg = { qualifier_poly, qualifier_poly, qualifier_poly };
234 1.1 mrg #define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
235 1.1 mrg static enum aarch64_type_qualifiers
236 1.1 mrg aarch64_types_binop_ppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
237 1.1 mrg = { qualifier_poly, qualifier_poly, qualifier_unsigned };
238 1.1 mrg #define TYPES_BINOP_PPU (aarch64_types_binop_ppu_qualifiers)
239 1.1 mrg
240 1.1 mrg static enum aarch64_type_qualifiers
241 1.1 mrg aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
242 1.1 mrg = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
243 1.1 mrg #define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
244 1.1 mrg static enum aarch64_type_qualifiers
245 1.1 mrg aarch64_types_ternop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
246 1.1 mrg = { qualifier_none, qualifier_none, qualifier_none, qualifier_lane_index };
247 1.1 mrg #define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
248 1.1 mrg static enum aarch64_type_qualifiers
249 1.1 mrg aarch64_types_ternopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
250 1.1 mrg = { qualifier_unsigned, qualifier_unsigned,
251 1.1 mrg qualifier_unsigned, qualifier_unsigned };
252 1.1 mrg #define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
253 1.1 mrg static enum aarch64_type_qualifiers
254 1.1 mrg aarch64_types_ternopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
255 1.1 mrg = { qualifier_unsigned, qualifier_unsigned,
256 1.1 mrg qualifier_unsigned, qualifier_lane_index };
257 1.1 mrg #define TYPES_TERNOPU_LANE (aarch64_types_ternopu_lane_qualifiers)
258 1.1 mrg static enum aarch64_type_qualifiers
259 1.1 mrg aarch64_types_ternopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
260 1.1 mrg = { qualifier_unsigned, qualifier_unsigned,
261 1.1 mrg qualifier_unsigned, qualifier_immediate };
262 1.1 mrg #define TYPES_TERNOPUI (aarch64_types_ternopu_imm_qualifiers)
263 1.1 mrg static enum aarch64_type_qualifiers
264 1.1 mrg aarch64_types_ternop_sssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
265 1.1 mrg = { qualifier_none, qualifier_none, qualifier_none, qualifier_unsigned };
266 1.1 mrg #define TYPES_TERNOP_SSSU (aarch64_types_ternop_sssu_qualifiers)
267 1.1 mrg static enum aarch64_type_qualifiers
268 1.1 mrg aarch64_types_ternop_ssus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
269 1.1 mrg = { qualifier_none, qualifier_none, qualifier_unsigned, qualifier_none };
270 1.1 mrg #define TYPES_TERNOP_SSUS (aarch64_types_ternop_ssus_qualifiers)
271 1.1 mrg static enum aarch64_type_qualifiers
272 1.1 mrg aarch64_types_ternop_suss_qualifiers[SIMD_MAX_BUILTIN_ARGS]
273 1.1 mrg = { qualifier_none, qualifier_unsigned, qualifier_none, qualifier_none };
274 1.1 mrg #define TYPES_TERNOP_SUSS (aarch64_types_ternop_suss_qualifiers)
275 1.1 mrg static enum aarch64_type_qualifiers
276 1.1 mrg aarch64_types_binop_pppu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
277 1.1 mrg = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_unsigned };
278 1.1 mrg #define TYPES_TERNOP_PPPU (aarch64_types_binop_pppu_qualifiers)
279 1.1 mrg
280 1.1 mrg static enum aarch64_type_qualifiers
281 1.1 mrg aarch64_types_quadop_lane_pair_qualifiers[SIMD_MAX_BUILTIN_ARGS]
282 1.1 mrg = { qualifier_none, qualifier_none, qualifier_none,
283 1.1 mrg qualifier_none, qualifier_lane_pair_index };
284 1.1 mrg #define TYPES_QUADOP_LANE_PAIR (aarch64_types_quadop_lane_pair_qualifiers)
285 1.1 mrg static enum aarch64_type_qualifiers
286 1.1 mrg aarch64_types_quadop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
287 1.1 mrg = { qualifier_none, qualifier_none, qualifier_none,
288 1.1 mrg qualifier_none, qualifier_lane_index };
289 1.1 mrg #define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
290 1.1 mrg static enum aarch64_type_qualifiers
291 1.1 mrg aarch64_types_quadopu_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
292 1.1 mrg = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
293 1.1 mrg qualifier_unsigned, qualifier_lane_index };
294 1.1 mrg #define TYPES_QUADOPU_LANE (aarch64_types_quadopu_lane_qualifiers)
295 1.1 mrg
296 1.1 mrg static enum aarch64_type_qualifiers
297 1.1 mrg aarch64_types_quadopssus_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
298 1.1 mrg = { qualifier_none, qualifier_none, qualifier_unsigned,
299 1.1 mrg qualifier_none, qualifier_lane_quadtup_index };
300 1.1 mrg #define TYPES_QUADOPSSUS_LANE_QUADTUP \
301 1.1 mrg (aarch64_types_quadopssus_lane_quadtup_qualifiers)
302 1.1 mrg static enum aarch64_type_qualifiers
303 1.1 mrg aarch64_types_quadopsssu_lane_quadtup_qualifiers[SIMD_MAX_BUILTIN_ARGS]
304 1.1 mrg = { qualifier_none, qualifier_none, qualifier_none,
305 1.1 mrg qualifier_unsigned, qualifier_lane_quadtup_index };
306 1.1 mrg #define TYPES_QUADOPSSSU_LANE_QUADTUP \
307 1.1 mrg (aarch64_types_quadopsssu_lane_quadtup_qualifiers)
308 1.1 mrg
309 1.1 mrg static enum aarch64_type_qualifiers
310 1.1 mrg aarch64_types_quadopu_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
311 1.1 mrg = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
312 1.1 mrg qualifier_unsigned, qualifier_immediate };
313 1.1 mrg #define TYPES_QUADOPUI (aarch64_types_quadopu_imm_qualifiers)
314 1.1 mrg
315 1.1 mrg static enum aarch64_type_qualifiers
316 1.1 mrg aarch64_types_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
317 1.1 mrg = { qualifier_none, qualifier_none, qualifier_immediate };
318 1.1 mrg #define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
319 1.1 mrg #define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
320 1.1 mrg static enum aarch64_type_qualifiers
321 1.1 mrg aarch64_types_shift_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
322 1.1 mrg = { qualifier_unsigned, qualifier_none, qualifier_immediate };
323 1.1 mrg #define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
324 1.1 mrg static enum aarch64_type_qualifiers
325 1.1 mrg aarch64_types_fcvt_from_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
326 1.1 mrg = { qualifier_none, qualifier_unsigned, qualifier_immediate };
327 1.1 mrg #define TYPES_FCVTIMM_SUS (aarch64_types_fcvt_from_unsigned_qualifiers)
328 1.1 mrg static enum aarch64_type_qualifiers
329 1.1 mrg aarch64_types_unsigned_shift_qualifiers[SIMD_MAX_BUILTIN_ARGS]
330 1.1 mrg = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate };
331 1.1 mrg #define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
332 1.1 mrg #define TYPES_USHIFT2IMM (aarch64_types_ternopu_imm_qualifiers)
333 1.1 mrg static enum aarch64_type_qualifiers
334 1.1 mrg aarch64_types_shift2_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
335 1.1 mrg = { qualifier_unsigned, qualifier_unsigned, qualifier_none, qualifier_immediate };
336 1.1 mrg #define TYPES_SHIFT2IMM_UUSS (aarch64_types_shift2_to_unsigned_qualifiers)
337 1.1 mrg
338 1.1 mrg static enum aarch64_type_qualifiers
339 1.1 mrg aarch64_types_ternop_s_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
340 1.1 mrg = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate};
341 1.1 mrg #define TYPES_SETREG (aarch64_types_ternop_s_imm_qualifiers)
342 1.1 mrg #define TYPES_SHIFTINSERT (aarch64_types_ternop_s_imm_qualifiers)
343 1.1 mrg #define TYPES_SHIFTACC (aarch64_types_ternop_s_imm_qualifiers)
344 1.1 mrg #define TYPES_SHIFT2IMM (aarch64_types_ternop_s_imm_qualifiers)
345 1.1 mrg
346 1.1 mrg static enum aarch64_type_qualifiers
347 1.1 mrg aarch64_types_ternop_p_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
348 1.1 mrg = { qualifier_poly, qualifier_poly, qualifier_poly, qualifier_immediate};
349 1.1 mrg #define TYPES_SHIFTINSERTP (aarch64_types_ternop_p_imm_qualifiers)
350 1.1 mrg
351 1.1 mrg static enum aarch64_type_qualifiers
352 1.1 mrg aarch64_types_unsigned_shiftacc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
353 1.1 mrg = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
354 1.1 mrg qualifier_immediate };
355 1.1 mrg #define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
356 1.1 mrg
357 1.1 mrg static enum aarch64_type_qualifiers
358 1.1 mrg aarch64_types_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
359 1.1 mrg = { qualifier_none, qualifier_const_pointer_map_mode };
360 1.1 mrg #define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
361 1.1 mrg #define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
362 1.1 mrg static enum aarch64_type_qualifiers
363 1.1 mrg aarch64_types_load1_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
364 1.1 mrg = { qualifier_unsigned, qualifier_const_pointer_map_mode };
365 1.1 mrg #define TYPES_LOAD1_U (aarch64_types_load1_u_qualifiers)
366 1.1 mrg #define TYPES_LOADSTRUCT_U (aarch64_types_load1_u_qualifiers)
367 1.1 mrg static enum aarch64_type_qualifiers
368 1.1 mrg aarch64_types_load1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
369 1.1 mrg = { qualifier_poly, qualifier_const_pointer_map_mode };
370 1.1 mrg #define TYPES_LOAD1_P (aarch64_types_load1_p_qualifiers)
371 1.1 mrg #define TYPES_LOADSTRUCT_P (aarch64_types_load1_p_qualifiers)
372 1.1 mrg
373 1.1 mrg static enum aarch64_type_qualifiers
374 1.1 mrg aarch64_types_loadstruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
375 1.1 mrg = { qualifier_none, qualifier_const_pointer_map_mode,
376 1.1 mrg qualifier_none, qualifier_struct_load_store_lane_index };
377 1.1 mrg #define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
378 1.1 mrg static enum aarch64_type_qualifiers
379 1.1 mrg aarch64_types_loadstruct_lane_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
380 1.1 mrg = { qualifier_unsigned, qualifier_const_pointer_map_mode,
381 1.1 mrg qualifier_unsigned, qualifier_struct_load_store_lane_index };
382 1.1 mrg #define TYPES_LOADSTRUCT_LANE_U (aarch64_types_loadstruct_lane_u_qualifiers)
383 1.1 mrg static enum aarch64_type_qualifiers
384 1.1 mrg aarch64_types_loadstruct_lane_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
385 1.1 mrg = { qualifier_poly, qualifier_const_pointer_map_mode,
386 1.1 mrg qualifier_poly, qualifier_struct_load_store_lane_index };
387 1.1 mrg #define TYPES_LOADSTRUCT_LANE_P (aarch64_types_loadstruct_lane_p_qualifiers)
388 1.1 mrg
389 1.1 mrg static enum aarch64_type_qualifiers
390 1.1 mrg aarch64_types_bsl_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
391 1.1 mrg = { qualifier_poly, qualifier_unsigned,
392 1.1 mrg qualifier_poly, qualifier_poly };
393 1.1 mrg #define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
394 1.1 mrg static enum aarch64_type_qualifiers
395 1.1 mrg aarch64_types_bsl_s_qualifiers[SIMD_MAX_BUILTIN_ARGS]
396 1.1 mrg = { qualifier_none, qualifier_unsigned,
397 1.1 mrg qualifier_none, qualifier_none };
398 1.1 mrg #define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
399 1.1 mrg static enum aarch64_type_qualifiers
400 1.1 mrg aarch64_types_bsl_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
401 1.1 mrg = { qualifier_unsigned, qualifier_unsigned,
402 1.1 mrg qualifier_unsigned, qualifier_unsigned };
403 1.1 mrg #define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
404 1.1 mrg
405 1.1 mrg /* The first argument (return type) of a store should be void type,
406 1.1 mrg which we represent with qualifier_void. Their first operand will be
407 1.1 mrg a DImode pointer to the location to store to, so we must use
408 1.1 mrg qualifier_map_mode | qualifier_pointer to build a pointer to the
409 1.1 mrg element type of the vector. */
410 1.1 mrg static enum aarch64_type_qualifiers
411 1.1 mrg aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
412 1.1 mrg = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
413 1.1 mrg #define TYPES_STORE1 (aarch64_types_store1_qualifiers)
414 1.1 mrg #define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
415 1.1 mrg static enum aarch64_type_qualifiers
416 1.1 mrg aarch64_types_store1_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
417 1.1 mrg = { qualifier_void, qualifier_pointer_map_mode, qualifier_unsigned };
418 1.1 mrg #define TYPES_STORE1_U (aarch64_types_store1_u_qualifiers)
419 1.1 mrg #define TYPES_STORESTRUCT_U (aarch64_types_store1_u_qualifiers)
420 1.1 mrg static enum aarch64_type_qualifiers
421 1.1 mrg aarch64_types_store1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
422 1.1 mrg = { qualifier_void, qualifier_pointer_map_mode, qualifier_poly };
423 1.1 mrg #define TYPES_STORE1_P (aarch64_types_store1_p_qualifiers)
424 1.1 mrg #define TYPES_STORESTRUCT_P (aarch64_types_store1_p_qualifiers)
425 1.1 mrg
426 1.1 mrg static enum aarch64_type_qualifiers
427 1.1 mrg aarch64_types_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
428 1.1 mrg = { qualifier_void, qualifier_pointer_map_mode,
429 1.1 mrg qualifier_none, qualifier_struct_load_store_lane_index };
430 1.1 mrg #define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
431 1.1 mrg static enum aarch64_type_qualifiers
432 1.1 mrg aarch64_types_storestruct_lane_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
433 1.1 mrg = { qualifier_void, qualifier_pointer_map_mode,
434 1.1 mrg qualifier_unsigned, qualifier_struct_load_store_lane_index };
435 1.1 mrg #define TYPES_STORESTRUCT_LANE_U (aarch64_types_storestruct_lane_u_qualifiers)
436 1.1 mrg static enum aarch64_type_qualifiers
437 1.1 mrg aarch64_types_storestruct_lane_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
438 1.1 mrg = { qualifier_void, qualifier_pointer_map_mode,
439 1.1 mrg qualifier_poly, qualifier_struct_load_store_lane_index };
440 1.1 mrg #define TYPES_STORESTRUCT_LANE_P (aarch64_types_storestruct_lane_p_qualifiers)
441 1.1 mrg
442 1.1 mrg #define CF0(N, X) CODE_FOR_aarch64_##N##X
443 1.1 mrg #define CF1(N, X) CODE_FOR_##N##X##1
444 1.1 mrg #define CF2(N, X) CODE_FOR_##N##X##2
445 1.1 mrg #define CF3(N, X) CODE_FOR_##N##X##3
446 1.1 mrg #define CF4(N, X) CODE_FOR_##N##X##4
447 1.1 mrg #define CF10(N, X) CODE_FOR_##N##X
448 1.1 mrg
449 1.1 mrg #define VAR1(T, N, MAP, FLAG, A) \
450 1.1 mrg {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T, FLAG_##FLAG},
451 1.1 mrg #define VAR2(T, N, MAP, FLAG, A, B) \
452 1.1 mrg VAR1 (T, N, MAP, FLAG, A) \
453 1.1 mrg VAR1 (T, N, MAP, FLAG, B)
454 1.1 mrg #define VAR3(T, N, MAP, FLAG, A, B, C) \
455 1.1 mrg VAR2 (T, N, MAP, FLAG, A, B) \
456 1.1 mrg VAR1 (T, N, MAP, FLAG, C)
457 1.1 mrg #define VAR4(T, N, MAP, FLAG, A, B, C, D) \
458 1.1 mrg VAR3 (T, N, MAP, FLAG, A, B, C) \
459 1.1 mrg VAR1 (T, N, MAP, FLAG, D)
460 1.1 mrg #define VAR5(T, N, MAP, FLAG, A, B, C, D, E) \
461 1.1 mrg VAR4 (T, N, MAP, FLAG, A, B, C, D) \
462 1.1 mrg VAR1 (T, N, MAP, FLAG, E)
463 1.1 mrg #define VAR6(T, N, MAP, FLAG, A, B, C, D, E, F) \
464 1.1 mrg VAR5 (T, N, MAP, FLAG, A, B, C, D, E) \
465 1.1 mrg VAR1 (T, N, MAP, FLAG, F)
466 1.1 mrg #define VAR7(T, N, MAP, FLAG, A, B, C, D, E, F, G) \
467 1.1 mrg VAR6 (T, N, MAP, FLAG, A, B, C, D, E, F) \
468 1.1 mrg VAR1 (T, N, MAP, FLAG, G)
469 1.1 mrg #define VAR8(T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
470 1.1 mrg VAR7 (T, N, MAP, FLAG, A, B, C, D, E, F, G) \
471 1.1 mrg VAR1 (T, N, MAP, FLAG, H)
472 1.1 mrg #define VAR9(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
473 1.1 mrg VAR8 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H) \
474 1.1 mrg VAR1 (T, N, MAP, FLAG, I)
475 1.1 mrg #define VAR10(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
476 1.1 mrg VAR9 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I) \
477 1.1 mrg VAR1 (T, N, MAP, FLAG, J)
478 1.1 mrg #define VAR11(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
479 1.1 mrg VAR10 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J) \
480 1.1 mrg VAR1 (T, N, MAP, FLAG, K)
481 1.1 mrg #define VAR12(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
482 1.1 mrg VAR11 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K) \
483 1.1 mrg VAR1 (T, N, MAP, FLAG, L)
484 1.1 mrg #define VAR13(T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
485 1.1 mrg VAR12 (T, N, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L) \
486 1.1 mrg VAR1 (T, N, MAP, FLAG, M)
487 1.1 mrg #define VAR14(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
488 1.1 mrg VAR13 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M) \
489 1.1 mrg VAR1 (T, X, MAP, FLAG, N)
490 1.1 mrg #define VAR15(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
491 1.1 mrg VAR14 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N) \
492 1.1 mrg VAR1 (T, X, MAP, FLAG, O)
493 1.1 mrg #define VAR16(T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) \
494 1.1 mrg VAR15 (T, X, MAP, FLAG, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) \
495 1.1 mrg VAR1 (T, X, MAP, FLAG, P)
496 1.1 mrg
497 1.1 mrg #include "aarch64-builtin-iterators.h"
498 1.1 mrg
499 1.1 mrg static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
500 1.1 mrg #include "aarch64-simd-builtins.def"
501 1.1 mrg };
502 1.1 mrg
503 1.1 mrg /* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
504 1.1 mrg #define AARCH64_CRC32_BUILTINS \
505 1.1 mrg CRC32_BUILTIN (crc32b, QI) \
506 1.1 mrg CRC32_BUILTIN (crc32h, HI) \
507 1.1 mrg CRC32_BUILTIN (crc32w, SI) \
508 1.1 mrg CRC32_BUILTIN (crc32x, DI) \
509 1.1 mrg CRC32_BUILTIN (crc32cb, QI) \
510 1.1 mrg CRC32_BUILTIN (crc32ch, HI) \
511 1.1 mrg CRC32_BUILTIN (crc32cw, SI) \
512 1.1 mrg CRC32_BUILTIN (crc32cx, DI)
513 1.1 mrg
514 1.1 mrg /* The next 8 FCMLA instrinsics require some special handling compared the
515 1.1 mrg normal simd intrinsics. */
516 1.1 mrg #define AARCH64_SIMD_FCMLA_LANEQ_BUILTINS \
517 1.1 mrg FCMLA_LANEQ_BUILTIN (0, v2sf, fcmla, V2SF, false) \
518 1.1 mrg FCMLA_LANEQ_BUILTIN (90, v2sf, fcmla, V2SF, false) \
519 1.1 mrg FCMLA_LANEQ_BUILTIN (180, v2sf, fcmla, V2SF, false) \
520 1.1 mrg FCMLA_LANEQ_BUILTIN (270, v2sf, fcmla, V2SF, false) \
521 1.1 mrg FCMLA_LANEQ_BUILTIN (0, v4hf, fcmla_laneq, V4HF, true) \
522 1.1 mrg FCMLA_LANEQ_BUILTIN (90, v4hf, fcmla_laneq, V4HF, true) \
523 1.1 mrg FCMLA_LANEQ_BUILTIN (180, v4hf, fcmla_laneq, V4HF, true) \
524 1.1 mrg FCMLA_LANEQ_BUILTIN (270, v4hf, fcmla_laneq, V4HF, true) \
525 1.1 mrg
526 1.1 mrg typedef struct
527 1.1 mrg {
528 1.1 mrg const char *name;
529 1.1 mrg machine_mode mode;
530 1.1 mrg const enum insn_code icode;
531 1.1 mrg unsigned int fcode;
532 1.1 mrg } aarch64_crc_builtin_datum;
533 1.1 mrg
534 1.1 mrg /* Hold information about how to expand the FCMLA_LANEQ builtins. */
535 1.1 mrg typedef struct
536 1.1 mrg {
537 1.1 mrg const char *name;
538 1.1 mrg machine_mode mode;
539 1.1 mrg const enum insn_code icode;
540 1.1 mrg unsigned int fcode;
541 1.1 mrg bool lane;
542 1.1 mrg } aarch64_fcmla_laneq_builtin_datum;
543 1.1 mrg
544 1.1 mrg #define CRC32_BUILTIN(N, M) \
545 1.1 mrg AARCH64_BUILTIN_##N,
546 1.1 mrg
547 1.1 mrg #define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
548 1.1 mrg AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M,
549 1.1 mrg
550 1.1 mrg #undef VAR1
551 1.1 mrg #define VAR1(T, N, MAP, FLAG, A) \
552 1.1 mrg AARCH64_SIMD_BUILTIN_##T##_##N##A,
553 1.1 mrg
554 1.1 mrg enum aarch64_builtins
555 1.1 mrg {
556 1.1 mrg AARCH64_BUILTIN_MIN,
557 1.1 mrg
558 1.1 mrg AARCH64_BUILTIN_GET_FPCR,
559 1.1 mrg AARCH64_BUILTIN_SET_FPCR,
560 1.1 mrg AARCH64_BUILTIN_GET_FPSR,
561 1.1 mrg AARCH64_BUILTIN_SET_FPSR,
562 1.1 mrg
563 1.1 mrg AARCH64_BUILTIN_GET_FPCR64,
564 1.1 mrg AARCH64_BUILTIN_SET_FPCR64,
565 1.1 mrg AARCH64_BUILTIN_GET_FPSR64,
566 1.1 mrg AARCH64_BUILTIN_SET_FPSR64,
567 1.1 mrg
568 1.1 mrg AARCH64_BUILTIN_RSQRT_DF,
569 1.1 mrg AARCH64_BUILTIN_RSQRT_SF,
570 1.1 mrg AARCH64_BUILTIN_RSQRT_V2DF,
571 1.1 mrg AARCH64_BUILTIN_RSQRT_V2SF,
572 1.1 mrg AARCH64_BUILTIN_RSQRT_V4SF,
573 1.1 mrg AARCH64_SIMD_BUILTIN_BASE,
574 1.1 mrg AARCH64_SIMD_BUILTIN_LANE_CHECK,
575 1.1 mrg #include "aarch64-simd-builtins.def"
576 1.1 mrg /* The first enum element which is based on an insn_data pattern. */
577 1.1 mrg AARCH64_SIMD_PATTERN_START = AARCH64_SIMD_BUILTIN_LANE_CHECK + 1,
578 1.1 mrg AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_PATTERN_START
579 1.1 mrg + ARRAY_SIZE (aarch64_simd_builtin_data) - 1,
580 1.1 mrg AARCH64_CRC32_BUILTIN_BASE,
581 1.1 mrg AARCH64_CRC32_BUILTINS
582 1.1 mrg AARCH64_CRC32_BUILTIN_MAX,
583 1.1 mrg /* ARMv8.3-A Pointer Authentication Builtins. */
584 1.1 mrg AARCH64_PAUTH_BUILTIN_AUTIA1716,
585 1.1 mrg AARCH64_PAUTH_BUILTIN_PACIA1716,
586 1.1 mrg AARCH64_PAUTH_BUILTIN_AUTIB1716,
587 1.1 mrg AARCH64_PAUTH_BUILTIN_PACIB1716,
588 1.1 mrg AARCH64_PAUTH_BUILTIN_XPACLRI,
589 1.1 mrg /* Special cased Armv8.3-A Complex FMA by Lane quad Builtins. */
590 1.1 mrg AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE,
591 1.1 mrg AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
592 1.1 mrg /* Builtin for Arm8.3-a Javascript conversion instruction. */
593 1.1 mrg AARCH64_JSCVT,
594 1.1 mrg /* TME builtins. */
595 1.1 mrg AARCH64_TME_BUILTIN_TSTART,
596 1.1 mrg AARCH64_TME_BUILTIN_TCOMMIT,
597 1.1 mrg AARCH64_TME_BUILTIN_TTEST,
598 1.1 mrg AARCH64_TME_BUILTIN_TCANCEL,
599 1.1 mrg /* Armv8.5-a RNG instruction builtins. */
600 1.1 mrg AARCH64_BUILTIN_RNG_RNDR,
601 1.1 mrg AARCH64_BUILTIN_RNG_RNDRRS,
602 1.1 mrg /* MEMTAG builtins. */
603 1.1 mrg AARCH64_MEMTAG_BUILTIN_START,
604 1.1 mrg AARCH64_MEMTAG_BUILTIN_IRG,
605 1.1 mrg AARCH64_MEMTAG_BUILTIN_GMI,
606 1.1 mrg AARCH64_MEMTAG_BUILTIN_SUBP,
607 1.1 mrg AARCH64_MEMTAG_BUILTIN_INC_TAG,
608 1.1 mrg AARCH64_MEMTAG_BUILTIN_SET_TAG,
609 1.1 mrg AARCH64_MEMTAG_BUILTIN_GET_TAG,
610 1.1 mrg AARCH64_MEMTAG_BUILTIN_END,
611 1.1 mrg /* LS64 builtins. */
612 1.1 mrg AARCH64_LS64_BUILTIN_LD64B,
613 1.1 mrg AARCH64_LS64_BUILTIN_ST64B,
614 1.1 mrg AARCH64_LS64_BUILTIN_ST64BV,
615 1.1 mrg AARCH64_LS64_BUILTIN_ST64BV0,
616 1.1 mrg AARCH64_REV16,
617 1.1 mrg AARCH64_REV16L,
618 1.1 mrg AARCH64_REV16LL,
619 1.1 mrg AARCH64_RBIT,
620 1.1 mrg AARCH64_RBITL,
621 1.1 mrg AARCH64_RBITLL,
622 1.1 mrg AARCH64_BUILTIN_MAX
623 1.1 mrg };
624 1.1 mrg
625 1.1 mrg #undef CRC32_BUILTIN
626 1.1 mrg #define CRC32_BUILTIN(N, M) \
627 1.1 mrg {"__builtin_aarch64_"#N, E_##M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
628 1.1 mrg
629 1.1 mrg static aarch64_crc_builtin_datum aarch64_crc_builtin_data[] = {
630 1.1 mrg AARCH64_CRC32_BUILTINS
631 1.1 mrg };
632 1.1 mrg
633 1.1 mrg
634 1.1 mrg #undef FCMLA_LANEQ_BUILTIN
635 1.1 mrg #define FCMLA_LANEQ_BUILTIN(I, N, X, M, T) \
636 1.1 mrg {"__builtin_aarch64_fcmla_laneq"#I#N, E_##M##mode, CODE_FOR_aarch64_##X##I##N, \
637 1.1 mrg AARCH64_SIMD_BUILTIN_FCMLA_LANEQ##I##_##M, T},
638 1.1 mrg
639 1.1 mrg /* This structure contains how to manage the mapping form the builtin to the
640 1.1 mrg instruction to generate in the backend and how to invoke the instruction. */
641 1.1 mrg static aarch64_fcmla_laneq_builtin_datum aarch64_fcmla_lane_builtin_data[] = {
642 1.1 mrg AARCH64_SIMD_FCMLA_LANEQ_BUILTINS
643 1.1 mrg };
644 1.1 mrg
645 1.1 mrg #undef CRC32_BUILTIN
646 1.1 mrg
647 1.1 mrg static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX];
648 1.1 mrg
649 1.1 mrg #define NUM_DREG_TYPES 6
650 1.1 mrg #define NUM_QREG_TYPES 6
651 1.1 mrg
652 1.1 mrg /* Internal scalar builtin types. These types are used to support
653 1.1 mrg neon intrinsic builtins. They are _not_ user-visible types. Therefore
654 1.1 mrg the mangling for these types are implementation defined. */
655 1.1 mrg const char *aarch64_scalar_builtin_types[] = {
656 1.1 mrg "__builtin_aarch64_simd_qi",
657 1.1 mrg "__builtin_aarch64_simd_hi",
658 1.1 mrg "__builtin_aarch64_simd_si",
659 1.1 mrg "__builtin_aarch64_simd_hf",
660 1.1 mrg "__builtin_aarch64_simd_sf",
661 1.1 mrg "__builtin_aarch64_simd_di",
662 1.1 mrg "__builtin_aarch64_simd_df",
663 1.1 mrg "__builtin_aarch64_simd_poly8",
664 1.1 mrg "__builtin_aarch64_simd_poly16",
665 1.1 mrg "__builtin_aarch64_simd_poly64",
666 1.1 mrg "__builtin_aarch64_simd_poly128",
667 1.1 mrg "__builtin_aarch64_simd_ti",
668 1.1 mrg "__builtin_aarch64_simd_uqi",
669 1.1 mrg "__builtin_aarch64_simd_uhi",
670 1.1 mrg "__builtin_aarch64_simd_usi",
671 1.1 mrg "__builtin_aarch64_simd_udi",
672 1.1 mrg "__builtin_aarch64_simd_ei",
673 1.1 mrg "__builtin_aarch64_simd_oi",
674 1.1 mrg "__builtin_aarch64_simd_ci",
675 1.1 mrg "__builtin_aarch64_simd_xi",
676 1.1 mrg "__builtin_aarch64_simd_bf",
677 1.1 mrg NULL
678 1.1 mrg };
679 1.1 mrg
680 1.1 mrg #define ENTRY(E, M, Q, G) E,
681 1.1 mrg enum aarch64_simd_type
682 1.1 mrg {
683 1.1 mrg #include "aarch64-simd-builtin-types.def"
684 1.1 mrg ARM_NEON_H_TYPES_LAST
685 1.1 mrg };
686 1.1 mrg #undef ENTRY
687 1.1 mrg
688 1.1 mrg struct GTY(()) aarch64_simd_type_info
689 1.1 mrg {
690 1.1 mrg enum aarch64_simd_type type;
691 1.1 mrg
692 1.1 mrg /* Internal type name. */
693 1.1 mrg const char *name;
694 1.1 mrg
695 1.1 mrg /* Internal type name(mangled). The mangled names conform to the
696 1.1 mrg AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
697 1.1 mrg Appendix A). To qualify for emission with the mangled names defined in
698 1.1 mrg that document, a vector type must not only be of the correct mode but also
699 1.1 mrg be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
700 1.1 mrg types are registered by aarch64_init_simd_builtin_types (). In other
701 1.1 mrg words, vector types defined in other ways e.g. via vector_size attribute
702 1.1 mrg will get default mangled names. */
703 1.1 mrg const char *mangle;
704 1.1 mrg
705 1.1 mrg /* Internal type. */
706 1.1 mrg tree itype;
707 1.1 mrg
708 1.1 mrg /* Element type. */
709 1.1 mrg tree eltype;
710 1.1 mrg
711 1.1 mrg /* Machine mode the internal type maps to. */
712 1.1 mrg enum machine_mode mode;
713 1.1 mrg
714 1.1 mrg /* Qualifiers. */
715 1.1 mrg enum aarch64_type_qualifiers q;
716 1.1 mrg };
717 1.1 mrg
718 1.1 mrg #define ENTRY(E, M, Q, G) \
719 1.1 mrg {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, E_##M##mode, qualifier_##Q},
720 1.1 mrg static GTY(()) struct aarch64_simd_type_info aarch64_simd_types [] = {
721 1.1 mrg #include "aarch64-simd-builtin-types.def"
722 1.1 mrg };
723 1.1 mrg #undef ENTRY
724 1.1 mrg
725 1.1 mrg static machine_mode aarch64_simd_tuple_modes[ARM_NEON_H_TYPES_LAST][3];
726 1.1 mrg static GTY(()) tree aarch64_simd_tuple_types[ARM_NEON_H_TYPES_LAST][3];
727 1.1 mrg
728 1.1 mrg static GTY(()) tree aarch64_simd_intOI_type_node = NULL_TREE;
729 1.1 mrg static GTY(()) tree aarch64_simd_intCI_type_node = NULL_TREE;
730 1.1 mrg static GTY(()) tree aarch64_simd_intXI_type_node = NULL_TREE;
731 1.1 mrg
732 1.1 mrg /* The user-visible __fp16 type, and a pointer to that type. Used
733 1.1 mrg across the back-end. */
734 1.1 mrg tree aarch64_fp16_type_node = NULL_TREE;
735 1.1 mrg tree aarch64_fp16_ptr_type_node = NULL_TREE;
736 1.1 mrg
737 1.1 mrg /* Back-end node type for brain float (bfloat) types. */
738 1.1 mrg tree aarch64_bf16_type_node = NULL_TREE;
739 1.1 mrg tree aarch64_bf16_ptr_type_node = NULL_TREE;
740 1.1 mrg
741 1.1 mrg /* Wrapper around add_builtin_function. NAME is the name of the built-in
742 1.1 mrg function, TYPE is the function type, CODE is the function subcode
743 1.1 mrg (relative to AARCH64_BUILTIN_GENERAL), and ATTRS is the function
744 1.1 mrg attributes. */
745 1.1 mrg static tree
746 1.1 mrg aarch64_general_add_builtin (const char *name, tree type, unsigned int code,
747 1.1 mrg tree attrs = NULL_TREE)
748 1.1 mrg {
749 1.1 mrg code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
750 1.1 mrg return add_builtin_function (name, type, code, BUILT_IN_MD,
751 1.1 mrg NULL, attrs);
752 1.1 mrg }
753 1.1 mrg
754 1.1 mrg static tree
755 1.1 mrg aarch64_general_simulate_builtin (const char *name, tree fntype,
756 1.1 mrg unsigned int code,
757 1.1 mrg tree attrs = NULL_TREE)
758 1.1 mrg {
759 1.1 mrg code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
760 1.1 mrg return simulate_builtin_function_decl (input_location, name, fntype,
761 1.1 mrg code, NULL, attrs);
762 1.1 mrg }
763 1.1 mrg
764 1.1 mrg static const char *
765 1.1 mrg aarch64_mangle_builtin_scalar_type (const_tree type)
766 1.1 mrg {
767 1.1 mrg int i = 0;
768 1.1 mrg
769 1.1 mrg while (aarch64_scalar_builtin_types[i] != NULL)
770 1.1 mrg {
771 1.1 mrg const char *name = aarch64_scalar_builtin_types[i];
772 1.1 mrg
773 1.1 mrg if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
774 1.1 mrg && DECL_NAME (TYPE_NAME (type))
775 1.1 mrg && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), name))
776 1.1 mrg return aarch64_scalar_builtin_types[i];
777 1.1 mrg i++;
778 1.1 mrg }
779 1.1 mrg return NULL;
780 1.1 mrg }
781 1.1 mrg
782 1.1 mrg static const char *
783 1.1 mrg aarch64_mangle_builtin_vector_type (const_tree type)
784 1.1 mrg {
785 1.1 mrg tree attrs = TYPE_ATTRIBUTES (type);
786 1.1 mrg if (tree attr = lookup_attribute ("Advanced SIMD type", attrs))
787 1.1 mrg {
788 1.1 mrg tree mangled_name = TREE_VALUE (TREE_VALUE (attr));
789 1.1 mrg return IDENTIFIER_POINTER (mangled_name);
790 1.1 mrg }
791 1.1 mrg
792 1.1 mrg return NULL;
793 1.1 mrg }
794 1.1 mrg
795 1.1 mrg const char *
796 1.1 mrg aarch64_general_mangle_builtin_type (const_tree type)
797 1.1 mrg {
798 1.1 mrg const char *mangle;
799 1.1 mrg /* Walk through all the AArch64 builtins types tables to filter out the
800 1.1 mrg incoming type. */
801 1.1 mrg if ((mangle = aarch64_mangle_builtin_vector_type (type))
802 1.1 mrg || (mangle = aarch64_mangle_builtin_scalar_type (type)))
803 1.1 mrg return mangle;
804 1.1 mrg
805 1.1 mrg return NULL;
806 1.1 mrg }
807 1.1 mrg
808 1.1 mrg static tree
809 1.1 mrg aarch64_simd_builtin_std_type (machine_mode mode,
810 1.1 mrg enum aarch64_type_qualifiers q)
811 1.1 mrg {
812 1.1 mrg #define QUAL_TYPE(M) \
813 1.1 mrg ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
814 1.1 mrg switch (mode)
815 1.1 mrg {
816 1.1 mrg case E_QImode:
817 1.1 mrg return QUAL_TYPE (QI);
818 1.1 mrg case E_HImode:
819 1.1 mrg return QUAL_TYPE (HI);
820 1.1 mrg case E_SImode:
821 1.1 mrg return QUAL_TYPE (SI);
822 1.1 mrg case E_DImode:
823 1.1 mrg return QUAL_TYPE (DI);
824 1.1 mrg case E_TImode:
825 1.1 mrg return QUAL_TYPE (TI);
826 1.1 mrg case E_OImode:
827 1.1 mrg return aarch64_simd_intOI_type_node;
828 1.1 mrg case E_CImode:
829 1.1 mrg return aarch64_simd_intCI_type_node;
830 1.1 mrg case E_XImode:
831 1.1 mrg return aarch64_simd_intXI_type_node;
832 1.1 mrg case E_HFmode:
833 1.1 mrg return aarch64_fp16_type_node;
834 1.1 mrg case E_SFmode:
835 1.1 mrg return float_type_node;
836 1.1 mrg case E_DFmode:
837 1.1 mrg return double_type_node;
838 1.1 mrg case E_BFmode:
839 1.1 mrg return aarch64_bf16_type_node;
840 1.1 mrg default:
841 1.1 mrg gcc_unreachable ();
842 1.1 mrg }
843 1.1 mrg #undef QUAL_TYPE
844 1.1 mrg }
845 1.1 mrg
846 1.1 mrg static tree
847 1.1 mrg aarch64_lookup_simd_builtin_type (machine_mode mode,
848 1.1 mrg enum aarch64_type_qualifiers q)
849 1.1 mrg {
850 1.1 mrg int i;
851 1.1 mrg int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
852 1.1 mrg
853 1.1 mrg /* Non-poly scalar modes map to standard types not in the table. */
854 1.1 mrg if (q != qualifier_poly && !VECTOR_MODE_P (mode))
855 1.1 mrg return aarch64_simd_builtin_std_type (mode, q);
856 1.1 mrg
857 1.1 mrg for (i = 0; i < nelts; i++)
858 1.1 mrg {
859 1.1 mrg if (aarch64_simd_types[i].mode == mode
860 1.1 mrg && aarch64_simd_types[i].q == q)
861 1.1 mrg return aarch64_simd_types[i].itype;
862 1.1 mrg if (aarch64_simd_tuple_types[i][0] != NULL_TREE)
863 1.1 mrg for (int j = 0; j < 3; j++)
864 1.1 mrg if (aarch64_simd_tuple_modes[i][j] == mode
865 1.1 mrg && aarch64_simd_types[i].q == q)
866 1.1 mrg return aarch64_simd_tuple_types[i][j];
867 1.1 mrg }
868 1.1 mrg
869 1.1 mrg return NULL_TREE;
870 1.1 mrg }
871 1.1 mrg
872 1.1 mrg static tree
873 1.1 mrg aarch64_simd_builtin_type (machine_mode mode,
874 1.1 mrg bool unsigned_p, bool poly_p)
875 1.1 mrg {
876 1.1 mrg if (poly_p)
877 1.1 mrg return aarch64_lookup_simd_builtin_type (mode, qualifier_poly);
878 1.1 mrg else if (unsigned_p)
879 1.1 mrg return aarch64_lookup_simd_builtin_type (mode, qualifier_unsigned);
880 1.1 mrg else
881 1.1 mrg return aarch64_lookup_simd_builtin_type (mode, qualifier_none);
882 1.1 mrg }
883 1.1 mrg
884 1.1 mrg static void
885 1.1 mrg aarch64_init_simd_builtin_types (void)
886 1.1 mrg {
887 1.1 mrg int i;
888 1.1 mrg int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
889 1.1 mrg tree tdecl;
890 1.1 mrg
891 1.1 mrg /* Init all the element types built by the front-end. */
892 1.1 mrg aarch64_simd_types[Int8x8_t].eltype = intQI_type_node;
893 1.1 mrg aarch64_simd_types[Int8x16_t].eltype = intQI_type_node;
894 1.1 mrg aarch64_simd_types[Int16x4_t].eltype = intHI_type_node;
895 1.1 mrg aarch64_simd_types[Int16x8_t].eltype = intHI_type_node;
896 1.1 mrg aarch64_simd_types[Int32x2_t].eltype = intSI_type_node;
897 1.1 mrg aarch64_simd_types[Int32x4_t].eltype = intSI_type_node;
898 1.1 mrg aarch64_simd_types[Int64x1_t].eltype = intDI_type_node;
899 1.1 mrg aarch64_simd_types[Int64x2_t].eltype = intDI_type_node;
900 1.1 mrg aarch64_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node;
901 1.1 mrg aarch64_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node;
902 1.1 mrg aarch64_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node;
903 1.1 mrg aarch64_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node;
904 1.1 mrg aarch64_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node;
905 1.1 mrg aarch64_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
906 1.1 mrg aarch64_simd_types[Uint64x1_t].eltype = unsigned_intDI_type_node;
907 1.1 mrg aarch64_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
908 1.1 mrg
909 1.1 mrg /* Poly types are a world of their own. */
910 1.1 mrg aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
911 1.1 mrg build_distinct_type_copy (unsigned_intQI_type_node);
912 1.1 mrg /* Prevent front-ends from transforming Poly8_t arrays into string
913 1.1 mrg literals. */
914 1.1 mrg TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
915 1.1 mrg
916 1.1 mrg aarch64_simd_types[Poly16_t].eltype = aarch64_simd_types[Poly16_t].itype =
917 1.1 mrg build_distinct_type_copy (unsigned_intHI_type_node);
918 1.1 mrg aarch64_simd_types[Poly64_t].eltype = aarch64_simd_types[Poly64_t].itype =
919 1.1 mrg build_distinct_type_copy (unsigned_intDI_type_node);
920 1.1 mrg aarch64_simd_types[Poly128_t].eltype = aarch64_simd_types[Poly128_t].itype =
921 1.1 mrg build_distinct_type_copy (unsigned_intTI_type_node);
922 1.1 mrg /* Init poly vector element types with scalar poly types. */
923 1.1 mrg aarch64_simd_types[Poly8x8_t].eltype = aarch64_simd_types[Poly8_t].itype;
924 1.1 mrg aarch64_simd_types[Poly8x16_t].eltype = aarch64_simd_types[Poly8_t].itype;
925 1.1 mrg aarch64_simd_types[Poly16x4_t].eltype = aarch64_simd_types[Poly16_t].itype;
926 1.1 mrg aarch64_simd_types[Poly16x8_t].eltype = aarch64_simd_types[Poly16_t].itype;
927 1.1 mrg aarch64_simd_types[Poly64x1_t].eltype = aarch64_simd_types[Poly64_t].itype;
928 1.1 mrg aarch64_simd_types[Poly64x2_t].eltype = aarch64_simd_types[Poly64_t].itype;
929 1.1 mrg
930 1.1 mrg /* Continue with standard types. */
931 1.1 mrg aarch64_simd_types[Float16x4_t].eltype = aarch64_fp16_type_node;
932 1.1 mrg aarch64_simd_types[Float16x8_t].eltype = aarch64_fp16_type_node;
933 1.1 mrg aarch64_simd_types[Float32x2_t].eltype = float_type_node;
934 1.1 mrg aarch64_simd_types[Float32x4_t].eltype = float_type_node;
935 1.1 mrg aarch64_simd_types[Float64x1_t].eltype = double_type_node;
936 1.1 mrg aarch64_simd_types[Float64x2_t].eltype = double_type_node;
937 1.1 mrg
938 1.1 mrg /* Init Bfloat vector types with underlying __bf16 type. */
939 1.1 mrg aarch64_simd_types[Bfloat16x4_t].eltype = aarch64_bf16_type_node;
940 1.1 mrg aarch64_simd_types[Bfloat16x8_t].eltype = aarch64_bf16_type_node;
941 1.1 mrg
942 1.1 mrg for (i = 0; i < nelts; i++)
943 1.1 mrg {
944 1.1 mrg tree eltype = aarch64_simd_types[i].eltype;
945 1.1 mrg machine_mode mode = aarch64_simd_types[i].mode;
946 1.1 mrg
947 1.1 mrg if (aarch64_simd_types[i].itype == NULL)
948 1.1 mrg {
949 1.1 mrg tree type = build_vector_type (eltype, GET_MODE_NUNITS (mode));
950 1.1 mrg type = build_distinct_type_copy (type);
951 1.1 mrg SET_TYPE_STRUCTURAL_EQUALITY (type);
952 1.1 mrg
953 1.1 mrg tree mangled_name = get_identifier (aarch64_simd_types[i].mangle);
954 1.1 mrg tree value = tree_cons (NULL_TREE, mangled_name, NULL_TREE);
955 1.1 mrg TYPE_ATTRIBUTES (type)
956 1.1 mrg = tree_cons (get_identifier ("Advanced SIMD type"), value,
957 1.1 mrg TYPE_ATTRIBUTES (type));
958 1.1 mrg aarch64_simd_types[i].itype = type;
959 1.1 mrg }
960 1.1 mrg
961 1.1 mrg tdecl = add_builtin_type (aarch64_simd_types[i].name,
962 1.1 mrg aarch64_simd_types[i].itype);
963 1.1 mrg TYPE_NAME (aarch64_simd_types[i].itype) = tdecl;
964 1.1 mrg }
965 1.1 mrg
966 1.1 mrg #define AARCH64_BUILD_SIGNED_TYPE(mode) \
967 1.1 mrg make_signed_type (GET_MODE_PRECISION (mode));
968 1.1 mrg aarch64_simd_intOI_type_node = AARCH64_BUILD_SIGNED_TYPE (OImode);
969 1.1 mrg aarch64_simd_intCI_type_node = AARCH64_BUILD_SIGNED_TYPE (CImode);
970 1.1 mrg aarch64_simd_intXI_type_node = AARCH64_BUILD_SIGNED_TYPE (XImode);
971 1.1 mrg #undef AARCH64_BUILD_SIGNED_TYPE
972 1.1 mrg
973 1.1 mrg tdecl = add_builtin_type
974 1.1 mrg ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node);
975 1.1 mrg TYPE_NAME (aarch64_simd_intOI_type_node) = tdecl;
976 1.1 mrg tdecl = add_builtin_type
977 1.1 mrg ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node);
978 1.1 mrg TYPE_NAME (aarch64_simd_intCI_type_node) = tdecl;
979 1.1 mrg tdecl = add_builtin_type
980 1.1 mrg ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node);
981 1.1 mrg TYPE_NAME (aarch64_simd_intXI_type_node) = tdecl;
982 1.1 mrg }
983 1.1 mrg
984 1.1 mrg static void
985 1.1 mrg aarch64_init_simd_builtin_scalar_types (void)
986 1.1 mrg {
987 1.1 mrg /* Define typedefs for all the standard scalar types. */
988 1.1 mrg (*lang_hooks.types.register_builtin_type) (intQI_type_node,
989 1.1 mrg "__builtin_aarch64_simd_qi");
990 1.1 mrg (*lang_hooks.types.register_builtin_type) (intHI_type_node,
991 1.1 mrg "__builtin_aarch64_simd_hi");
992 1.1 mrg (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node,
993 1.1 mrg "__builtin_aarch64_simd_hf");
994 1.1 mrg (*lang_hooks.types.register_builtin_type) (intSI_type_node,
995 1.1 mrg "__builtin_aarch64_simd_si");
996 1.1 mrg (*lang_hooks.types.register_builtin_type) (float_type_node,
997 1.1 mrg "__builtin_aarch64_simd_sf");
998 1.1 mrg (*lang_hooks.types.register_builtin_type) (intDI_type_node,
999 1.1 mrg "__builtin_aarch64_simd_di");
1000 1.1 mrg (*lang_hooks.types.register_builtin_type) (double_type_node,
1001 1.1 mrg "__builtin_aarch64_simd_df");
1002 1.1 mrg (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
1003 1.1 mrg "__builtin_aarch64_simd_poly8");
1004 1.1 mrg (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
1005 1.1 mrg "__builtin_aarch64_simd_poly16");
1006 1.1 mrg (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
1007 1.1 mrg "__builtin_aarch64_simd_poly64");
1008 1.1 mrg (*lang_hooks.types.register_builtin_type) (unsigned_intTI_type_node,
1009 1.1 mrg "__builtin_aarch64_simd_poly128");
1010 1.1 mrg (*lang_hooks.types.register_builtin_type) (intTI_type_node,
1011 1.1 mrg "__builtin_aarch64_simd_ti");
1012 1.1 mrg (*lang_hooks.types.register_builtin_type) (aarch64_bf16_type_node,
1013 1.1 mrg "__builtin_aarch64_simd_bf");
1014 1.1 mrg /* Unsigned integer types for various mode sizes. */
1015 1.1 mrg (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
1016 1.1 mrg "__builtin_aarch64_simd_uqi");
1017 1.1 mrg (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
1018 1.1 mrg "__builtin_aarch64_simd_uhi");
1019 1.1 mrg (*lang_hooks.types.register_builtin_type) (unsigned_intSI_type_node,
1020 1.1 mrg "__builtin_aarch64_simd_usi");
1021 1.1 mrg (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
1022 1.1 mrg "__builtin_aarch64_simd_udi");
1023 1.1 mrg }
1024 1.1 mrg
1025 1.1 mrg /* Return a set of FLAG_* flags derived from FLAGS
1026 1.1 mrg that describe what a function with result MODE could do,
1027 1.1 mrg taking the command-line flags into account. */
1028 1.1 mrg static unsigned int
1029 1.1 mrg aarch64_call_properties (unsigned int flags, machine_mode mode)
1030 1.1 mrg {
1031 1.1 mrg if (!(flags & FLAG_AUTO_FP) && FLOAT_MODE_P (mode))
1032 1.1 mrg flags |= FLAG_FP;
1033 1.1 mrg
1034 1.1 mrg /* -fno-trapping-math means that we can assume any FP exceptions
1035 1.1 mrg are not user-visible. */
1036 1.1 mrg if (!flag_trapping_math)
1037 1.1 mrg flags &= ~FLAG_RAISE_FP_EXCEPTIONS;
1038 1.1 mrg
1039 1.1 mrg return flags;
1040 1.1 mrg }
1041 1.1 mrg
1042 1.1 mrg /* Return true if calls to a function with flags F and mode MODE
1043 1.1 mrg could modify some form of global state. */
1044 1.1 mrg static bool
1045 1.1 mrg aarch64_modifies_global_state_p (unsigned int f, machine_mode mode)
1046 1.1 mrg {
1047 1.1 mrg unsigned int flags = aarch64_call_properties (f, mode);
1048 1.1 mrg
1049 1.1 mrg if (flags & FLAG_RAISE_FP_EXCEPTIONS)
1050 1.1 mrg return true;
1051 1.1 mrg
1052 1.1 mrg if (flags & FLAG_PREFETCH_MEMORY)
1053 1.1 mrg return true;
1054 1.1 mrg
1055 1.1 mrg return flags & FLAG_WRITE_MEMORY;
1056 1.1 mrg }
1057 1.1 mrg
1058 1.1 mrg /* Return true if calls to a function with flags F and mode MODE
1059 1.1 mrg could read some form of global state. */
1060 1.1 mrg static bool
1061 1.1 mrg aarch64_reads_global_state_p (unsigned int f, machine_mode mode)
1062 1.1 mrg {
1063 1.1 mrg unsigned int flags = aarch64_call_properties (f, mode);
1064 1.1 mrg
1065 1.1 mrg if (flags & FLAG_READ_FPCR)
1066 1.1 mrg return true;
1067 1.1 mrg
1068 1.1 mrg return flags & FLAG_READ_MEMORY;
1069 1.1 mrg }
1070 1.1 mrg
1071 1.1 mrg /* Return true if calls to a function with flags F and mode MODE
1072 1.1 mrg could raise a signal. */
1073 1.1 mrg static bool
1074 1.1 mrg aarch64_could_trap_p (unsigned int f, machine_mode mode)
1075 1.1 mrg {
1076 1.1 mrg unsigned int flags = aarch64_call_properties (f, mode);
1077 1.1 mrg
1078 1.1 mrg if (flags & FLAG_RAISE_FP_EXCEPTIONS)
1079 1.1 mrg return true;
1080 1.1 mrg
1081 1.1 mrg if (flags & (FLAG_READ_MEMORY | FLAG_WRITE_MEMORY))
1082 1.1 mrg return true;
1083 1.1 mrg
1084 1.1 mrg return false;
1085 1.1 mrg }
1086 1.1 mrg
1087 1.1 mrg /* Add attribute NAME to ATTRS. */
1088 1.1 mrg static tree
1089 1.1 mrg aarch64_add_attribute (const char *name, tree attrs)
1090 1.1 mrg {
1091 1.1 mrg return tree_cons (get_identifier (name), NULL_TREE, attrs);
1092 1.1 mrg }
1093 1.1 mrg
1094 1.1 mrg /* Return the appropriate attributes for a function that has
1095 1.1 mrg flags F and mode MODE. */
1096 1.1 mrg static tree
1097 1.1 mrg aarch64_get_attributes (unsigned int f, machine_mode mode)
1098 1.1 mrg {
1099 1.1 mrg tree attrs = NULL_TREE;
1100 1.1 mrg
1101 1.1 mrg if (!aarch64_modifies_global_state_p (f, mode))
1102 1.1 mrg {
1103 1.1 mrg if (aarch64_reads_global_state_p (f, mode))
1104 1.1 mrg attrs = aarch64_add_attribute ("pure", attrs);
1105 1.1 mrg else
1106 1.1 mrg attrs = aarch64_add_attribute ("const", attrs);
1107 1.1 mrg }
1108 1.1 mrg
1109 1.1 mrg if (!flag_non_call_exceptions || !aarch64_could_trap_p (f, mode))
1110 1.1 mrg attrs = aarch64_add_attribute ("nothrow", attrs);
1111 1.1 mrg
1112 1.1 mrg return aarch64_add_attribute ("leaf", attrs);
1113 1.1 mrg }
1114 1.1 mrg
1115 1.1 mrg static bool aarch64_simd_builtins_initialized_p = false;
1116 1.1 mrg
1117 1.1 mrg /* Due to the architecture not providing lane variant of the lane instructions
1118 1.1 mrg for fcmla we can't use the standard simd builtin expansion code, but we
1119 1.1 mrg still want the majority of the validation that would normally be done. */
1120 1.1 mrg
1121 1.1 mrg void
1122 1.1 mrg aarch64_init_fcmla_laneq_builtins (void)
1123 1.1 mrg {
1124 1.1 mrg unsigned int i = 0;
1125 1.1 mrg
1126 1.1 mrg for (i = 0; i < ARRAY_SIZE (aarch64_fcmla_lane_builtin_data); ++i)
1127 1.1 mrg {
1128 1.1 mrg aarch64_fcmla_laneq_builtin_datum* d
1129 1.1 mrg = &aarch64_fcmla_lane_builtin_data[i];
1130 1.1 mrg tree argtype = aarch64_lookup_simd_builtin_type (d->mode, qualifier_none);
1131 1.1 mrg machine_mode quadmode = GET_MODE_2XWIDER_MODE (d->mode).require ();
1132 1.1 mrg tree quadtype
1133 1.1 mrg = aarch64_lookup_simd_builtin_type (quadmode, qualifier_none);
1134 1.1 mrg tree lanetype
1135 1.1 mrg = aarch64_simd_builtin_std_type (SImode, qualifier_lane_pair_index);
1136 1.1 mrg tree ftype = build_function_type_list (argtype, argtype, argtype,
1137 1.1 mrg quadtype, lanetype, NULL_TREE);
1138 1.1 mrg tree attrs = aarch64_get_attributes (FLAG_FP, d->mode);
1139 1.1 mrg tree fndecl
1140 1.1 mrg = aarch64_general_add_builtin (d->name, ftype, d->fcode, attrs);
1141 1.1 mrg
1142 1.1 mrg aarch64_builtin_decls[d->fcode] = fndecl;
1143 1.1 mrg }
1144 1.1 mrg }
1145 1.1 mrg
1146 1.1 mrg void
1147 1.1 mrg aarch64_init_simd_builtin_functions (bool called_from_pragma)
1148 1.1 mrg {
1149 1.1 mrg unsigned int i, fcode = AARCH64_SIMD_PATTERN_START;
1150 1.1 mrg
1151 1.1 mrg if (!called_from_pragma)
1152 1.1 mrg {
1153 1.1 mrg tree lane_check_fpr = build_function_type_list (void_type_node,
1154 1.1 mrg size_type_node,
1155 1.1 mrg size_type_node,
1156 1.1 mrg intSI_type_node,
1157 1.1 mrg NULL);
1158 1.1 mrg aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_LANE_CHECK]
1159 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_im_lane_boundsi",
1160 1.1 mrg lane_check_fpr,
1161 1.1 mrg AARCH64_SIMD_BUILTIN_LANE_CHECK);
1162 1.1 mrg }
1163 1.1 mrg
1164 1.1 mrg for (i = 0; i < ARRAY_SIZE (aarch64_simd_builtin_data); i++, fcode++)
1165 1.1 mrg {
1166 1.1 mrg bool print_type_signature_p = false;
1167 1.1 mrg char type_signature[SIMD_MAX_BUILTIN_ARGS + 1] = { 0 };
1168 1.1 mrg aarch64_simd_builtin_datum *d = &aarch64_simd_builtin_data[i];
1169 1.1 mrg char namebuf[60];
1170 1.1 mrg tree ftype = NULL;
1171 1.1 mrg tree fndecl = NULL;
1172 1.1 mrg
1173 1.1 mrg d->fcode = fcode;
1174 1.1 mrg
1175 1.1 mrg /* We must track two variables here. op_num is
1176 1.1 mrg the operand number as in the RTL pattern. This is
1177 1.1 mrg required to access the mode (e.g. V4SF mode) of the
1178 1.1 mrg argument, from which the base type can be derived.
1179 1.1 mrg arg_num is an index in to the qualifiers data, which
1180 1.1 mrg gives qualifiers to the type (e.g. const unsigned).
1181 1.1 mrg The reason these two variables may differ by one is the
1182 1.1 mrg void return type. While all return types take the 0th entry
1183 1.1 mrg in the qualifiers array, there is no operand for them in the
1184 1.1 mrg RTL pattern. */
1185 1.1 mrg int op_num = insn_data[d->code].n_operands - 1;
1186 1.1 mrg int arg_num = d->qualifiers[0] & qualifier_void
1187 1.1 mrg ? op_num + 1
1188 1.1 mrg : op_num;
1189 1.1 mrg tree return_type = void_type_node, args = void_list_node;
1190 1.1 mrg tree eltype;
1191 1.1 mrg
1192 1.1 mrg int struct_mode_args = 0;
1193 1.1 mrg for (int j = op_num; j >= 0; j--)
1194 1.1 mrg {
1195 1.1 mrg machine_mode op_mode = insn_data[d->code].operand[j].mode;
1196 1.1 mrg if (aarch64_advsimd_struct_mode_p (op_mode))
1197 1.1 mrg struct_mode_args++;
1198 1.1 mrg }
1199 1.1 mrg
1200 1.1 mrg if ((called_from_pragma && struct_mode_args == 0)
1201 1.1 mrg || (!called_from_pragma && struct_mode_args > 0))
1202 1.1 mrg continue;
1203 1.1 mrg
1204 1.1 mrg /* Build a function type directly from the insn_data for this
1205 1.1 mrg builtin. The build_function_type () function takes care of
1206 1.1 mrg removing duplicates for us. */
1207 1.1 mrg for (; op_num >= 0; arg_num--, op_num--)
1208 1.1 mrg {
1209 1.1 mrg machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
1210 1.1 mrg enum aarch64_type_qualifiers qualifiers = d->qualifiers[arg_num];
1211 1.1 mrg
1212 1.1 mrg if (qualifiers & qualifier_unsigned)
1213 1.1 mrg {
1214 1.1 mrg type_signature[op_num] = 'u';
1215 1.1 mrg print_type_signature_p = true;
1216 1.1 mrg }
1217 1.1 mrg else if (qualifiers & qualifier_poly)
1218 1.1 mrg {
1219 1.1 mrg type_signature[op_num] = 'p';
1220 1.1 mrg print_type_signature_p = true;
1221 1.1 mrg }
1222 1.1 mrg else
1223 1.1 mrg type_signature[op_num] = 's';
1224 1.1 mrg
1225 1.1 mrg /* Skip an internal operand for vget_{low, high}. */
1226 1.1 mrg if (qualifiers & qualifier_internal)
1227 1.1 mrg continue;
1228 1.1 mrg
1229 1.1 mrg /* Some builtins have different user-facing types
1230 1.1 mrg for certain arguments, encoded in d->mode. */
1231 1.1 mrg if (qualifiers & qualifier_map_mode)
1232 1.1 mrg op_mode = d->mode;
1233 1.1 mrg
1234 1.1 mrg /* For pointers, we want a pointer to the basic type
1235 1.1 mrg of the vector. */
1236 1.1 mrg if (qualifiers & qualifier_pointer && VECTOR_MODE_P (op_mode))
1237 1.1 mrg op_mode = GET_MODE_INNER (op_mode);
1238 1.1 mrg
1239 1.1 mrg eltype = aarch64_simd_builtin_type
1240 1.1 mrg (op_mode,
1241 1.1 mrg (qualifiers & qualifier_unsigned) != 0,
1242 1.1 mrg (qualifiers & qualifier_poly) != 0);
1243 1.1 mrg gcc_assert (eltype != NULL);
1244 1.1 mrg
1245 1.1 mrg /* Add qualifiers. */
1246 1.1 mrg if (qualifiers & qualifier_const)
1247 1.1 mrg eltype = build_qualified_type (eltype, TYPE_QUAL_CONST);
1248 1.1 mrg
1249 1.1 mrg if (qualifiers & qualifier_pointer)
1250 1.1 mrg eltype = build_pointer_type (eltype);
1251 1.1 mrg
1252 1.1 mrg /* If we have reached arg_num == 0, we are at a non-void
1253 1.1 mrg return type. Otherwise, we are still processing
1254 1.1 mrg arguments. */
1255 1.1 mrg if (arg_num == 0)
1256 1.1 mrg return_type = eltype;
1257 1.1 mrg else
1258 1.1 mrg args = tree_cons (NULL_TREE, eltype, args);
1259 1.1 mrg }
1260 1.1 mrg
1261 1.1 mrg ftype = build_function_type (return_type, args);
1262 1.1 mrg
1263 1.1 mrg gcc_assert (ftype != NULL);
1264 1.1 mrg
1265 1.1 mrg if (print_type_signature_p)
1266 1.1 mrg snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s_%s",
1267 1.1 mrg d->name, type_signature);
1268 1.1 mrg else
1269 1.1 mrg snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s",
1270 1.1 mrg d->name);
1271 1.1 mrg
1272 1.1 mrg tree attrs = aarch64_get_attributes (d->flags, d->mode);
1273 1.1 mrg
1274 1.1 mrg if (called_from_pragma)
1275 1.1 mrg {
1276 1.1 mrg unsigned int raw_code
1277 1.1 mrg = (fcode << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL;
1278 1.1 mrg fndecl = simulate_builtin_function_decl (input_location, namebuf,
1279 1.1 mrg ftype, raw_code, NULL,
1280 1.1 mrg attrs);
1281 1.1 mrg }
1282 1.1 mrg else
1283 1.1 mrg fndecl = aarch64_general_add_builtin (namebuf, ftype, fcode, attrs);
1284 1.1 mrg
1285 1.1 mrg aarch64_builtin_decls[fcode] = fndecl;
1286 1.1 mrg }
1287 1.1 mrg }
1288 1.1 mrg
1289 1.1 mrg /* Register the tuple type that contains NUM_VECTORS of the AdvSIMD type
1290 1.1 mrg indexed by TYPE_INDEX. */
1291 1.1 mrg static void
1292 1.1 mrg register_tuple_type (unsigned int num_vectors, unsigned int type_index)
1293 1.1 mrg {
1294 1.1 mrg aarch64_simd_type_info *type = &aarch64_simd_types[type_index];
1295 1.1 mrg
1296 1.1 mrg /* Synthesize the name of the user-visible vector tuple type. */
1297 1.1 mrg const char *vector_type_name = type->name;
1298 1.1 mrg char tuple_type_name[sizeof ("bfloat16x4x2_t")];
1299 1.1 mrg snprintf (tuple_type_name, sizeof (tuple_type_name), "%.*sx%d_t",
1300 1.1 mrg (int) strlen (vector_type_name) - 4, vector_type_name + 2,
1301 1.1 mrg num_vectors);
1302 1.1 mrg tuple_type_name[0] = TOLOWER (tuple_type_name[0]);
1303 1.1 mrg
1304 1.1 mrg tree vector_type = type->itype;
1305 1.1 mrg tree array_type = build_array_type_nelts (vector_type, num_vectors);
1306 1.1 mrg if (type->mode == DImode)
1307 1.1 mrg {
1308 1.1 mrg if (num_vectors == 2)
1309 1.1 mrg SET_TYPE_MODE (array_type, V2x1DImode);
1310 1.1 mrg else if (num_vectors == 3)
1311 1.1 mrg SET_TYPE_MODE (array_type, V3x1DImode);
1312 1.1 mrg else if (num_vectors == 4)
1313 1.1 mrg SET_TYPE_MODE (array_type, V4x1DImode);
1314 1.1 mrg }
1315 1.1 mrg
1316 1.1 mrg unsigned int alignment
1317 1.1 mrg = known_eq (GET_MODE_SIZE (type->mode), 16) ? 128 : 64;
1318 1.1 mrg machine_mode tuple_mode = TYPE_MODE_RAW (array_type);
1319 1.1 mrg gcc_assert (VECTOR_MODE_P (tuple_mode)
1320 1.1 mrg && TYPE_MODE (array_type) == tuple_mode
1321 1.1 mrg && TYPE_ALIGN (array_type) == alignment);
1322 1.1 mrg
1323 1.1 mrg tree field = build_decl (input_location, FIELD_DECL,
1324 1.1 mrg get_identifier ("val"), array_type);
1325 1.1 mrg
1326 1.1 mrg tree t = lang_hooks.types.simulate_record_decl (input_location,
1327 1.1 mrg tuple_type_name,
1328 1.1 mrg make_array_slice (&field,
1329 1.1 mrg 1));
1330 1.1 mrg gcc_assert (TYPE_MODE_RAW (t) == TYPE_MODE (t)
1331 1.1 mrg && (flag_pack_struct
1332 1.1 mrg || maximum_field_alignment
1333 1.1 mrg || (TYPE_MODE_RAW (t) == tuple_mode
1334 1.1 mrg && TYPE_ALIGN (t) == alignment)));
1335 1.1 mrg
1336 1.1 mrg aarch64_simd_tuple_modes[type_index][num_vectors - 2] = tuple_mode;
1337 1.1 mrg aarch64_simd_tuple_types[type_index][num_vectors - 2] = t;
1338 1.1 mrg }
1339 1.1 mrg
1340 1.1 mrg static bool
1341 1.1 mrg aarch64_scalar_builtin_type_p (aarch64_simd_type t)
1342 1.1 mrg {
1343 1.1 mrg return (t == Poly8_t || t == Poly16_t || t == Poly64_t || t == Poly128_t);
1344 1.1 mrg }
1345 1.1 mrg
1346 1.1 mrg /* Enable AARCH64_FL_* flags EXTRA_FLAGS on top of the base Advanced SIMD
1347 1.1 mrg set. */
1348 1.1 mrg aarch64_simd_switcher::aarch64_simd_switcher (unsigned int extra_flags)
1349 1.1 mrg : m_old_isa_flags (aarch64_isa_flags),
1350 1.1 mrg m_old_general_regs_only (TARGET_GENERAL_REGS_ONLY)
1351 1.1 mrg {
1352 1.1 mrg /* Changing the ISA flags should be enough here. We shouldn't need to
1353 1.1 mrg pay the compile-time cost of a full target switch. */
1354 1.1 mrg aarch64_isa_flags = AARCH64_FL_FP | AARCH64_FL_SIMD | extra_flags;
1355 1.1 mrg global_options.x_target_flags &= ~MASK_GENERAL_REGS_ONLY;
1356 1.1 mrg }
1357 1.1 mrg
1358 1.1 mrg aarch64_simd_switcher::~aarch64_simd_switcher ()
1359 1.1 mrg {
1360 1.1 mrg if (m_old_general_regs_only)
1361 1.1 mrg global_options.x_target_flags |= MASK_GENERAL_REGS_ONLY;
1362 1.1 mrg aarch64_isa_flags = m_old_isa_flags;
1363 1.1 mrg }
1364 1.1 mrg
1365 1.1 mrg /* Implement #pragma GCC aarch64 "arm_neon.h". */
1366 1.1 mrg void
1367 1.1 mrg handle_arm_neon_h (void)
1368 1.1 mrg {
1369 1.1 mrg aarch64_simd_switcher simd;
1370 1.1 mrg
1371 1.1 mrg /* Register the AdvSIMD vector tuple types. */
1372 1.1 mrg for (unsigned int i = 0; i < ARM_NEON_H_TYPES_LAST; i++)
1373 1.1 mrg for (unsigned int count = 2; count <= 4; ++count)
1374 1.1 mrg if (!aarch64_scalar_builtin_type_p (aarch64_simd_types[i].type))
1375 1.1 mrg register_tuple_type (count, i);
1376 1.1 mrg
1377 1.1 mrg aarch64_init_simd_builtin_functions (true);
1378 1.1 mrg }
1379 1.1 mrg
1380 1.1 mrg void
1381 1.1 mrg aarch64_init_simd_builtins (void)
1382 1.1 mrg {
1383 1.1 mrg if (aarch64_simd_builtins_initialized_p)
1384 1.1 mrg return;
1385 1.1 mrg
1386 1.1 mrg aarch64_simd_builtins_initialized_p = true;
1387 1.1 mrg
1388 1.1 mrg aarch64_init_simd_builtin_types ();
1389 1.1 mrg
1390 1.1 mrg /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
1391 1.1 mrg Therefore we need to preserve the old __builtin scalar types. It can be
1392 1.1 mrg removed once all the intrinsics become strongly typed using the qualifier
1393 1.1 mrg system. */
1394 1.1 mrg aarch64_init_simd_builtin_scalar_types ();
1395 1.1 mrg
1396 1.1 mrg aarch64_init_simd_builtin_functions (false);
1397 1.1 mrg if (in_lto_p)
1398 1.1 mrg handle_arm_neon_h ();
1399 1.1 mrg
1400 1.1 mrg /* Initialize the remaining fcmla_laneq intrinsics. */
1401 1.1 mrg aarch64_init_fcmla_laneq_builtins ();
1402 1.1 mrg }
1403 1.1 mrg
1404 1.1 mrg static void
1405 1.1 mrg aarch64_init_crc32_builtins ()
1406 1.1 mrg {
1407 1.1 mrg tree usi_type = aarch64_simd_builtin_std_type (SImode, qualifier_unsigned);
1408 1.1 mrg unsigned int i = 0;
1409 1.1 mrg
1410 1.1 mrg for (i = 0; i < ARRAY_SIZE (aarch64_crc_builtin_data); ++i)
1411 1.1 mrg {
1412 1.1 mrg aarch64_crc_builtin_datum* d = &aarch64_crc_builtin_data[i];
1413 1.1 mrg tree argtype = aarch64_simd_builtin_std_type (d->mode,
1414 1.1 mrg qualifier_unsigned);
1415 1.1 mrg tree ftype = build_function_type_list (usi_type, usi_type, argtype, NULL_TREE);
1416 1.1 mrg tree attrs = aarch64_get_attributes (FLAG_NONE, d->mode);
1417 1.1 mrg tree fndecl
1418 1.1 mrg = aarch64_general_add_builtin (d->name, ftype, d->fcode, attrs);
1419 1.1 mrg
1420 1.1 mrg aarch64_builtin_decls[d->fcode] = fndecl;
1421 1.1 mrg }
1422 1.1 mrg }
1423 1.1 mrg
1424 1.1 mrg /* Add builtins for reciprocal square root. */
1425 1.1 mrg
1426 1.1 mrg void
1427 1.1 mrg aarch64_init_builtin_rsqrt (void)
1428 1.1 mrg {
1429 1.1 mrg tree fndecl = NULL;
1430 1.1 mrg tree ftype = NULL;
1431 1.1 mrg
1432 1.1 mrg tree V2SF_type_node = build_vector_type (float_type_node, 2);
1433 1.1 mrg tree V2DF_type_node = build_vector_type (double_type_node, 2);
1434 1.1 mrg tree V4SF_type_node = build_vector_type (float_type_node, 4);
1435 1.1 mrg
1436 1.1 mrg struct builtin_decls_data
1437 1.1 mrg {
1438 1.1 mrg tree type_node;
1439 1.1 mrg const char *builtin_name;
1440 1.1 mrg int function_code;
1441 1.1 mrg };
1442 1.1 mrg
1443 1.1 mrg builtin_decls_data bdda[] =
1444 1.1 mrg {
1445 1.1 mrg { double_type_node, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF },
1446 1.1 mrg { float_type_node, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF },
1447 1.1 mrg { V2DF_type_node, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF },
1448 1.1 mrg { V2SF_type_node, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF },
1449 1.1 mrg { V4SF_type_node, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF }
1450 1.1 mrg };
1451 1.1 mrg
1452 1.1 mrg builtin_decls_data *bdd = bdda;
1453 1.1 mrg builtin_decls_data *bdd_end = bdd + (sizeof (bdda) / sizeof (builtin_decls_data));
1454 1.1 mrg
1455 1.1 mrg for (; bdd < bdd_end; bdd++)
1456 1.1 mrg {
1457 1.1 mrg ftype = build_function_type_list (bdd->type_node, bdd->type_node, NULL_TREE);
1458 1.1 mrg tree attrs = aarch64_get_attributes (FLAG_FP, TYPE_MODE (bdd->type_node));
1459 1.1 mrg fndecl = aarch64_general_add_builtin (bdd->builtin_name,
1460 1.1 mrg ftype, bdd->function_code, attrs);
1461 1.1 mrg aarch64_builtin_decls[bdd->function_code] = fndecl;
1462 1.1 mrg }
1463 1.1 mrg }
1464 1.1 mrg
1465 1.1 mrg /* Initialize the backend types that support the user-visible __fp16
1466 1.1 mrg type, also initialize a pointer to that type, to be used when
1467 1.1 mrg forming HFAs. */
1468 1.1 mrg
1469 1.1 mrg static void
1470 1.1 mrg aarch64_init_fp16_types (void)
1471 1.1 mrg {
1472 1.1 mrg aarch64_fp16_type_node = make_node (REAL_TYPE);
1473 1.1 mrg TYPE_PRECISION (aarch64_fp16_type_node) = 16;
1474 1.1 mrg layout_type (aarch64_fp16_type_node);
1475 1.1 mrg
1476 1.1 mrg (*lang_hooks.types.register_builtin_type) (aarch64_fp16_type_node, "__fp16");
1477 1.1 mrg aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
1478 1.1 mrg }
1479 1.1 mrg
1480 1.1 mrg /* Initialize the backend REAL_TYPE type supporting bfloat types. */
1481 1.1 mrg static void
1482 1.1 mrg aarch64_init_bf16_types (void)
1483 1.1 mrg {
1484 1.1 mrg aarch64_bf16_type_node = make_node (REAL_TYPE);
1485 1.1 mrg TYPE_PRECISION (aarch64_bf16_type_node) = 16;
1486 1.1 mrg SET_TYPE_MODE (aarch64_bf16_type_node, BFmode);
1487 1.1 mrg layout_type (aarch64_bf16_type_node);
1488 1.1 mrg
1489 1.1 mrg lang_hooks.types.register_builtin_type (aarch64_bf16_type_node, "__bf16");
1490 1.1 mrg aarch64_bf16_ptr_type_node = build_pointer_type (aarch64_bf16_type_node);
1491 1.1 mrg }
1492 1.1 mrg
1493 1.1 mrg /* Pointer authentication builtins that will become NOP on legacy platform.
1494 1.1 mrg Currently, these builtins are for internal use only (libgcc EH unwinder). */
1495 1.1 mrg
1496 1.1 mrg void
1497 1.1 mrg aarch64_init_pauth_hint_builtins (void)
1498 1.1 mrg {
1499 1.1 mrg /* Pointer Authentication builtins. */
1500 1.1 mrg tree ftype_pointer_auth
1501 1.1 mrg = build_function_type_list (ptr_type_node, ptr_type_node,
1502 1.1 mrg unsigned_intDI_type_node, NULL_TREE);
1503 1.1 mrg tree ftype_pointer_strip
1504 1.1 mrg = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
1505 1.1 mrg
1506 1.1 mrg aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
1507 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_autia1716",
1508 1.1 mrg ftype_pointer_auth,
1509 1.1 mrg AARCH64_PAUTH_BUILTIN_AUTIA1716);
1510 1.1 mrg aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIA1716]
1511 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_pacia1716",
1512 1.1 mrg ftype_pointer_auth,
1513 1.1 mrg AARCH64_PAUTH_BUILTIN_PACIA1716);
1514 1.1 mrg aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIB1716]
1515 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_autib1716",
1516 1.1 mrg ftype_pointer_auth,
1517 1.1 mrg AARCH64_PAUTH_BUILTIN_AUTIB1716);
1518 1.1 mrg aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIB1716]
1519 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_pacib1716",
1520 1.1 mrg ftype_pointer_auth,
1521 1.1 mrg AARCH64_PAUTH_BUILTIN_PACIB1716);
1522 1.1 mrg aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
1523 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_xpaclri",
1524 1.1 mrg ftype_pointer_strip,
1525 1.1 mrg AARCH64_PAUTH_BUILTIN_XPACLRI);
1526 1.1 mrg }
1527 1.1 mrg
1528 1.1 mrg /* Initialize the transactional memory extension (TME) builtins. */
1529 1.1 mrg static void
1530 1.1 mrg aarch64_init_tme_builtins (void)
1531 1.1 mrg {
1532 1.1 mrg tree ftype_uint64_void
1533 1.1 mrg = build_function_type_list (uint64_type_node, NULL);
1534 1.1 mrg tree ftype_void_void
1535 1.1 mrg = build_function_type_list (void_type_node, NULL);
1536 1.1 mrg tree ftype_void_uint64
1537 1.1 mrg = build_function_type_list (void_type_node, uint64_type_node, NULL);
1538 1.1 mrg
1539 1.1 mrg aarch64_builtin_decls[AARCH64_TME_BUILTIN_TSTART]
1540 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_tstart",
1541 1.1 mrg ftype_uint64_void,
1542 1.1 mrg AARCH64_TME_BUILTIN_TSTART);
1543 1.1 mrg aarch64_builtin_decls[AARCH64_TME_BUILTIN_TTEST]
1544 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_ttest",
1545 1.1 mrg ftype_uint64_void,
1546 1.1 mrg AARCH64_TME_BUILTIN_TTEST);
1547 1.1 mrg aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCOMMIT]
1548 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_tcommit",
1549 1.1 mrg ftype_void_void,
1550 1.1 mrg AARCH64_TME_BUILTIN_TCOMMIT);
1551 1.1 mrg aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCANCEL]
1552 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_tcancel",
1553 1.1 mrg ftype_void_uint64,
1554 1.1 mrg AARCH64_TME_BUILTIN_TCANCEL);
1555 1.1 mrg }
1556 1.1 mrg
1557 1.1 mrg /* Add builtins for Random Number instructions. */
1558 1.1 mrg
1559 1.1 mrg static void
1560 1.1 mrg aarch64_init_rng_builtins (void)
1561 1.1 mrg {
1562 1.1 mrg tree unsigned_ptr_type = build_pointer_type (unsigned_intDI_type_node);
1563 1.1 mrg tree ftype
1564 1.1 mrg = build_function_type_list (integer_type_node, unsigned_ptr_type, NULL);
1565 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDR]
1566 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_rndr", ftype,
1567 1.1 mrg AARCH64_BUILTIN_RNG_RNDR);
1568 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_RNG_RNDRRS]
1569 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_rndrrs", ftype,
1570 1.1 mrg AARCH64_BUILTIN_RNG_RNDRRS);
1571 1.1 mrg }
1572 1.1 mrg
1573 1.1 mrg /* Initialize the memory tagging extension (MTE) builtins. */
1574 1.1 mrg struct aarch64_mte
1575 1.1 mrg {
1576 1.1 mrg tree ftype;
1577 1.1 mrg enum insn_code icode;
1578 1.1 mrg } aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_END -
1579 1.1 mrg AARCH64_MEMTAG_BUILTIN_START - 1];
1580 1.1 mrg
1581 1.1 mrg static void
1582 1.1 mrg aarch64_init_memtag_builtins (void)
1583 1.1 mrg {
1584 1.1 mrg tree fntype = NULL;
1585 1.1 mrg
1586 1.1 mrg #define AARCH64_INIT_MEMTAG_BUILTINS_DECL(F, N, I, T) \
1587 1.1 mrg aarch64_builtin_decls[AARCH64_MEMTAG_BUILTIN_##F] \
1588 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_memtag_"#N, \
1589 1.1 mrg T, AARCH64_MEMTAG_BUILTIN_##F); \
1590 1.1 mrg aarch64_memtag_builtin_data[AARCH64_MEMTAG_BUILTIN_##F - \
1591 1.1 mrg AARCH64_MEMTAG_BUILTIN_START - 1] = \
1592 1.1 mrg {T, CODE_FOR_##I};
1593 1.1 mrg
1594 1.1 mrg fntype = build_function_type_list (ptr_type_node, ptr_type_node,
1595 1.1 mrg uint64_type_node, NULL);
1596 1.1 mrg AARCH64_INIT_MEMTAG_BUILTINS_DECL (IRG, irg, irg, fntype);
1597 1.1 mrg
1598 1.1 mrg fntype = build_function_type_list (uint64_type_node, ptr_type_node,
1599 1.1 mrg uint64_type_node, NULL);
1600 1.1 mrg AARCH64_INIT_MEMTAG_BUILTINS_DECL (GMI, gmi, gmi, fntype);
1601 1.1 mrg
1602 1.1 mrg fntype = build_function_type_list (ptrdiff_type_node, ptr_type_node,
1603 1.1 mrg ptr_type_node, NULL);
1604 1.1 mrg AARCH64_INIT_MEMTAG_BUILTINS_DECL (SUBP, subp, subp, fntype);
1605 1.1 mrg
1606 1.1 mrg fntype = build_function_type_list (ptr_type_node, ptr_type_node,
1607 1.1 mrg unsigned_type_node, NULL);
1608 1.1 mrg AARCH64_INIT_MEMTAG_BUILTINS_DECL (INC_TAG, inc_tag, addg, fntype);
1609 1.1 mrg
1610 1.1 mrg fntype = build_function_type_list (void_type_node, ptr_type_node, NULL);
1611 1.1 mrg AARCH64_INIT_MEMTAG_BUILTINS_DECL (SET_TAG, set_tag, stg, fntype);
1612 1.1 mrg
1613 1.1 mrg fntype = build_function_type_list (ptr_type_node, ptr_type_node, NULL);
1614 1.1 mrg AARCH64_INIT_MEMTAG_BUILTINS_DECL (GET_TAG, get_tag, ldg, fntype);
1615 1.1 mrg
1616 1.1 mrg #undef AARCH64_INIT_MEMTAG_BUILTINS_DECL
1617 1.1 mrg }
1618 1.1 mrg
1619 1.1 mrg /* Add builtins for Load/store 64 Byte instructions. */
1620 1.1 mrg
1621 1.1 mrg typedef struct
1622 1.1 mrg {
1623 1.1 mrg const char *name;
1624 1.1 mrg unsigned int code;
1625 1.1 mrg tree type;
1626 1.1 mrg } ls64_builtins_data;
1627 1.1 mrg
1628 1.1 mrg static GTY(()) tree ls64_arm_data_t = NULL_TREE;
1629 1.1 mrg
1630 1.1 mrg static void
1631 1.1 mrg aarch64_init_ls64_builtins_types (void)
1632 1.1 mrg {
1633 1.1 mrg /* Synthesize:
1634 1.1 mrg
1635 1.1 mrg typedef struct {
1636 1.1 mrg uint64_t val[8];
1637 1.1 mrg } __arm_data512_t; */
1638 1.1 mrg const char *tuple_type_name = "__arm_data512_t";
1639 1.1 mrg tree node_type = get_typenode_from_name (UINT64_TYPE);
1640 1.1 mrg tree array_type = build_array_type_nelts (node_type, 8);
1641 1.1 mrg SET_TYPE_MODE (array_type, V8DImode);
1642 1.1 mrg
1643 1.1 mrg gcc_assert (TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type));
1644 1.1 mrg gcc_assert (TYPE_ALIGN (array_type) == 64);
1645 1.1 mrg
1646 1.1 mrg tree field = build_decl (input_location, FIELD_DECL,
1647 1.1 mrg get_identifier ("val"), array_type);
1648 1.1 mrg
1649 1.1 mrg ls64_arm_data_t = lang_hooks.types.simulate_record_decl (input_location,
1650 1.1 mrg tuple_type_name,
1651 1.1 mrg make_array_slice (&field, 1));
1652 1.1 mrg
1653 1.1 mrg gcc_assert (TYPE_MODE (ls64_arm_data_t) == V8DImode);
1654 1.1 mrg gcc_assert (TYPE_MODE_RAW (ls64_arm_data_t) == TYPE_MODE (ls64_arm_data_t));
1655 1.1 mrg gcc_assert (TYPE_ALIGN (ls64_arm_data_t) == 64);
1656 1.1 mrg }
1657 1.1 mrg
1658 1.1 mrg static void
1659 1.1 mrg aarch64_init_ls64_builtins (void)
1660 1.1 mrg {
1661 1.1 mrg aarch64_init_ls64_builtins_types ();
1662 1.1 mrg
1663 1.1 mrg ls64_builtins_data data[4] = {
1664 1.1 mrg {"__arm_ld64b", AARCH64_LS64_BUILTIN_LD64B,
1665 1.1 mrg build_function_type_list (ls64_arm_data_t,
1666 1.1 mrg const_ptr_type_node, NULL_TREE)},
1667 1.1 mrg {"__arm_st64b", AARCH64_LS64_BUILTIN_ST64B,
1668 1.1 mrg build_function_type_list (void_type_node, ptr_type_node,
1669 1.1 mrg ls64_arm_data_t, NULL_TREE)},
1670 1.1 mrg {"__arm_st64bv", AARCH64_LS64_BUILTIN_ST64BV,
1671 1.1 mrg build_function_type_list (uint64_type_node, ptr_type_node,
1672 1.1 mrg ls64_arm_data_t, NULL_TREE)},
1673 1.1 mrg {"__arm_st64bv0", AARCH64_LS64_BUILTIN_ST64BV0,
1674 1.1 mrg build_function_type_list (uint64_type_node, ptr_type_node,
1675 1.1 mrg ls64_arm_data_t, NULL_TREE)},
1676 1.1 mrg };
1677 1.1 mrg
1678 1.1 mrg for (size_t i = 0; i < ARRAY_SIZE (data); ++i)
1679 1.1 mrg aarch64_builtin_decls[data[i].code]
1680 1.1 mrg = aarch64_general_simulate_builtin (data[i].name, data[i].type,
1681 1.1 mrg data[i].code);
1682 1.1 mrg }
1683 1.1 mrg
1684 1.1 mrg static void
1685 1.1 mrg aarch64_init_data_intrinsics (void)
1686 1.1 mrg {
1687 1.1 mrg tree uint32_fntype = build_function_type_list (uint32_type_node,
1688 1.1 mrg uint32_type_node, NULL_TREE);
1689 1.1 mrg tree ulong_fntype = build_function_type_list (long_unsigned_type_node,
1690 1.1 mrg long_unsigned_type_node,
1691 1.1 mrg NULL_TREE);
1692 1.1 mrg tree uint64_fntype = build_function_type_list (uint64_type_node,
1693 1.1 mrg uint64_type_node, NULL_TREE);
1694 1.1 mrg aarch64_builtin_decls[AARCH64_REV16]
1695 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_rev16", uint32_fntype,
1696 1.1 mrg AARCH64_REV16);
1697 1.1 mrg aarch64_builtin_decls[AARCH64_REV16L]
1698 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_rev16l", ulong_fntype,
1699 1.1 mrg AARCH64_REV16L);
1700 1.1 mrg aarch64_builtin_decls[AARCH64_REV16LL]
1701 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_rev16ll", uint64_fntype,
1702 1.1 mrg AARCH64_REV16LL);
1703 1.1 mrg aarch64_builtin_decls[AARCH64_RBIT]
1704 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_rbit", uint32_fntype,
1705 1.1 mrg AARCH64_RBIT);
1706 1.1 mrg aarch64_builtin_decls[AARCH64_RBITL]
1707 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_rbitl", ulong_fntype,
1708 1.1 mrg AARCH64_RBITL);
1709 1.1 mrg aarch64_builtin_decls[AARCH64_RBITLL]
1710 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_rbitll", uint64_fntype,
1711 1.1 mrg AARCH64_RBITLL);
1712 1.1 mrg }
1713 1.1 mrg
1714 1.1 mrg /* Implement #pragma GCC aarch64 "arm_acle.h". */
1715 1.1 mrg void
1716 1.1 mrg handle_arm_acle_h (void)
1717 1.1 mrg {
1718 1.1 mrg if (TARGET_LS64)
1719 1.1 mrg aarch64_init_ls64_builtins ();
1720 1.1 mrg }
1721 1.1 mrg
1722 1.1 mrg /* Initialize fpsr fpcr getters and setters. */
1723 1.1 mrg
1724 1.1 mrg static void
1725 1.1 mrg aarch64_init_fpsr_fpcr_builtins (void)
1726 1.1 mrg {
1727 1.1 mrg tree ftype_set
1728 1.1 mrg = build_function_type_list (void_type_node, unsigned_type_node, NULL);
1729 1.1 mrg tree ftype_get
1730 1.1 mrg = build_function_type_list (unsigned_type_node, NULL);
1731 1.1 mrg
1732 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
1733 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr",
1734 1.1 mrg ftype_get,
1735 1.1 mrg AARCH64_BUILTIN_GET_FPCR);
1736 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
1737 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr",
1738 1.1 mrg ftype_set,
1739 1.1 mrg AARCH64_BUILTIN_SET_FPCR);
1740 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
1741 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr",
1742 1.1 mrg ftype_get,
1743 1.1 mrg AARCH64_BUILTIN_GET_FPSR);
1744 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
1745 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr",
1746 1.1 mrg ftype_set,
1747 1.1 mrg AARCH64_BUILTIN_SET_FPSR);
1748 1.1 mrg
1749 1.1 mrg ftype_set
1750 1.1 mrg = build_function_type_list (void_type_node, long_long_unsigned_type_node,
1751 1.1 mrg NULL);
1752 1.1 mrg ftype_get
1753 1.1 mrg = build_function_type_list (long_long_unsigned_type_node, NULL);
1754 1.1 mrg
1755 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR64]
1756 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr64",
1757 1.1 mrg ftype_get,
1758 1.1 mrg AARCH64_BUILTIN_GET_FPCR64);
1759 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR64]
1760 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr64",
1761 1.1 mrg ftype_set,
1762 1.1 mrg AARCH64_BUILTIN_SET_FPCR64);
1763 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR64]
1764 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr64",
1765 1.1 mrg ftype_get,
1766 1.1 mrg AARCH64_BUILTIN_GET_FPSR64);
1767 1.1 mrg aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR64]
1768 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr64",
1769 1.1 mrg ftype_set,
1770 1.1 mrg AARCH64_BUILTIN_SET_FPSR64);
1771 1.1 mrg }
1772 1.1 mrg
1773 1.1 mrg /* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group. */
1774 1.1 mrg
1775 1.1 mrg void
1776 1.1 mrg aarch64_general_init_builtins (void)
1777 1.1 mrg {
1778 1.1 mrg aarch64_init_fpsr_fpcr_builtins ();
1779 1.1 mrg
1780 1.1 mrg aarch64_init_fp16_types ();
1781 1.1 mrg
1782 1.1 mrg aarch64_init_bf16_types ();
1783 1.1 mrg
1784 1.1 mrg {
1785 1.1 mrg aarch64_simd_switcher simd;
1786 1.1 mrg aarch64_init_simd_builtins ();
1787 1.1 mrg }
1788 1.1 mrg
1789 1.1 mrg aarch64_init_crc32_builtins ();
1790 1.1 mrg aarch64_init_builtin_rsqrt ();
1791 1.1 mrg aarch64_init_rng_builtins ();
1792 1.1 mrg aarch64_init_data_intrinsics ();
1793 1.1 mrg
1794 1.1 mrg tree ftype_jcvt
1795 1.1 mrg = build_function_type_list (intSI_type_node, double_type_node, NULL);
1796 1.1 mrg aarch64_builtin_decls[AARCH64_JSCVT]
1797 1.1 mrg = aarch64_general_add_builtin ("__builtin_aarch64_jcvtzs", ftype_jcvt,
1798 1.1 mrg AARCH64_JSCVT);
1799 1.1 mrg
1800 1.1 mrg /* Initialize pointer authentication builtins which are backed by instructions
1801 1.1 mrg in NOP encoding space.
1802 1.1 mrg
1803 1.1 mrg NOTE: these builtins are supposed to be used by libgcc unwinder only, as
1804 1.1 mrg there is no support on return address signing under ILP32, we don't
1805 1.1 mrg register them. */
1806 1.1 mrg if (!TARGET_ILP32)
1807 1.1 mrg aarch64_init_pauth_hint_builtins ();
1808 1.1 mrg
1809 1.1 mrg if (TARGET_TME)
1810 1.1 mrg aarch64_init_tme_builtins ();
1811 1.1 mrg
1812 1.1 mrg if (TARGET_MEMTAG)
1813 1.1 mrg aarch64_init_memtag_builtins ();
1814 1.1 mrg
1815 1.1 mrg if (in_lto_p)
1816 1.1 mrg handle_arm_acle_h ();
1817 1.1 mrg }
1818 1.1 mrg
1819 1.1 mrg /* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group. */
1820 1.1 mrg tree
1821 1.1 mrg aarch64_general_builtin_decl (unsigned code, bool)
1822 1.1 mrg {
1823 1.1 mrg if (code >= AARCH64_BUILTIN_MAX)
1824 1.1 mrg return error_mark_node;
1825 1.1 mrg
1826 1.1 mrg return aarch64_builtin_decls[code];
1827 1.1 mrg }
1828 1.1 mrg
1829 1.1 mrg typedef enum
1830 1.1 mrg {
1831 1.1 mrg SIMD_ARG_COPY_TO_REG,
1832 1.1 mrg SIMD_ARG_CONSTANT,
1833 1.1 mrg SIMD_ARG_LANE_INDEX,
1834 1.1 mrg SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX,
1835 1.1 mrg SIMD_ARG_LANE_PAIR_INDEX,
1836 1.1 mrg SIMD_ARG_LANE_QUADTUP_INDEX,
1837 1.1 mrg SIMD_ARG_STOP
1838 1.1 mrg } builtin_simd_arg;
1839 1.1 mrg
1840 1.1 mrg
1841 1.1 mrg static rtx
1842 1.1 mrg aarch64_simd_expand_args (rtx target, int icode, int have_retval,
1843 1.1 mrg tree exp, builtin_simd_arg *args,
1844 1.1 mrg machine_mode builtin_mode)
1845 1.1 mrg {
1846 1.1 mrg rtx pat;
1847 1.1 mrg rtx op[SIMD_MAX_BUILTIN_ARGS + 1]; /* First element for result operand. */
1848 1.1 mrg int opc = 0;
1849 1.1 mrg
1850 1.1 mrg if (have_retval)
1851 1.1 mrg {
1852 1.1 mrg machine_mode tmode = insn_data[icode].operand[0].mode;
1853 1.1 mrg if (!target
1854 1.1 mrg || GET_MODE (target) != tmode
1855 1.1 mrg || !(*insn_data[icode].operand[0].predicate) (target, tmode))
1856 1.1 mrg target = gen_reg_rtx (tmode);
1857 1.1 mrg op[opc++] = target;
1858 1.1 mrg }
1859 1.1 mrg
1860 1.1 mrg for (;;)
1861 1.1 mrg {
1862 1.1 mrg builtin_simd_arg thisarg = args[opc - have_retval];
1863 1.1 mrg
1864 1.1 mrg if (thisarg == SIMD_ARG_STOP)
1865 1.1 mrg break;
1866 1.1 mrg else
1867 1.1 mrg {
1868 1.1 mrg tree arg = CALL_EXPR_ARG (exp, opc - have_retval);
1869 1.1 mrg machine_mode mode = insn_data[icode].operand[opc].mode;
1870 1.1 mrg op[opc] = expand_normal (arg);
1871 1.1 mrg
1872 1.1 mrg switch (thisarg)
1873 1.1 mrg {
1874 1.1 mrg case SIMD_ARG_COPY_TO_REG:
1875 1.1 mrg if (POINTER_TYPE_P (TREE_TYPE (arg)))
1876 1.1 mrg op[opc] = convert_memory_address (Pmode, op[opc]);
1877 1.1 mrg /*gcc_assert (GET_MODE (op[opc]) == mode); */
1878 1.1 mrg if (!(*insn_data[icode].operand[opc].predicate)
1879 1.1 mrg (op[opc], mode))
1880 1.1 mrg op[opc] = copy_to_mode_reg (mode, op[opc]);
1881 1.1 mrg break;
1882 1.1 mrg
1883 1.1 mrg case SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX:
1884 1.1 mrg gcc_assert (opc > 1);
1885 1.1 mrg if (CONST_INT_P (op[opc]))
1886 1.1 mrg {
1887 1.1 mrg unsigned int nunits
1888 1.1 mrg = GET_MODE_NUNITS (builtin_mode).to_constant ();
1889 1.1 mrg aarch64_simd_lane_bounds (op[opc], 0, nunits, exp);
1890 1.1 mrg /* Keep to GCC-vector-extension lane indices in the RTL. */
1891 1.1 mrg op[opc] = aarch64_endian_lane_rtx (builtin_mode,
1892 1.1 mrg INTVAL (op[opc]));
1893 1.1 mrg }
1894 1.1 mrg goto constant_arg;
1895 1.1 mrg
1896 1.1 mrg case SIMD_ARG_LANE_INDEX:
1897 1.1 mrg /* Must be a previous operand into which this is an index. */
1898 1.1 mrg gcc_assert (opc > 0);
1899 1.1 mrg if (CONST_INT_P (op[opc]))
1900 1.1 mrg {
1901 1.1 mrg machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
1902 1.1 mrg unsigned int nunits
1903 1.1 mrg = GET_MODE_NUNITS (vmode).to_constant ();
1904 1.1 mrg aarch64_simd_lane_bounds (op[opc], 0, nunits, exp);
1905 1.1 mrg /* Keep to GCC-vector-extension lane indices in the RTL. */
1906 1.1 mrg op[opc] = aarch64_endian_lane_rtx (vmode, INTVAL (op[opc]));
1907 1.1 mrg }
1908 1.1 mrg /* If the lane index isn't a constant then error out. */
1909 1.1 mrg goto constant_arg;
1910 1.1 mrg
1911 1.1 mrg case SIMD_ARG_LANE_PAIR_INDEX:
1912 1.1 mrg /* Must be a previous operand into which this is an index and
1913 1.1 mrg index is restricted to nunits / 2. */
1914 1.1 mrg gcc_assert (opc > 0);
1915 1.1 mrg if (CONST_INT_P (op[opc]))
1916 1.1 mrg {
1917 1.1 mrg machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
1918 1.1 mrg unsigned int nunits
1919 1.1 mrg = GET_MODE_NUNITS (vmode).to_constant ();
1920 1.1 mrg aarch64_simd_lane_bounds (op[opc], 0, nunits / 2, exp);
1921 1.1 mrg /* Keep to GCC-vector-extension lane indices in the RTL. */
1922 1.1 mrg int lane = INTVAL (op[opc]);
1923 1.1 mrg op[opc] = gen_int_mode (ENDIAN_LANE_N (nunits / 2, lane),
1924 1.1 mrg SImode);
1925 1.1 mrg }
1926 1.1 mrg /* If the lane index isn't a constant then error out. */
1927 1.1 mrg goto constant_arg;
1928 1.1 mrg case SIMD_ARG_LANE_QUADTUP_INDEX:
1929 1.1 mrg /* Must be a previous operand into which this is an index and
1930 1.1 mrg index is restricted to nunits / 4. */
1931 1.1 mrg gcc_assert (opc > 0);
1932 1.1 mrg if (CONST_INT_P (op[opc]))
1933 1.1 mrg {
1934 1.1 mrg machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
1935 1.1 mrg unsigned int nunits
1936 1.1 mrg = GET_MODE_NUNITS (vmode).to_constant ();
1937 1.1 mrg aarch64_simd_lane_bounds (op[opc], 0, nunits / 4, exp);
1938 1.1 mrg /* Keep to GCC-vector-extension lane indices in the RTL. */
1939 1.1 mrg int lane = INTVAL (op[opc]);
1940 1.1 mrg op[opc] = gen_int_mode (ENDIAN_LANE_N (nunits / 4, lane),
1941 1.1 mrg SImode);
1942 1.1 mrg }
1943 1.1 mrg /* If the lane index isn't a constant then error out. */
1944 1.1 mrg goto constant_arg;
1945 1.1 mrg case SIMD_ARG_CONSTANT:
1946 1.1 mrg constant_arg:
1947 1.1 mrg if (!(*insn_data[icode].operand[opc].predicate)
1948 1.1 mrg (op[opc], mode))
1949 1.1 mrg {
1950 1.1 mrg error_at (EXPR_LOCATION (exp),
1951 1.1 mrg "argument %d must be a constant immediate",
1952 1.1 mrg opc + 1 - have_retval);
1953 1.1 mrg return const0_rtx;
1954 1.1 mrg }
1955 1.1 mrg break;
1956 1.1 mrg
1957 1.1 mrg case SIMD_ARG_STOP:
1958 1.1 mrg gcc_unreachable ();
1959 1.1 mrg }
1960 1.1 mrg
1961 1.1 mrg opc++;
1962 1.1 mrg }
1963 1.1 mrg }
1964 1.1 mrg
1965 1.1 mrg switch (opc)
1966 1.1 mrg {
1967 1.1 mrg case 1:
1968 1.1 mrg pat = GEN_FCN (icode) (op[0]);
1969 1.1 mrg break;
1970 1.1 mrg
1971 1.1 mrg case 2:
1972 1.1 mrg pat = GEN_FCN (icode) (op[0], op[1]);
1973 1.1 mrg break;
1974 1.1 mrg
1975 1.1 mrg case 3:
1976 1.1 mrg pat = GEN_FCN (icode) (op[0], op[1], op[2]);
1977 1.1 mrg break;
1978 1.1 mrg
1979 1.1 mrg case 4:
1980 1.1 mrg pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
1981 1.1 mrg break;
1982 1.1 mrg
1983 1.1 mrg case 5:
1984 1.1 mrg pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
1985 1.1 mrg break;
1986 1.1 mrg
1987 1.1 mrg case 6:
1988 1.1 mrg pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]);
1989 1.1 mrg break;
1990 1.1 mrg
1991 1.1 mrg default:
1992 1.1 mrg gcc_unreachable ();
1993 1.1 mrg }
1994 1.1 mrg
1995 1.1 mrg if (!pat)
1996 1.1 mrg return NULL_RTX;
1997 1.1 mrg
1998 1.1 mrg emit_insn (pat);
1999 1.1 mrg
2000 1.1 mrg return target;
2001 1.1 mrg }
2002 1.1 mrg
2003 1.1 mrg /* Expand an AArch64 AdvSIMD builtin(intrinsic). */
2004 1.1 mrg rtx
2005 1.1 mrg aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
2006 1.1 mrg {
2007 1.1 mrg if (fcode == AARCH64_SIMD_BUILTIN_LANE_CHECK)
2008 1.1 mrg {
2009 1.1 mrg rtx totalsize = expand_normal (CALL_EXPR_ARG (exp, 0));
2010 1.1 mrg rtx elementsize = expand_normal (CALL_EXPR_ARG (exp, 1));
2011 1.1 mrg if (CONST_INT_P (totalsize) && CONST_INT_P (elementsize)
2012 1.1 mrg && UINTVAL (elementsize) != 0
2013 1.1 mrg && UINTVAL (totalsize) != 0)
2014 1.1 mrg {
2015 1.1 mrg rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 2));
2016 1.1 mrg if (CONST_INT_P (lane_idx))
2017 1.1 mrg aarch64_simd_lane_bounds (lane_idx, 0,
2018 1.1 mrg UINTVAL (totalsize)
2019 1.1 mrg / UINTVAL (elementsize),
2020 1.1 mrg exp);
2021 1.1 mrg else
2022 1.1 mrg error_at (EXPR_LOCATION (exp),
2023 1.1 mrg "lane index must be a constant immediate");
2024 1.1 mrg }
2025 1.1 mrg else
2026 1.1 mrg error_at (EXPR_LOCATION (exp),
2027 1.1 mrg "total size and element size must be a nonzero "
2028 1.1 mrg "constant immediate");
2029 1.1 mrg /* Don't generate any RTL. */
2030 1.1 mrg return const0_rtx;
2031 1.1 mrg }
2032 1.1 mrg aarch64_simd_builtin_datum *d =
2033 1.1 mrg &aarch64_simd_builtin_data[fcode - AARCH64_SIMD_PATTERN_START];
2034 1.1 mrg enum insn_code icode = d->code;
2035 1.1 mrg builtin_simd_arg args[SIMD_MAX_BUILTIN_ARGS + 1];
2036 1.1 mrg int num_args = insn_data[d->code].n_operands;
2037 1.1 mrg int is_void = 0;
2038 1.1 mrg int k;
2039 1.1 mrg
2040 1.1 mrg is_void = !!(d->qualifiers[0] & qualifier_void);
2041 1.1 mrg
2042 1.1 mrg num_args += is_void;
2043 1.1 mrg
2044 1.1 mrg for (k = 1; k < num_args; k++)
2045 1.1 mrg {
2046 1.1 mrg /* We have four arrays of data, each indexed in a different fashion.
2047 1.1 mrg qualifiers - element 0 always describes the function return type.
2048 1.1 mrg operands - element 0 is either the operand for return value (if
2049 1.1 mrg the function has a non-void return type) or the operand for the
2050 1.1 mrg first argument.
2051 1.1 mrg expr_args - element 0 always holds the first argument.
2052 1.1 mrg args - element 0 is always used for the return type. */
2053 1.1 mrg int qualifiers_k = k;
2054 1.1 mrg int operands_k = k - is_void;
2055 1.1 mrg int expr_args_k = k - 1;
2056 1.1 mrg
2057 1.1 mrg if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
2058 1.1 mrg args[k] = SIMD_ARG_LANE_INDEX;
2059 1.1 mrg else if (d->qualifiers[qualifiers_k] & qualifier_lane_pair_index)
2060 1.1 mrg args[k] = SIMD_ARG_LANE_PAIR_INDEX;
2061 1.1 mrg else if (d->qualifiers[qualifiers_k] & qualifier_lane_quadtup_index)
2062 1.1 mrg args[k] = SIMD_ARG_LANE_QUADTUP_INDEX;
2063 1.1 mrg else if (d->qualifiers[qualifiers_k] & qualifier_struct_load_store_lane_index)
2064 1.1 mrg args[k] = SIMD_ARG_STRUCT_LOAD_STORE_LANE_INDEX;
2065 1.1 mrg else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
2066 1.1 mrg args[k] = SIMD_ARG_CONSTANT;
2067 1.1 mrg else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
2068 1.1 mrg {
2069 1.1 mrg rtx arg
2070 1.1 mrg = expand_normal (CALL_EXPR_ARG (exp,
2071 1.1 mrg (expr_args_k)));
2072 1.1 mrg /* Handle constants only if the predicate allows it. */
2073 1.1 mrg bool op_const_int_p =
2074 1.1 mrg (CONST_INT_P (arg)
2075 1.1 mrg && (*insn_data[icode].operand[operands_k].predicate)
2076 1.1 mrg (arg, insn_data[icode].operand[operands_k].mode));
2077 1.1 mrg args[k] = op_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG;
2078 1.1 mrg }
2079 1.1 mrg else
2080 1.1 mrg args[k] = SIMD_ARG_COPY_TO_REG;
2081 1.1 mrg
2082 1.1 mrg }
2083 1.1 mrg args[k] = SIMD_ARG_STOP;
2084 1.1 mrg
2085 1.1 mrg /* The interface to aarch64_simd_expand_args expects a 0 if
2086 1.1 mrg the function is void, and a 1 if it is not. */
2087 1.1 mrg return aarch64_simd_expand_args
2088 1.1 mrg (target, icode, !is_void, exp, &args[1], d->mode);
2089 1.1 mrg }
2090 1.1 mrg
2091 1.1 mrg rtx
2092 1.1 mrg aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target)
2093 1.1 mrg {
2094 1.1 mrg rtx pat;
2095 1.1 mrg aarch64_crc_builtin_datum *d
2096 1.1 mrg = &aarch64_crc_builtin_data[fcode - (AARCH64_CRC32_BUILTIN_BASE + 1)];
2097 1.1 mrg enum insn_code icode = d->icode;
2098 1.1 mrg tree arg0 = CALL_EXPR_ARG (exp, 0);
2099 1.1 mrg tree arg1 = CALL_EXPR_ARG (exp, 1);
2100 1.1 mrg rtx op0 = expand_normal (arg0);
2101 1.1 mrg rtx op1 = expand_normal (arg1);
2102 1.1 mrg machine_mode tmode = insn_data[icode].operand[0].mode;
2103 1.1 mrg machine_mode mode0 = insn_data[icode].operand[1].mode;
2104 1.1 mrg machine_mode mode1 = insn_data[icode].operand[2].mode;
2105 1.1 mrg
2106 1.1 mrg if (! target
2107 1.1 mrg || GET_MODE (target) != tmode
2108 1.1 mrg || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
2109 1.1 mrg target = gen_reg_rtx (tmode);
2110 1.1 mrg
2111 1.1 mrg gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
2112 1.1 mrg && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
2113 1.1 mrg
2114 1.1 mrg if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
2115 1.1 mrg op0 = copy_to_mode_reg (mode0, op0);
2116 1.1 mrg if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
2117 1.1 mrg op1 = copy_to_mode_reg (mode1, op1);
2118 1.1 mrg
2119 1.1 mrg pat = GEN_FCN (icode) (target, op0, op1);
2120 1.1 mrg if (!pat)
2121 1.1 mrg return NULL_RTX;
2122 1.1 mrg
2123 1.1 mrg emit_insn (pat);
2124 1.1 mrg return target;
2125 1.1 mrg }
2126 1.1 mrg
2127 1.1 mrg /* Function to expand reciprocal square root builtins. */
2128 1.1 mrg
2129 1.1 mrg static rtx
2130 1.1 mrg aarch64_expand_builtin_rsqrt (int fcode, tree exp, rtx target)
2131 1.1 mrg {
2132 1.1 mrg tree arg0 = CALL_EXPR_ARG (exp, 0);
2133 1.1 mrg rtx op0 = expand_normal (arg0);
2134 1.1 mrg
2135 1.1 mrg rtx (*gen) (rtx, rtx);
2136 1.1 mrg
2137 1.1 mrg switch (fcode)
2138 1.1 mrg {
2139 1.1 mrg case AARCH64_BUILTIN_RSQRT_DF:
2140 1.1 mrg gen = gen_rsqrtdf2;
2141 1.1 mrg break;
2142 1.1 mrg case AARCH64_BUILTIN_RSQRT_SF:
2143 1.1 mrg gen = gen_rsqrtsf2;
2144 1.1 mrg break;
2145 1.1 mrg case AARCH64_BUILTIN_RSQRT_V2DF:
2146 1.1 mrg gen = gen_rsqrtv2df2;
2147 1.1 mrg break;
2148 1.1 mrg case AARCH64_BUILTIN_RSQRT_V2SF:
2149 1.1 mrg gen = gen_rsqrtv2sf2;
2150 1.1 mrg break;
2151 1.1 mrg case AARCH64_BUILTIN_RSQRT_V4SF:
2152 1.1 mrg gen = gen_rsqrtv4sf2;
2153 1.1 mrg break;
2154 1.1 mrg default: gcc_unreachable ();
2155 1.1 mrg }
2156 1.1 mrg
2157 1.1 mrg if (!target)
2158 1.1 mrg target = gen_reg_rtx (GET_MODE (op0));
2159 1.1 mrg
2160 1.1 mrg emit_insn (gen (target, op0));
2161 1.1 mrg
2162 1.1 mrg return target;
2163 1.1 mrg }
2164 1.1 mrg
2165 1.1 mrg /* Expand a FCMLA lane expression EXP with code FCODE and
2166 1.1 mrg result going to TARGET if that is convenient. */
2167 1.1 mrg
2168 1.1 mrg rtx
2169 1.1 mrg aarch64_expand_fcmla_builtin (tree exp, rtx target, int fcode)
2170 1.1 mrg {
2171 1.1 mrg int bcode = fcode - AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE - 1;
2172 1.1 mrg aarch64_fcmla_laneq_builtin_datum* d
2173 1.1 mrg = &aarch64_fcmla_lane_builtin_data[bcode];
2174 1.1 mrg machine_mode quadmode = GET_MODE_2XWIDER_MODE (d->mode).require ();
2175 1.1 mrg rtx op0 = force_reg (d->mode, expand_normal (CALL_EXPR_ARG (exp, 0)));
2176 1.1 mrg rtx op1 = force_reg (d->mode, expand_normal (CALL_EXPR_ARG (exp, 1)));
2177 1.1 mrg rtx op2 = force_reg (quadmode, expand_normal (CALL_EXPR_ARG (exp, 2)));
2178 1.1 mrg tree tmp = CALL_EXPR_ARG (exp, 3);
2179 1.1 mrg rtx lane_idx = expand_expr (tmp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
2180 1.1 mrg
2181 1.1 mrg /* Validate that the lane index is a constant. */
2182 1.1 mrg if (!CONST_INT_P (lane_idx))
2183 1.1 mrg {
2184 1.1 mrg error_at (EXPR_LOCATION (exp),
2185 1.1 mrg "argument %d must be a constant immediate", 4);
2186 1.1 mrg return const0_rtx;
2187 1.1 mrg }
2188 1.1 mrg
2189 1.1 mrg /* Validate that the index is within the expected range. */
2190 1.1 mrg int nunits = GET_MODE_NUNITS (quadmode).to_constant ();
2191 1.1 mrg aarch64_simd_lane_bounds (lane_idx, 0, nunits / 2, exp);
2192 1.1 mrg
2193 1.1 mrg /* Generate the correct register and mode. */
2194 1.1 mrg int lane = INTVAL (lane_idx);
2195 1.1 mrg
2196 1.1 mrg if (lane < nunits / 4)
2197 1.1 mrg op2 = simplify_gen_subreg (d->mode, op2, quadmode,
2198 1.1 mrg subreg_lowpart_offset (d->mode, quadmode));
2199 1.1 mrg else
2200 1.1 mrg {
2201 1.1 mrg /* Select the upper 64 bits, either a V2SF or V4HF, this however
2202 1.1 mrg is quite messy, as the operation required even though simple
2203 1.1 mrg doesn't have a simple RTL pattern, and seems it's quite hard to
2204 1.1 mrg define using a single RTL pattern. The target generic version
2205 1.1 mrg gen_highpart_mode generates code that isn't optimal. */
2206 1.1 mrg rtx temp1 = gen_reg_rtx (d->mode);
2207 1.1 mrg rtx temp2 = gen_reg_rtx (DImode);
2208 1.1 mrg temp1 = simplify_gen_subreg (d->mode, op2, quadmode,
2209 1.1 mrg subreg_lowpart_offset (d->mode, quadmode));
2210 1.1 mrg temp1 = simplify_gen_subreg (V2DImode, temp1, d->mode, 0);
2211 1.1 mrg if (BYTES_BIG_ENDIAN)
2212 1.1 mrg emit_insn (gen_aarch64_get_lanev2di (temp2, temp1, const0_rtx));
2213 1.1 mrg else
2214 1.1 mrg emit_insn (gen_aarch64_get_lanev2di (temp2, temp1, const1_rtx));
2215 1.1 mrg op2 = simplify_gen_subreg (d->mode, temp2, GET_MODE (temp2), 0);
2216 1.1 mrg
2217 1.1 mrg /* And recalculate the index. */
2218 1.1 mrg lane -= nunits / 4;
2219 1.1 mrg }
2220 1.1 mrg
2221 1.1 mrg /* Keep to GCC-vector-extension lane indices in the RTL, only nunits / 4
2222 1.1 mrg (max nunits in range check) are valid. Which means only 0-1, so we
2223 1.1 mrg only need to know the order in a V2mode. */
2224 1.1 mrg lane_idx = aarch64_endian_lane_rtx (V2DImode, lane);
2225 1.1 mrg
2226 1.1 mrg if (!target
2227 1.1 mrg || !REG_P (target)
2228 1.1 mrg || GET_MODE (target) != d->mode)
2229 1.1 mrg target = gen_reg_rtx (d->mode);
2230 1.1 mrg
2231 1.1 mrg rtx pat = NULL_RTX;
2232 1.1 mrg
2233 1.1 mrg if (d->lane)
2234 1.1 mrg pat = GEN_FCN (d->icode) (target, op0, op1, op2, lane_idx);
2235 1.1 mrg else
2236 1.1 mrg pat = GEN_FCN (d->icode) (target, op0, op1, op2);
2237 1.1 mrg
2238 1.1 mrg if (!pat)
2239 1.1 mrg return NULL_RTX;
2240 1.1 mrg
2241 1.1 mrg emit_insn (pat);
2242 1.1 mrg return target;
2243 1.1 mrg }
2244 1.1 mrg
2245 1.1 mrg /* Function to expand an expression EXP which calls one of the Transactional
2246 1.1 mrg Memory Extension (TME) builtins FCODE with the result going to TARGET. */
2247 1.1 mrg static rtx
2248 1.1 mrg aarch64_expand_builtin_tme (int fcode, tree exp, rtx target)
2249 1.1 mrg {
2250 1.1 mrg switch (fcode)
2251 1.1 mrg {
2252 1.1 mrg case AARCH64_TME_BUILTIN_TSTART:
2253 1.1 mrg target = gen_reg_rtx (DImode);
2254 1.1 mrg emit_insn (GEN_FCN (CODE_FOR_tstart) (target));
2255 1.1 mrg break;
2256 1.1 mrg
2257 1.1 mrg case AARCH64_TME_BUILTIN_TTEST:
2258 1.1 mrg target = gen_reg_rtx (DImode);
2259 1.1 mrg emit_insn (GEN_FCN (CODE_FOR_ttest) (target));
2260 1.1 mrg break;
2261 1.1 mrg
2262 1.1 mrg case AARCH64_TME_BUILTIN_TCOMMIT:
2263 1.1 mrg emit_insn (GEN_FCN (CODE_FOR_tcommit) ());
2264 1.1 mrg break;
2265 1.1 mrg
2266 1.1 mrg case AARCH64_TME_BUILTIN_TCANCEL:
2267 1.1 mrg {
2268 1.1 mrg tree arg0 = CALL_EXPR_ARG (exp, 0);
2269 1.1 mrg rtx op0 = expand_normal (arg0);
2270 1.1 mrg if (CONST_INT_P (op0) && UINTVAL (op0) <= 65536)
2271 1.1 mrg emit_insn (GEN_FCN (CODE_FOR_tcancel) (op0));
2272 1.1 mrg else
2273 1.1 mrg {
2274 1.1 mrg error_at (EXPR_LOCATION (exp),
2275 1.1 mrg "argument must be a 16-bit constant immediate");
2276 1.1 mrg return const0_rtx;
2277 1.1 mrg }
2278 1.1 mrg }
2279 1.1 mrg break;
2280 1.1 mrg
2281 1.1 mrg default :
2282 1.1 mrg gcc_unreachable ();
2283 1.1 mrg }
2284 1.1 mrg return target;
2285 1.1 mrg }
2286 1.1 mrg
2287 1.1 mrg /* Function to expand an expression EXP which calls one of the Load/Store
2288 1.1 mrg 64 Byte extension (LS64) builtins FCODE with the result going to TARGET. */
2289 1.1 mrg static rtx
2290 1.1 mrg aarch64_expand_builtin_ls64 (int fcode, tree exp, rtx target)
2291 1.1 mrg {
2292 1.1 mrg expand_operand ops[3];
2293 1.1 mrg
2294 1.1 mrg switch (fcode)
2295 1.1 mrg {
2296 1.1 mrg case AARCH64_LS64_BUILTIN_LD64B:
2297 1.1 mrg {
2298 1.1 mrg rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2299 1.1 mrg create_output_operand (&ops[0], target, V8DImode);
2300 1.1 mrg create_input_operand (&ops[1], op0, DImode);
2301 1.1 mrg expand_insn (CODE_FOR_ld64b, 2, ops);
2302 1.1 mrg return ops[0].value;
2303 1.1 mrg }
2304 1.1 mrg case AARCH64_LS64_BUILTIN_ST64B:
2305 1.1 mrg {
2306 1.1 mrg rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2307 1.1 mrg rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2308 1.1 mrg create_input_operand (&ops[0], op0, DImode);
2309 1.1 mrg create_input_operand (&ops[1], op1, V8DImode);
2310 1.1 mrg expand_insn (CODE_FOR_st64b, 2, ops);
2311 1.1 mrg return const0_rtx;
2312 1.1 mrg }
2313 1.1 mrg case AARCH64_LS64_BUILTIN_ST64BV:
2314 1.1 mrg {
2315 1.1 mrg rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2316 1.1 mrg rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2317 1.1 mrg create_output_operand (&ops[0], target, DImode);
2318 1.1 mrg create_input_operand (&ops[1], op0, DImode);
2319 1.1 mrg create_input_operand (&ops[2], op1, V8DImode);
2320 1.1 mrg expand_insn (CODE_FOR_st64bv, 3, ops);
2321 1.1 mrg return ops[0].value;
2322 1.1 mrg }
2323 1.1 mrg case AARCH64_LS64_BUILTIN_ST64BV0:
2324 1.1 mrg {
2325 1.1 mrg rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2326 1.1 mrg rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2327 1.1 mrg create_output_operand (&ops[0], target, DImode);
2328 1.1 mrg create_input_operand (&ops[1], op0, DImode);
2329 1.1 mrg create_input_operand (&ops[2], op1, V8DImode);
2330 1.1 mrg expand_insn (CODE_FOR_st64bv0, 3, ops);
2331 1.1 mrg return ops[0].value;
2332 1.1 mrg }
2333 1.1 mrg }
2334 1.1 mrg
2335 1.1 mrg gcc_unreachable ();
2336 1.1 mrg }
2337 1.1 mrg
2338 1.1 mrg /* Expand a random number builtin EXP with code FCODE, putting the result
2339 1.1 mrg int TARGET. If IGNORE is true the return value is ignored. */
2340 1.1 mrg
2341 1.1 mrg rtx
2342 1.1 mrg aarch64_expand_rng_builtin (tree exp, rtx target, int fcode, int ignore)
2343 1.1 mrg {
2344 1.1 mrg rtx pat;
2345 1.1 mrg enum insn_code icode;
2346 1.1 mrg if (fcode == AARCH64_BUILTIN_RNG_RNDR)
2347 1.1 mrg icode = CODE_FOR_aarch64_rndr;
2348 1.1 mrg else if (fcode == AARCH64_BUILTIN_RNG_RNDRRS)
2349 1.1 mrg icode = CODE_FOR_aarch64_rndrrs;
2350 1.1 mrg else
2351 1.1 mrg gcc_unreachable ();
2352 1.1 mrg
2353 1.1 mrg rtx rand = gen_reg_rtx (DImode);
2354 1.1 mrg pat = GEN_FCN (icode) (rand);
2355 1.1 mrg if (!pat)
2356 1.1 mrg return NULL_RTX;
2357 1.1 mrg
2358 1.1 mrg tree arg0 = CALL_EXPR_ARG (exp, 0);
2359 1.1 mrg rtx res_addr = expand_normal (arg0);
2360 1.1 mrg res_addr = convert_memory_address (Pmode, res_addr);
2361 1.1 mrg rtx res_mem = gen_rtx_MEM (DImode, res_addr);
2362 1.1 mrg emit_insn (pat);
2363 1.1 mrg emit_move_insn (res_mem, rand);
2364 1.1 mrg /* If the status result is unused don't generate the CSET code. */
2365 1.1 mrg if (ignore)
2366 1.1 mrg return target;
2367 1.1 mrg
2368 1.1 mrg rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
2369 1.1 mrg rtx cmp_rtx = gen_rtx_fmt_ee (EQ, SImode, cc_reg, const0_rtx);
2370 1.1 mrg emit_insn (gen_aarch64_cstoresi (target, cmp_rtx, cc_reg));
2371 1.1 mrg return target;
2372 1.1 mrg }
2373 1.1 mrg
2374 1.1 mrg /* Expand an expression EXP that calls a MEMTAG built-in FCODE
2375 1.1 mrg with result going to TARGET. */
2376 1.1 mrg static rtx
2377 1.1 mrg aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)
2378 1.1 mrg {
2379 1.1 mrg if (TARGET_ILP32)
2380 1.1 mrg {
2381 1.1 mrg error ("Memory Tagging Extension does not support %<-mabi=ilp32%>");
2382 1.1 mrg return const0_rtx;
2383 1.1 mrg }
2384 1.1 mrg
2385 1.1 mrg rtx pat = NULL;
2386 1.1 mrg enum insn_code icode = aarch64_memtag_builtin_data[fcode -
2387 1.1 mrg AARCH64_MEMTAG_BUILTIN_START - 1].icode;
2388 1.1 mrg
2389 1.1 mrg rtx op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2390 1.1 mrg machine_mode mode0 = GET_MODE (op0);
2391 1.1 mrg op0 = force_reg (mode0 == VOIDmode ? DImode : mode0, op0);
2392 1.1 mrg op0 = convert_to_mode (DImode, op0, true);
2393 1.1 mrg
2394 1.1 mrg switch (fcode)
2395 1.1 mrg {
2396 1.1 mrg case AARCH64_MEMTAG_BUILTIN_IRG:
2397 1.1 mrg case AARCH64_MEMTAG_BUILTIN_GMI:
2398 1.1 mrg case AARCH64_MEMTAG_BUILTIN_SUBP:
2399 1.1 mrg case AARCH64_MEMTAG_BUILTIN_INC_TAG:
2400 1.1 mrg {
2401 1.1 mrg if (! target
2402 1.1 mrg || GET_MODE (target) != DImode
2403 1.1 mrg || ! (*insn_data[icode].operand[0].predicate) (target, DImode))
2404 1.1 mrg target = gen_reg_rtx (DImode);
2405 1.1 mrg
2406 1.1 mrg if (fcode == AARCH64_MEMTAG_BUILTIN_INC_TAG)
2407 1.1 mrg {
2408 1.1 mrg rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2409 1.1 mrg
2410 1.1 mrg if ((*insn_data[icode].operand[3].predicate) (op1, QImode))
2411 1.1 mrg {
2412 1.1 mrg pat = GEN_FCN (icode) (target, op0, const0_rtx, op1);
2413 1.1 mrg break;
2414 1.1 mrg }
2415 1.1 mrg error_at (EXPR_LOCATION (exp),
2416 1.1 mrg "argument %d must be a constant immediate "
2417 1.1 mrg "in range [0,15]", 2);
2418 1.1 mrg return const0_rtx;
2419 1.1 mrg }
2420 1.1 mrg else
2421 1.1 mrg {
2422 1.1 mrg rtx op1 = expand_normal (CALL_EXPR_ARG (exp, 1));
2423 1.1 mrg machine_mode mode1 = GET_MODE (op1);
2424 1.1 mrg op1 = force_reg (mode1 == VOIDmode ? DImode : mode1, op1);
2425 1.1 mrg op1 = convert_to_mode (DImode, op1, true);
2426 1.1 mrg pat = GEN_FCN (icode) (target, op0, op1);
2427 1.1 mrg }
2428 1.1 mrg break;
2429 1.1 mrg }
2430 1.1 mrg case AARCH64_MEMTAG_BUILTIN_GET_TAG:
2431 1.1 mrg target = op0;
2432 1.1 mrg pat = GEN_FCN (icode) (target, op0, const0_rtx);
2433 1.1 mrg break;
2434 1.1 mrg case AARCH64_MEMTAG_BUILTIN_SET_TAG:
2435 1.1 mrg pat = GEN_FCN (icode) (op0, op0, const0_rtx);
2436 1.1 mrg break;
2437 1.1 mrg default:
2438 1.1 mrg gcc_unreachable();
2439 1.1 mrg }
2440 1.1 mrg
2441 1.1 mrg if (!pat)
2442 1.1 mrg return NULL_RTX;
2443 1.1 mrg
2444 1.1 mrg emit_insn (pat);
2445 1.1 mrg return target;
2446 1.1 mrg }
2447 1.1 mrg
2448 1.1 mrg /* Function to expand an expression EXP which calls one of the ACLE Data
2449 1.1 mrg Intrinsic builtins FCODE with the result going to TARGET. */
2450 1.1 mrg static rtx
2451 1.1 mrg aarch64_expand_builtin_data_intrinsic (unsigned int fcode, tree exp, rtx target)
2452 1.1 mrg {
2453 1.1 mrg expand_operand ops[2];
2454 1.1 mrg machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
2455 1.1 mrg create_output_operand (&ops[0], target, mode);
2456 1.1 mrg create_input_operand (&ops[1], expand_normal (CALL_EXPR_ARG (exp, 0)), mode);
2457 1.1 mrg enum insn_code icode;
2458 1.1 mrg
2459 1.1 mrg switch (fcode)
2460 1.1 mrg {
2461 1.1 mrg case AARCH64_REV16:
2462 1.1 mrg case AARCH64_REV16L:
2463 1.1 mrg case AARCH64_REV16LL:
2464 1.1 mrg icode = code_for_aarch64_rev16 (mode);
2465 1.1 mrg break;
2466 1.1 mrg case AARCH64_RBIT:
2467 1.1 mrg case AARCH64_RBITL:
2468 1.1 mrg case AARCH64_RBITLL:
2469 1.1 mrg icode = code_for_aarch64_rbit (mode);
2470 1.1 mrg break;
2471 1.1 mrg default:
2472 1.1 mrg gcc_unreachable ();
2473 1.1 mrg }
2474 1.1 mrg
2475 1.1 mrg expand_insn (icode, 2, ops);
2476 1.1 mrg return ops[0].value;
2477 1.1 mrg }
2478 1.1 mrg
2479 1.1 mrg /* Expand an expression EXP as fpsr or fpcr setter (depending on
2480 1.1 mrg UNSPEC) using MODE. */
2481 1.1 mrg static void
2482 1.1 mrg aarch64_expand_fpsr_fpcr_setter (int unspec, machine_mode mode, tree exp)
2483 1.1 mrg {
2484 1.1 mrg tree arg = CALL_EXPR_ARG (exp, 0);
2485 1.1 mrg rtx op = force_reg (mode, expand_normal (arg));
2486 1.1 mrg emit_insn (gen_aarch64_set (unspec, mode, op));
2487 1.1 mrg }
2488 1.1 mrg
2489 1.1 mrg /* Expand a fpsr or fpcr getter (depending on UNSPEC) using MODE.
2490 1.1 mrg Return the target. */
2491 1.1 mrg static rtx
2492 1.1 mrg aarch64_expand_fpsr_fpcr_getter (enum insn_code icode, machine_mode mode,
2493 1.1 mrg rtx target)
2494 1.1 mrg {
2495 1.1 mrg expand_operand op;
2496 1.1 mrg create_output_operand (&op, target, mode);
2497 1.1 mrg expand_insn (icode, 1, &op);
2498 1.1 mrg return op.value;
2499 1.1 mrg }
2500 1.1 mrg
2501 1.1 mrg /* Expand an expression EXP that calls built-in function FCODE,
2502 1.1 mrg with result going to TARGET if that's convenient. IGNORE is true
2503 1.1 mrg if the result of the builtin is ignored. */
2504 1.1 mrg rtx
2505 1.1 mrg aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
2506 1.1 mrg int ignore)
2507 1.1 mrg {
2508 1.1 mrg int icode;
2509 1.1 mrg rtx op0;
2510 1.1 mrg tree arg0;
2511 1.1 mrg
2512 1.1 mrg switch (fcode)
2513 1.1 mrg {
2514 1.1 mrg case AARCH64_BUILTIN_GET_FPCR:
2515 1.1 mrg return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpcrsi,
2516 1.1 mrg SImode, target);
2517 1.1 mrg case AARCH64_BUILTIN_SET_FPCR:
2518 1.1 mrg aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR, SImode, exp);
2519 1.1 mrg return target;
2520 1.1 mrg case AARCH64_BUILTIN_GET_FPSR:
2521 1.1 mrg return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpsrsi,
2522 1.1 mrg SImode, target);
2523 1.1 mrg case AARCH64_BUILTIN_SET_FPSR:
2524 1.1 mrg aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR, SImode, exp);
2525 1.1 mrg return target;
2526 1.1 mrg case AARCH64_BUILTIN_GET_FPCR64:
2527 1.1 mrg return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpcrdi,
2528 1.1 mrg DImode, target);
2529 1.1 mrg case AARCH64_BUILTIN_SET_FPCR64:
2530 1.1 mrg aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPCR, DImode, exp);
2531 1.1 mrg return target;
2532 1.1 mrg case AARCH64_BUILTIN_GET_FPSR64:
2533 1.1 mrg return aarch64_expand_fpsr_fpcr_getter (CODE_FOR_aarch64_get_fpsrdi,
2534 1.1 mrg DImode, target);
2535 1.1 mrg case AARCH64_BUILTIN_SET_FPSR64:
2536 1.1 mrg aarch64_expand_fpsr_fpcr_setter (UNSPECV_SET_FPSR, DImode, exp);
2537 1.1 mrg return target;
2538 1.1 mrg case AARCH64_PAUTH_BUILTIN_AUTIA1716:
2539 1.1 mrg case AARCH64_PAUTH_BUILTIN_PACIA1716:
2540 1.1 mrg case AARCH64_PAUTH_BUILTIN_AUTIB1716:
2541 1.1 mrg case AARCH64_PAUTH_BUILTIN_PACIB1716:
2542 1.1 mrg case AARCH64_PAUTH_BUILTIN_XPACLRI:
2543 1.1 mrg arg0 = CALL_EXPR_ARG (exp, 0);
2544 1.1 mrg op0 = force_reg (Pmode, expand_normal (arg0));
2545 1.1 mrg
2546 1.1 mrg if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
2547 1.1 mrg {
2548 1.1 mrg rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
2549 1.1 mrg icode = CODE_FOR_xpaclri;
2550 1.1 mrg emit_move_insn (lr, op0);
2551 1.1 mrg emit_insn (GEN_FCN (icode) ());
2552 1.1 mrg return lr;
2553 1.1 mrg }
2554 1.1 mrg else
2555 1.1 mrg {
2556 1.1 mrg tree arg1 = CALL_EXPR_ARG (exp, 1);
2557 1.1 mrg rtx op1 = force_reg (Pmode, expand_normal (arg1));
2558 1.1 mrg switch (fcode)
2559 1.1 mrg {
2560 1.1 mrg case AARCH64_PAUTH_BUILTIN_AUTIA1716:
2561 1.1 mrg icode = CODE_FOR_autia1716;
2562 1.1 mrg break;
2563 1.1 mrg case AARCH64_PAUTH_BUILTIN_AUTIB1716:
2564 1.1 mrg icode = CODE_FOR_autib1716;
2565 1.1 mrg break;
2566 1.1 mrg case AARCH64_PAUTH_BUILTIN_PACIA1716:
2567 1.1 mrg icode = CODE_FOR_pacia1716;
2568 1.1 mrg break;
2569 1.1 mrg case AARCH64_PAUTH_BUILTIN_PACIB1716:
2570 1.1 mrg icode = CODE_FOR_pacib1716;
2571 1.1 mrg break;
2572 1.1 mrg default:
2573 1.1 mrg icode = 0;
2574 1.1 mrg gcc_unreachable ();
2575 1.1 mrg }
2576 1.1 mrg
2577 1.1 mrg rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
2578 1.1 mrg rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
2579 1.1 mrg emit_move_insn (x17_reg, op0);
2580 1.1 mrg emit_move_insn (x16_reg, op1);
2581 1.1 mrg emit_insn (GEN_FCN (icode) ());
2582 1.1 mrg return x17_reg;
2583 1.1 mrg }
2584 1.1 mrg
2585 1.1 mrg case AARCH64_JSCVT:
2586 1.1 mrg {
2587 1.1 mrg expand_operand ops[2];
2588 1.1 mrg create_output_operand (&ops[0], target, SImode);
2589 1.1 mrg op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
2590 1.1 mrg create_input_operand (&ops[1], op0, DFmode);
2591 1.1 mrg expand_insn (CODE_FOR_aarch64_fjcvtzs, 2, ops);
2592 1.1 mrg return ops[0].value;
2593 1.1 mrg }
2594 1.1 mrg
2595 1.1 mrg case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V2SF:
2596 1.1 mrg case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V2SF:
2597 1.1 mrg case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V2SF:
2598 1.1 mrg case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V2SF:
2599 1.1 mrg case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V4HF:
2600 1.1 mrg case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V4HF:
2601 1.1 mrg case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V4HF:
2602 1.1 mrg case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ270_V4HF:
2603 1.1 mrg return aarch64_expand_fcmla_builtin (exp, target, fcode);
2604 1.1 mrg case AARCH64_BUILTIN_RNG_RNDR:
2605 1.1 mrg case AARCH64_BUILTIN_RNG_RNDRRS:
2606 1.1 mrg return aarch64_expand_rng_builtin (exp, target, fcode, ignore);
2607 1.1 mrg }
2608 1.1 mrg
2609 1.1 mrg if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
2610 1.1 mrg return aarch64_simd_expand_builtin (fcode, exp, target);
2611 1.1 mrg else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX)
2612 1.1 mrg return aarch64_crc32_expand_builtin (fcode, exp, target);
2613 1.1 mrg
2614 1.1 mrg if (fcode == AARCH64_BUILTIN_RSQRT_DF
2615 1.1 mrg || fcode == AARCH64_BUILTIN_RSQRT_SF
2616 1.1 mrg || fcode == AARCH64_BUILTIN_RSQRT_V2DF
2617 1.1 mrg || fcode == AARCH64_BUILTIN_RSQRT_V2SF
2618 1.1 mrg || fcode == AARCH64_BUILTIN_RSQRT_V4SF)
2619 1.1 mrg return aarch64_expand_builtin_rsqrt (fcode, exp, target);
2620 1.1 mrg
2621 1.1 mrg if (fcode == AARCH64_TME_BUILTIN_TSTART
2622 1.1 mrg || fcode == AARCH64_TME_BUILTIN_TCOMMIT
2623 1.1 mrg || fcode == AARCH64_TME_BUILTIN_TTEST
2624 1.1 mrg || fcode == AARCH64_TME_BUILTIN_TCANCEL)
2625 1.1 mrg return aarch64_expand_builtin_tme (fcode, exp, target);
2626 1.1 mrg
2627 1.1 mrg if (fcode == AARCH64_LS64_BUILTIN_LD64B
2628 1.1 mrg || fcode == AARCH64_LS64_BUILTIN_ST64B
2629 1.1 mrg || fcode == AARCH64_LS64_BUILTIN_ST64BV
2630 1.1 mrg || fcode == AARCH64_LS64_BUILTIN_ST64BV0)
2631 1.1 mrg return aarch64_expand_builtin_ls64 (fcode, exp, target);
2632 1.1 mrg
2633 1.1 mrg if (fcode >= AARCH64_MEMTAG_BUILTIN_START
2634 1.1 mrg && fcode <= AARCH64_MEMTAG_BUILTIN_END)
2635 1.1 mrg return aarch64_expand_builtin_memtag (fcode, exp, target);
2636 1.1 mrg if (fcode >= AARCH64_REV16
2637 1.1 mrg && fcode <= AARCH64_RBITLL)
2638 1.1 mrg return aarch64_expand_builtin_data_intrinsic (fcode, exp, target);
2639 1.1 mrg
2640 1.1 mrg gcc_unreachable ();
2641 1.1 mrg }
2642 1.1 mrg
2643 1.1 mrg tree
2644 1.1 mrg aarch64_builtin_vectorized_function (unsigned int fn, tree type_out,
2645 1.1 mrg tree type_in)
2646 1.1 mrg {
2647 1.1 mrg machine_mode in_mode, out_mode;
2648 1.1 mrg
2649 1.1 mrg if (TREE_CODE (type_out) != VECTOR_TYPE
2650 1.1 mrg || TREE_CODE (type_in) != VECTOR_TYPE)
2651 1.1 mrg return NULL_TREE;
2652 1.1 mrg
2653 1.1 mrg out_mode = TYPE_MODE (type_out);
2654 1.1 mrg in_mode = TYPE_MODE (type_in);
2655 1.1 mrg
2656 1.1 mrg #undef AARCH64_CHECK_BUILTIN_MODE
2657 1.1 mrg #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
2658 1.1 mrg #define AARCH64_FIND_FRINT_VARIANT(N) \
2659 1.1 mrg (AARCH64_CHECK_BUILTIN_MODE (2, D) \
2660 1.1 mrg ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
2661 1.1 mrg : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
2662 1.1 mrg ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
2663 1.1 mrg : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
2664 1.1 mrg ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
2665 1.1 mrg : NULL_TREE)))
2666 1.1 mrg switch (fn)
2667 1.1 mrg {
2668 1.1 mrg #undef AARCH64_CHECK_BUILTIN_MODE
2669 1.1 mrg #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
2670 1.1 mrg (out_mode == V##C##N##Fmode && in_mode == V##C##N##Fmode)
2671 1.1 mrg CASE_CFN_FLOOR:
2672 1.1 mrg return AARCH64_FIND_FRINT_VARIANT (floor);
2673 1.1 mrg CASE_CFN_CEIL:
2674 1.1 mrg return AARCH64_FIND_FRINT_VARIANT (ceil);
2675 1.1 mrg CASE_CFN_TRUNC:
2676 1.1 mrg return AARCH64_FIND_FRINT_VARIANT (btrunc);
2677 1.1 mrg CASE_CFN_ROUND:
2678 1.1 mrg return AARCH64_FIND_FRINT_VARIANT (round);
2679 1.1 mrg CASE_CFN_NEARBYINT:
2680 1.1 mrg return AARCH64_FIND_FRINT_VARIANT (nearbyint);
2681 1.1 mrg CASE_CFN_SQRT:
2682 1.1 mrg return AARCH64_FIND_FRINT_VARIANT (sqrt);
2683 1.1 mrg #undef AARCH64_CHECK_BUILTIN_MODE
2684 1.1 mrg #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
2685 1.1 mrg (out_mode == V##C##SImode && in_mode == V##C##N##Imode)
2686 1.1 mrg CASE_CFN_CLZ:
2687 1.1 mrg {
2688 1.1 mrg if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2689 1.1 mrg return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_clzv4si];
2690 1.1 mrg return NULL_TREE;
2691 1.1 mrg }
2692 1.1 mrg CASE_CFN_CTZ:
2693 1.1 mrg {
2694 1.1 mrg if (AARCH64_CHECK_BUILTIN_MODE (2, S))
2695 1.1 mrg return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si];
2696 1.1 mrg else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2697 1.1 mrg return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si];
2698 1.1 mrg return NULL_TREE;
2699 1.1 mrg }
2700 1.1 mrg #undef AARCH64_CHECK_BUILTIN_MODE
2701 1.1 mrg #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
2702 1.1 mrg (out_mode == V##C##N##Imode && in_mode == V##C##N##Fmode)
2703 1.1 mrg CASE_CFN_IFLOOR:
2704 1.1 mrg CASE_CFN_LFLOOR:
2705 1.1 mrg CASE_CFN_LLFLOOR:
2706 1.1 mrg {
2707 1.1 mrg enum aarch64_builtins builtin;
2708 1.1 mrg if (AARCH64_CHECK_BUILTIN_MODE (2, D))
2709 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di;
2710 1.1 mrg else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2711 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si;
2712 1.1 mrg else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
2713 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si;
2714 1.1 mrg else
2715 1.1 mrg return NULL_TREE;
2716 1.1 mrg
2717 1.1 mrg return aarch64_builtin_decls[builtin];
2718 1.1 mrg }
2719 1.1 mrg CASE_CFN_ICEIL:
2720 1.1 mrg CASE_CFN_LCEIL:
2721 1.1 mrg CASE_CFN_LLCEIL:
2722 1.1 mrg {
2723 1.1 mrg enum aarch64_builtins builtin;
2724 1.1 mrg if (AARCH64_CHECK_BUILTIN_MODE (2, D))
2725 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di;
2726 1.1 mrg else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2727 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si;
2728 1.1 mrg else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
2729 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si;
2730 1.1 mrg else
2731 1.1 mrg return NULL_TREE;
2732 1.1 mrg
2733 1.1 mrg return aarch64_builtin_decls[builtin];
2734 1.1 mrg }
2735 1.1 mrg CASE_CFN_IROUND:
2736 1.1 mrg CASE_CFN_LROUND:
2737 1.1 mrg CASE_CFN_LLROUND:
2738 1.1 mrg {
2739 1.1 mrg enum aarch64_builtins builtin;
2740 1.1 mrg if (AARCH64_CHECK_BUILTIN_MODE (2, D))
2741 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di;
2742 1.1 mrg else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
2743 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si;
2744 1.1 mrg else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
2745 1.1 mrg builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si;
2746 1.1 mrg else
2747 1.1 mrg return NULL_TREE;
2748 1.1 mrg
2749 1.1 mrg return aarch64_builtin_decls[builtin];
2750 1.1 mrg }
2751 1.1 mrg default:
2752 1.1 mrg return NULL_TREE;
2753 1.1 mrg }
2754 1.1 mrg
2755 1.1 mrg return NULL_TREE;
2756 1.1 mrg }
2757 1.1 mrg
2758 1.1 mrg /* Return builtin for reciprocal square root. */
2759 1.1 mrg
2760 1.1 mrg tree
2761 1.1 mrg aarch64_general_builtin_rsqrt (unsigned int fn)
2762 1.1 mrg {
2763 1.1 mrg if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df)
2764 1.1 mrg return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2DF];
2765 1.1 mrg if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf)
2766 1.1 mrg return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2SF];
2767 1.1 mrg if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf)
2768 1.1 mrg return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V4SF];
2769 1.1 mrg return NULL_TREE;
2770 1.1 mrg }
2771 1.1 mrg
2772 1.1 mrg /* Return true if the lane check can be removed as there is no
2773 1.1 mrg error going to be emitted. */
2774 1.1 mrg static bool
2775 1.1 mrg aarch64_fold_builtin_lane_check (tree arg0, tree arg1, tree arg2)
2776 1.1 mrg {
2777 1.1 mrg if (TREE_CODE (arg0) != INTEGER_CST)
2778 1.1 mrg return false;
2779 1.1 mrg if (TREE_CODE (arg1) != INTEGER_CST)
2780 1.1 mrg return false;
2781 1.1 mrg if (TREE_CODE (arg2) != INTEGER_CST)
2782 1.1 mrg return false;
2783 1.1 mrg
2784 1.1 mrg auto totalsize = wi::to_widest (arg0);
2785 1.1 mrg auto elementsize = wi::to_widest (arg1);
2786 1.1 mrg if (totalsize == 0 || elementsize == 0)
2787 1.1 mrg return false;
2788 1.1 mrg auto lane = wi::to_widest (arg2);
2789 1.1 mrg auto high = wi::udiv_trunc (totalsize, elementsize);
2790 1.1 mrg return wi::ltu_p (lane, high);
2791 1.1 mrg }
2792 1.1 mrg
2793 1.1 mrg #undef VAR1
2794 1.1 mrg #define VAR1(T, N, MAP, FLAG, A) \
2795 1.1 mrg case AARCH64_SIMD_BUILTIN_##T##_##N##A:
2796 1.1 mrg
2797 1.1 mrg /* Try to fold a call to the built-in function with subcode FCODE. The
2798 1.1 mrg function is passed the N_ARGS arguments in ARGS and it returns a value
2799 1.1 mrg of type TYPE. Return the new expression on success and NULL_TREE on
2800 1.1 mrg failure. */
2801 1.1 mrg tree
2802 1.1 mrg aarch64_general_fold_builtin (unsigned int fcode, tree type,
2803 1.1 mrg unsigned int n_args ATTRIBUTE_UNUSED, tree *args)
2804 1.1 mrg {
2805 1.1 mrg switch (fcode)
2806 1.1 mrg {
2807 1.1 mrg BUILTIN_VDQF (UNOP, abs, 2, ALL)
2808 1.1 mrg return fold_build1 (ABS_EXPR, type, args[0]);
2809 1.1 mrg VAR1 (UNOP, floatv2si, 2, ALL, v2sf)
2810 1.1 mrg VAR1 (UNOP, floatv4si, 2, ALL, v4sf)
2811 1.1 mrg VAR1 (UNOP, floatv2di, 2, ALL, v2df)
2812 1.1 mrg return fold_build1 (FLOAT_EXPR, type, args[0]);
2813 1.1 mrg case AARCH64_SIMD_BUILTIN_LANE_CHECK:
2814 1.1 mrg gcc_assert (n_args == 3);
2815 1.1 mrg if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
2816 1.1 mrg return void_node;
2817 1.1 mrg break;
2818 1.1 mrg default:
2819 1.1 mrg break;
2820 1.1 mrg }
2821 1.1 mrg
2822 1.1 mrg return NULL_TREE;
2823 1.1 mrg }
2824 1.1 mrg
2825 1.1 mrg enum aarch64_simd_type
2826 1.1 mrg get_mem_type_for_load_store (unsigned int fcode)
2827 1.1 mrg {
2828 1.1 mrg switch (fcode)
2829 1.1 mrg {
2830 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v8qi)
2831 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v8qi)
2832 1.1 mrg return Int8x8_t;
2833 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v16qi)
2834 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v16qi)
2835 1.1 mrg return Int8x16_t;
2836 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v4hi)
2837 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v4hi)
2838 1.1 mrg return Int16x4_t;
2839 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v8hi)
2840 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v8hi)
2841 1.1 mrg return Int16x8_t;
2842 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v2si)
2843 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v2si)
2844 1.1 mrg return Int32x2_t;
2845 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v4si)
2846 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v4si)
2847 1.1 mrg return Int32x4_t;
2848 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v2di)
2849 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v2di)
2850 1.1 mrg return Int64x2_t;
2851 1.1 mrg VAR1 (LOAD1_U, ld1, 0, LOAD, v8qi)
2852 1.1 mrg VAR1 (STORE1_U, st1, 0, STORE, v8qi)
2853 1.1 mrg return Uint8x8_t;
2854 1.1 mrg VAR1 (LOAD1_U, ld1, 0, LOAD, v16qi)
2855 1.1 mrg VAR1 (STORE1_U, st1, 0, STORE, v16qi)
2856 1.1 mrg return Uint8x16_t;
2857 1.1 mrg VAR1 (LOAD1_U, ld1, 0, LOAD, v4hi)
2858 1.1 mrg VAR1 (STORE1_U, st1, 0, STORE, v4hi)
2859 1.1 mrg return Uint16x4_t;
2860 1.1 mrg VAR1 (LOAD1_U, ld1, 0, LOAD, v8hi)
2861 1.1 mrg VAR1 (STORE1_U, st1, 0, STORE, v8hi)
2862 1.1 mrg return Uint16x8_t;
2863 1.1 mrg VAR1 (LOAD1_U, ld1, 0, LOAD, v2si)
2864 1.1 mrg VAR1 (STORE1_U, st1, 0, STORE, v2si)
2865 1.1 mrg return Uint32x2_t;
2866 1.1 mrg VAR1 (LOAD1_U, ld1, 0, LOAD, v4si)
2867 1.1 mrg VAR1 (STORE1_U, st1, 0, STORE, v4si)
2868 1.1 mrg return Uint32x4_t;
2869 1.1 mrg VAR1 (LOAD1_U, ld1, 0, LOAD, v2di)
2870 1.1 mrg VAR1 (STORE1_U, st1, 0, STORE, v2di)
2871 1.1 mrg return Uint64x2_t;
2872 1.1 mrg VAR1 (LOAD1_P, ld1, 0, LOAD, v8qi)
2873 1.1 mrg VAR1 (STORE1_P, st1, 0, STORE, v8qi)
2874 1.1 mrg return Poly8x8_t;
2875 1.1 mrg VAR1 (LOAD1_P, ld1, 0, LOAD, v16qi)
2876 1.1 mrg VAR1 (STORE1_P, st1, 0, STORE, v16qi)
2877 1.1 mrg return Poly8x16_t;
2878 1.1 mrg VAR1 (LOAD1_P, ld1, 0, LOAD, v4hi)
2879 1.1 mrg VAR1 (STORE1_P, st1, 0, STORE, v4hi)
2880 1.1 mrg return Poly16x4_t;
2881 1.1 mrg VAR1 (LOAD1_P, ld1, 0, LOAD, v8hi)
2882 1.1 mrg VAR1 (STORE1_P, st1, 0, STORE, v8hi)
2883 1.1 mrg return Poly16x8_t;
2884 1.1 mrg VAR1 (LOAD1_P, ld1, 0, LOAD, v2di)
2885 1.1 mrg VAR1 (STORE1_P, st1, 0, STORE, v2di)
2886 1.1 mrg return Poly64x2_t;
2887 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v4hf)
2888 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v4hf)
2889 1.1 mrg return Float16x4_t;
2890 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v8hf)
2891 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v8hf)
2892 1.1 mrg return Float16x8_t;
2893 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v4bf)
2894 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v4bf)
2895 1.1 mrg return Bfloat16x4_t;
2896 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v8bf)
2897 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v8bf)
2898 1.1 mrg return Bfloat16x8_t;
2899 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v2sf)
2900 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v2sf)
2901 1.1 mrg return Float32x2_t;
2902 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v4sf)
2903 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v4sf)
2904 1.1 mrg return Float32x4_t;
2905 1.1 mrg VAR1 (LOAD1, ld1, 0, LOAD, v2df)
2906 1.1 mrg VAR1 (STORE1, st1, 0, STORE, v2df)
2907 1.1 mrg return Float64x2_t;
2908 1.1 mrg default:
2909 1.1 mrg gcc_unreachable ();
2910 1.1 mrg break;
2911 1.1 mrg }
2912 1.1 mrg }
2913 1.1 mrg
2914 1.1 mrg /* We've seen a vector load from address ADDR. Record it in
2915 1.1 mrg vector_load_decls, if appropriate. */
2916 1.1 mrg static void
2917 1.1 mrg aarch64_record_vector_load_arg (tree addr)
2918 1.1 mrg {
2919 1.1 mrg tree decl = aarch64_vector_load_decl (addr);
2920 1.1 mrg if (!decl)
2921 1.1 mrg return;
2922 1.1 mrg if (!cfun->machine->vector_load_decls)
2923 1.1 mrg cfun->machine->vector_load_decls = hash_set<tree>::create_ggc (31);
2924 1.1 mrg cfun->machine->vector_load_decls->add (decl);
2925 1.1 mrg }
2926 1.1 mrg
2927 1.1 mrg /* Try to fold STMT, given that it's a call to the built-in function with
2928 1.1 mrg subcode FCODE. Return the new statement on success and null on
2929 1.1 mrg failure. */
2930 1.1 mrg gimple *
2931 1.1 mrg aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt,
2932 1.1 mrg gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED)
2933 1.1 mrg {
2934 1.1 mrg gimple *new_stmt = NULL;
2935 1.1 mrg unsigned nargs = gimple_call_num_args (stmt);
2936 1.1 mrg tree *args = (nargs > 0
2937 1.1 mrg ? gimple_call_arg_ptr (stmt, 0)
2938 1.1 mrg : &error_mark_node);
2939 1.1 mrg
2940 1.1 mrg /* We use gimple's IFN_REDUC_(PLUS|MIN|MAX)s for float, signed int
2941 1.1 mrg and unsigned int; it will distinguish according to the types of
2942 1.1 mrg the arguments to the __builtin. */
2943 1.1 mrg switch (fcode)
2944 1.1 mrg {
2945 1.1 mrg BUILTIN_VALL (UNOP, reduc_plus_scal_, 10, ALL)
2946 1.1 mrg new_stmt = gimple_build_call_internal (IFN_REDUC_PLUS,
2947 1.1 mrg 1, args[0]);
2948 1.1 mrg gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
2949 1.1 mrg break;
2950 1.1 mrg
2951 1.1 mrg /* Lower sqrt builtins to gimple/internal function sqrt. */
2952 1.1 mrg BUILTIN_VHSDF_DF (UNOP, sqrt, 2, FP)
2953 1.1 mrg new_stmt = gimple_build_call_internal (IFN_SQRT,
2954 1.1 mrg 1, args[0]);
2955 1.1 mrg gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
2956 1.1 mrg break;
2957 1.1 mrg
2958 1.1 mrg /*lower store and load neon builtins to gimple. */
2959 1.1 mrg BUILTIN_VALL_F16 (LOAD1, ld1, 0, LOAD)
2960 1.1 mrg BUILTIN_VDQ_I (LOAD1_U, ld1, 0, LOAD)
2961 1.1 mrg BUILTIN_VALLP_NO_DI (LOAD1_P, ld1, 0, LOAD)
2962 1.1 mrg /* Punt until after inlining, so that we stand more chance of
2963 1.1 mrg recording something meaningful in vector_load_decls. */
2964 1.1 mrg if (!cfun->after_inlining)
2965 1.1 mrg break;
2966 1.1 mrg aarch64_record_vector_load_arg (args[0]);
2967 1.1 mrg if (!BYTES_BIG_ENDIAN)
2968 1.1 mrg {
2969 1.1 mrg enum aarch64_simd_type mem_type
2970 1.1 mrg = get_mem_type_for_load_store(fcode);
2971 1.1 mrg aarch64_simd_type_info simd_type
2972 1.1 mrg = aarch64_simd_types[mem_type];
2973 1.1 mrg tree elt_ptr_type = build_pointer_type_for_mode (simd_type.eltype,
2974 1.1 mrg VOIDmode, true);
2975 1.1 mrg tree zero = build_zero_cst (elt_ptr_type);
2976 1.1 mrg /* Use element type alignment. */
2977 1.1 mrg tree access_type
2978 1.1 mrg = build_aligned_type (simd_type.itype,
2979 1.1 mrg TYPE_ALIGN (simd_type.eltype));
2980 1.1 mrg new_stmt
2981 1.1 mrg = gimple_build_assign (gimple_get_lhs (stmt),
2982 1.1 mrg fold_build2 (MEM_REF,
2983 1.1 mrg access_type,
2984 1.1 mrg args[0], zero));
2985 1.1 mrg gimple_set_vuse (new_stmt, gimple_vuse (stmt));
2986 1.1 mrg gimple_set_vdef (new_stmt, gimple_vdef (stmt));
2987 1.1 mrg }
2988 1.1 mrg break;
2989 1.1 mrg
2990 1.1 mrg BUILTIN_VALL_F16 (STORE1, st1, 0, STORE)
2991 1.1 mrg BUILTIN_VDQ_I (STORE1_U, st1, 0, STORE)
2992 1.1 mrg BUILTIN_VALLP_NO_DI (STORE1_P, st1, 0, STORE)
2993 1.1 mrg if (!BYTES_BIG_ENDIAN)
2994 1.1 mrg {
2995 1.1 mrg enum aarch64_simd_type mem_type
2996 1.1 mrg = get_mem_type_for_load_store(fcode);
2997 1.1 mrg aarch64_simd_type_info simd_type
2998 1.1 mrg = aarch64_simd_types[mem_type];
2999 1.1 mrg tree elt_ptr_type = build_pointer_type_for_mode (simd_type.eltype,
3000 1.1 mrg VOIDmode, true);
3001 1.1 mrg tree zero = build_zero_cst (elt_ptr_type);
3002 1.1 mrg /* Use element type alignment. */
3003 1.1 mrg tree access_type
3004 1.1 mrg = build_aligned_type (simd_type.itype,
3005 1.1 mrg TYPE_ALIGN (simd_type.eltype));
3006 1.1 mrg new_stmt
3007 1.1 mrg = gimple_build_assign (fold_build2 (MEM_REF, access_type,
3008 1.1 mrg args[0], zero),
3009 1.1 mrg args[1]);
3010 1.1 mrg gimple_set_vuse (new_stmt, gimple_vuse (stmt));
3011 1.1 mrg gimple_set_vdef (new_stmt, gimple_vdef (stmt));
3012 1.1 mrg }
3013 1.1 mrg break;
3014 1.1 mrg
3015 1.1 mrg BUILTIN_VDQIF (UNOP, reduc_smax_scal_, 10, ALL)
3016 1.1 mrg BUILTIN_VDQ_BHSI (UNOPU, reduc_umax_scal_, 10, ALL)
3017 1.1 mrg new_stmt = gimple_build_call_internal (IFN_REDUC_MAX,
3018 1.1 mrg 1, args[0]);
3019 1.1 mrg gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
3020 1.1 mrg break;
3021 1.1 mrg BUILTIN_VDQIF (UNOP, reduc_smin_scal_, 10, ALL)
3022 1.1 mrg BUILTIN_VDQ_BHSI (UNOPU, reduc_umin_scal_, 10, ALL)
3023 1.1 mrg new_stmt = gimple_build_call_internal (IFN_REDUC_MIN,
3024 1.1 mrg 1, args[0]);
3025 1.1 mrg gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
3026 1.1 mrg break;
3027 1.1 mrg BUILTIN_VSDQ_I_DI (BINOP, ashl, 3, NONE)
3028 1.1 mrg if (TREE_CODE (args[1]) == INTEGER_CST
3029 1.1 mrg && wi::ltu_p (wi::to_wide (args[1]), element_precision (args[0])))
3030 1.1 mrg new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3031 1.1 mrg LSHIFT_EXPR, args[0], args[1]);
3032 1.1 mrg break;
3033 1.1 mrg BUILTIN_VSDQ_I_DI (BINOP, sshl, 0, NONE)
3034 1.1 mrg BUILTIN_VSDQ_I_DI (BINOP_UUS, ushl, 0, NONE)
3035 1.1 mrg {
3036 1.1 mrg tree cst = args[1];
3037 1.1 mrg tree ctype = TREE_TYPE (cst);
3038 1.1 mrg /* Left shifts can be both scalar or vector, e.g. uint64x1_t is
3039 1.1 mrg treated as a scalar type not a vector one. */
3040 1.1 mrg if ((cst = uniform_integer_cst_p (cst)) != NULL_TREE)
3041 1.1 mrg {
3042 1.1 mrg wide_int wcst = wi::to_wide (cst);
3043 1.1 mrg tree unit_ty = TREE_TYPE (cst);
3044 1.1 mrg
3045 1.1 mrg wide_int abs_cst = wi::abs (wcst);
3046 1.1 mrg if (wi::geu_p (abs_cst, element_precision (args[0])))
3047 1.1 mrg break;
3048 1.1 mrg
3049 1.1 mrg if (wi::neg_p (wcst, TYPE_SIGN (ctype)))
3050 1.1 mrg {
3051 1.1 mrg tree final_cst;
3052 1.1 mrg final_cst = wide_int_to_tree (unit_ty, abs_cst);
3053 1.1 mrg if (TREE_CODE (cst) != INTEGER_CST)
3054 1.1 mrg final_cst = build_uniform_cst (ctype, final_cst);
3055 1.1 mrg
3056 1.1 mrg new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3057 1.1 mrg RSHIFT_EXPR, args[0],
3058 1.1 mrg final_cst);
3059 1.1 mrg }
3060 1.1 mrg else
3061 1.1 mrg new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3062 1.1 mrg LSHIFT_EXPR, args[0], args[1]);
3063 1.1 mrg }
3064 1.1 mrg }
3065 1.1 mrg break;
3066 1.1 mrg BUILTIN_VDQ_I (SHIFTIMM, ashr, 3, NONE)
3067 1.1 mrg VAR1 (SHIFTIMM, ashr_simd, 0, NONE, di)
3068 1.1 mrg BUILTIN_VDQ_I (USHIFTIMM, lshr, 3, NONE)
3069 1.1 mrg VAR1 (USHIFTIMM, lshr_simd, 0, NONE, di)
3070 1.1 mrg if (TREE_CODE (args[1]) == INTEGER_CST
3071 1.1 mrg && wi::ltu_p (wi::to_wide (args[1]), element_precision (args[0])))
3072 1.1 mrg new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3073 1.1 mrg RSHIFT_EXPR, args[0], args[1]);
3074 1.1 mrg break;
3075 1.1 mrg BUILTIN_GPF (BINOP, fmulx, 0, ALL)
3076 1.1 mrg {
3077 1.1 mrg gcc_assert (nargs == 2);
3078 1.1 mrg bool a0_cst_p = TREE_CODE (args[0]) == REAL_CST;
3079 1.1 mrg bool a1_cst_p = TREE_CODE (args[1]) == REAL_CST;
3080 1.1 mrg if (a0_cst_p || a1_cst_p)
3081 1.1 mrg {
3082 1.1 mrg if (a0_cst_p && a1_cst_p)
3083 1.1 mrg {
3084 1.1 mrg tree t0 = TREE_TYPE (args[0]);
3085 1.1 mrg real_value a0 = (TREE_REAL_CST (args[0]));
3086 1.1 mrg real_value a1 = (TREE_REAL_CST (args[1]));
3087 1.1 mrg if (real_equal (&a1, &dconst0))
3088 1.1 mrg std::swap (a0, a1);
3089 1.1 mrg /* According to real_equal (), +0 equals -0. */
3090 1.1 mrg if (real_equal (&a0, &dconst0) && real_isinf (&a1))
3091 1.1 mrg {
3092 1.1 mrg real_value res = dconst2;
3093 1.1 mrg res.sign = a0.sign ^ a1.sign;
3094 1.1 mrg new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3095 1.1 mrg REAL_CST,
3096 1.1 mrg build_real (t0, res));
3097 1.1 mrg }
3098 1.1 mrg else
3099 1.1 mrg new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3100 1.1 mrg MULT_EXPR,
3101 1.1 mrg args[0], args[1]);
3102 1.1 mrg }
3103 1.1 mrg else /* a0_cst_p ^ a1_cst_p. */
3104 1.1 mrg {
3105 1.1 mrg real_value const_part = a0_cst_p
3106 1.1 mrg ? TREE_REAL_CST (args[0]) : TREE_REAL_CST (args[1]);
3107 1.1 mrg if (!real_equal (&const_part, &dconst0)
3108 1.1 mrg && !real_isinf (&const_part))
3109 1.1 mrg new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
3110 1.1 mrg MULT_EXPR, args[0],
3111 1.1 mrg args[1]);
3112 1.1 mrg }
3113 1.1 mrg }
3114 1.1 mrg if (new_stmt)
3115 1.1 mrg {
3116 1.1 mrg gimple_set_vuse (new_stmt, gimple_vuse (stmt));
3117 1.1 mrg gimple_set_vdef (new_stmt, gimple_vdef (stmt));
3118 1.1 mrg }
3119 1.1 mrg break;
3120 1.1 mrg }
3121 1.1 mrg case AARCH64_SIMD_BUILTIN_LANE_CHECK:
3122 1.1 mrg if (aarch64_fold_builtin_lane_check (args[0], args[1], args[2]))
3123 1.1 mrg {
3124 1.1 mrg unlink_stmt_vdef (stmt);
3125 1.1 mrg release_defs (stmt);
3126 1.1 mrg new_stmt = gimple_build_nop ();
3127 1.1 mrg }
3128 1.1 mrg break;
3129 1.1 mrg default:
3130 1.1 mrg break;
3131 1.1 mrg }
3132 1.1 mrg return new_stmt;
3133 1.1 mrg }
3134 1.1 mrg
3135 1.1 mrg void
3136 1.1 mrg aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
3137 1.1 mrg {
3138 1.1 mrg const unsigned AARCH64_FE_INVALID = 1;
3139 1.1 mrg const unsigned AARCH64_FE_DIVBYZERO = 2;
3140 1.1 mrg const unsigned AARCH64_FE_OVERFLOW = 4;
3141 1.1 mrg const unsigned AARCH64_FE_UNDERFLOW = 8;
3142 1.1 mrg const unsigned AARCH64_FE_INEXACT = 16;
3143 1.1 mrg const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID
3144 1.1 mrg | AARCH64_FE_DIVBYZERO
3145 1.1 mrg | AARCH64_FE_OVERFLOW
3146 1.1 mrg | AARCH64_FE_UNDERFLOW
3147 1.1 mrg | AARCH64_FE_INEXACT);
3148 1.1 mrg const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8;
3149 1.1 mrg tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr;
3150 1.1 mrg tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr;
3151 1.1 mrg tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr;
3152 1.1 mrg tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv;
3153 1.1 mrg
3154 1.1 mrg /* Generate the equivalence of :
3155 1.1 mrg unsigned int fenv_cr;
3156 1.1 mrg fenv_cr = __builtin_aarch64_get_fpcr ();
3157 1.1 mrg
3158 1.1 mrg unsigned int fenv_sr;
3159 1.1 mrg fenv_sr = __builtin_aarch64_get_fpsr ();
3160 1.1 mrg
3161 1.1 mrg Now set all exceptions to non-stop
3162 1.1 mrg unsigned int mask_cr
3163 1.1 mrg = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
3164 1.1 mrg unsigned int masked_cr;
3165 1.1 mrg masked_cr = fenv_cr & mask_cr;
3166 1.1 mrg
3167 1.1 mrg And clear all exception flags
3168 1.1 mrg unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
3169 1.1 mrg unsigned int masked_cr;
3170 1.1 mrg masked_sr = fenv_sr & mask_sr;
3171 1.1 mrg
3172 1.1 mrg __builtin_aarch64_set_cr (masked_cr);
3173 1.1 mrg __builtin_aarch64_set_sr (masked_sr); */
3174 1.1 mrg
3175 1.1 mrg fenv_cr = create_tmp_var_raw (unsigned_type_node);
3176 1.1 mrg fenv_sr = create_tmp_var_raw (unsigned_type_node);
3177 1.1 mrg
3178 1.1 mrg get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR];
3179 1.1 mrg set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR];
3180 1.1 mrg get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR];
3181 1.1 mrg set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR];
3182 1.1 mrg
3183 1.1 mrg mask_cr = build_int_cst (unsigned_type_node,
3184 1.1 mrg ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT));
3185 1.1 mrg mask_sr = build_int_cst (unsigned_type_node,
3186 1.1 mrg ~(AARCH64_FE_ALL_EXCEPT));
3187 1.1 mrg
3188 1.1 mrg ld_fenv_cr = build4 (TARGET_EXPR, unsigned_type_node,
3189 1.1 mrg fenv_cr, build_call_expr (get_fpcr, 0),
3190 1.1 mrg NULL_TREE, NULL_TREE);
3191 1.1 mrg ld_fenv_sr = build4 (TARGET_EXPR, unsigned_type_node,
3192 1.1 mrg fenv_sr, build_call_expr (get_fpsr, 0),
3193 1.1 mrg NULL_TREE, NULL_TREE);
3194 1.1 mrg
3195 1.1 mrg masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr);
3196 1.1 mrg masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr);
3197 1.1 mrg
3198 1.1 mrg hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr);
3199 1.1 mrg hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr);
3200 1.1 mrg
3201 1.1 mrg hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr,
3202 1.1 mrg hold_fnclex_sr);
3203 1.1 mrg masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr,
3204 1.1 mrg masked_fenv_sr);
3205 1.1 mrg ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr);
3206 1.1 mrg
3207 1.1 mrg *hold = build2 (COMPOUND_EXPR, void_type_node,
3208 1.1 mrg build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
3209 1.1 mrg hold_fnclex);
3210 1.1 mrg
3211 1.1 mrg /* Store the value of masked_fenv to clear the exceptions:
3212 1.1 mrg __builtin_aarch64_set_fpsr (masked_fenv_sr); */
3213 1.1 mrg
3214 1.1 mrg *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr);
3215 1.1 mrg
3216 1.1 mrg /* Generate the equivalent of :
3217 1.1 mrg unsigned int new_fenv_var;
3218 1.1 mrg new_fenv_var = __builtin_aarch64_get_fpsr ();
3219 1.1 mrg
3220 1.1 mrg __builtin_aarch64_set_fpsr (fenv_sr);
3221 1.1 mrg
3222 1.1 mrg __atomic_feraiseexcept (new_fenv_var); */
3223 1.1 mrg
3224 1.1 mrg new_fenv_var = create_tmp_var_raw (unsigned_type_node);
3225 1.1 mrg reload_fenv = build4 (TARGET_EXPR, unsigned_type_node,
3226 1.1 mrg new_fenv_var, build_call_expr (get_fpsr, 0),
3227 1.1 mrg NULL_TREE, NULL_TREE);
3228 1.1 mrg restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr);
3229 1.1 mrg atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
3230 1.1 mrg update_call = build_call_expr (atomic_feraiseexcept, 1,
3231 1.1 mrg fold_convert (integer_type_node, new_fenv_var));
3232 1.1 mrg *update = build2 (COMPOUND_EXPR, void_type_node,
3233 1.1 mrg build2 (COMPOUND_EXPR, void_type_node,
3234 1.1 mrg reload_fenv, restore_fnenv), update_call);
3235 1.1 mrg }
3236 1.1 mrg
3237 1.1 mrg /* Resolve overloaded MEMTAG build-in functions. */
3238 1.1 mrg #define AARCH64_BUILTIN_SUBCODE(F) \
3239 1.1 mrg (DECL_MD_FUNCTION_CODE (F) >> AARCH64_BUILTIN_SHIFT)
3240 1.1 mrg
3241 1.1 mrg static tree
3242 1.1 mrg aarch64_resolve_overloaded_memtag (location_t loc,
3243 1.1 mrg tree fndecl, void *pass_params)
3244 1.1 mrg {
3245 1.1 mrg vec<tree, va_gc> *params = static_cast<vec<tree, va_gc> *> (pass_params);
3246 1.1 mrg unsigned param_num = params ? params->length() : 0;
3247 1.1 mrg unsigned int fcode = AARCH64_BUILTIN_SUBCODE (fndecl);
3248 1.1 mrg tree inittype = aarch64_memtag_builtin_data[
3249 1.1 mrg fcode - AARCH64_MEMTAG_BUILTIN_START - 1].ftype;
3250 1.1 mrg unsigned arg_num = list_length (TYPE_ARG_TYPES (inittype)) - 1;
3251 1.1 mrg
3252 1.1 mrg if (param_num != arg_num)
3253 1.1 mrg {
3254 1.1 mrg TREE_TYPE (fndecl) = inittype;
3255 1.1 mrg return NULL_TREE;
3256 1.1 mrg }
3257 1.1 mrg tree retype = NULL;
3258 1.1 mrg
3259 1.1 mrg if (fcode == AARCH64_MEMTAG_BUILTIN_SUBP)
3260 1.1 mrg {
3261 1.1 mrg tree t0 = TREE_TYPE ((*params)[0]);
3262 1.1 mrg tree t1 = TREE_TYPE ((*params)[1]);
3263 1.1 mrg
3264 1.1 mrg if (t0 == error_mark_node || TREE_CODE (t0) != POINTER_TYPE)
3265 1.1 mrg t0 = ptr_type_node;
3266 1.1 mrg if (t1 == error_mark_node || TREE_CODE (t1) != POINTER_TYPE)
3267 1.1 mrg t1 = ptr_type_node;
3268 1.1 mrg
3269 1.1 mrg if (TYPE_MODE (t0) != DImode)
3270 1.1 mrg warning_at (loc, 1, "expected 64-bit address but argument 1 is %d-bit",
3271 1.1 mrg (int)tree_to_shwi (DECL_SIZE ((*params)[0])));
3272 1.1 mrg
3273 1.1 mrg if (TYPE_MODE (t1) != DImode)
3274 1.1 mrg warning_at (loc, 1, "expected 64-bit address but argument 2 is %d-bit",
3275 1.1 mrg (int)tree_to_shwi (DECL_SIZE ((*params)[1])));
3276 1.1 mrg
3277 1.1 mrg retype = build_function_type_list (ptrdiff_type_node, t0, t1, NULL);
3278 1.1 mrg }
3279 1.1 mrg else
3280 1.1 mrg {
3281 1.1 mrg tree t0 = TREE_TYPE ((*params)[0]);
3282 1.1 mrg
3283 1.1 mrg if (t0 == error_mark_node || TREE_CODE (t0) != POINTER_TYPE)
3284 1.1 mrg {
3285 1.1 mrg TREE_TYPE (fndecl) = inittype;
3286 1.1 mrg return NULL_TREE;
3287 1.1 mrg }
3288 1.1 mrg
3289 1.1 mrg if (TYPE_MODE (t0) != DImode)
3290 1.1 mrg warning_at (loc, 1, "expected 64-bit address but argument 1 is %d-bit",
3291 1.1 mrg (int)tree_to_shwi (DECL_SIZE ((*params)[0])));
3292 1.1 mrg
3293 1.1 mrg switch (fcode)
3294 1.1 mrg {
3295 1.1 mrg case AARCH64_MEMTAG_BUILTIN_IRG:
3296 1.1 mrg retype = build_function_type_list (t0, t0, uint64_type_node, NULL);
3297 1.1 mrg break;
3298 1.1 mrg case AARCH64_MEMTAG_BUILTIN_GMI:
3299 1.1 mrg retype = build_function_type_list (uint64_type_node, t0,
3300 1.1 mrg uint64_type_node, NULL);
3301 1.1 mrg break;
3302 1.1 mrg case AARCH64_MEMTAG_BUILTIN_INC_TAG:
3303 1.1 mrg retype = build_function_type_list (t0, t0, unsigned_type_node, NULL);
3304 1.1 mrg break;
3305 1.1 mrg case AARCH64_MEMTAG_BUILTIN_SET_TAG:
3306 1.1 mrg retype = build_function_type_list (void_type_node, t0, NULL);
3307 1.1 mrg break;
3308 1.1 mrg case AARCH64_MEMTAG_BUILTIN_GET_TAG:
3309 1.1 mrg retype = build_function_type_list (t0, t0, NULL);
3310 1.1 mrg break;
3311 1.1 mrg default:
3312 1.1 mrg return NULL_TREE;
3313 1.1 mrg }
3314 1.1 mrg }
3315 1.1 mrg
3316 1.1 mrg if (!retype || retype == error_mark_node)
3317 1.1 mrg TREE_TYPE (fndecl) = inittype;
3318 1.1 mrg else
3319 1.1 mrg TREE_TYPE (fndecl) = retype;
3320 1.1 mrg
3321 1.1 mrg return NULL_TREE;
3322 1.1 mrg }
3323 1.1 mrg
3324 1.1 mrg /* Called at aarch64_resolve_overloaded_builtin in aarch64-c.cc. */
3325 1.1 mrg tree
3326 1.1 mrg aarch64_resolve_overloaded_builtin_general (location_t loc, tree function,
3327 1.1 mrg void *pass_params)
3328 1.1 mrg {
3329 1.1 mrg unsigned int fcode = AARCH64_BUILTIN_SUBCODE (function);
3330 1.1 mrg
3331 1.1 mrg if (fcode >= AARCH64_MEMTAG_BUILTIN_START
3332 1.1 mrg && fcode <= AARCH64_MEMTAG_BUILTIN_END)
3333 1.1 mrg return aarch64_resolve_overloaded_memtag(loc, function, pass_params);
3334 1.1 mrg
3335 1.1 mrg return NULL_TREE;
3336 1.1 mrg }
3337 1.1 mrg
3338 1.1 mrg #undef AARCH64_CHECK_BUILTIN_MODE
3339 1.1 mrg #undef AARCH64_FIND_FRINT_VARIANT
3340 1.1 mrg #undef CF0
3341 1.1 mrg #undef CF1
3342 1.1 mrg #undef CF2
3343 1.1 mrg #undef CF3
3344 1.1 mrg #undef CF4
3345 1.1 mrg #undef CF10
3346 1.1 mrg #undef VAR1
3347 1.1 mrg #undef VAR2
3348 1.1 mrg #undef VAR3
3349 1.1 mrg #undef VAR4
3350 1.1 mrg #undef VAR5
3351 1.1 mrg #undef VAR6
3352 1.1 mrg #undef VAR7
3353 1.1 mrg #undef VAR8
3354 1.1 mrg #undef VAR9
3355 1.1 mrg #undef VAR10
3356 1.1 mrg #undef VAR11
3357 1.1 mrg
3358 1.1 mrg #include "gt-aarch64-builtins.h"
3359