aarch64-sve.md revision 1.1 1 1.1 mrg ;; Machine description for AArch64 SVE.
2 1.1 mrg ;; Copyright (C) 2009-2016 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 ;; Note on the handling of big-endian SVE
22 1.1 mrg ;; --------------------------------------
23 1.1 mrg ;;
24 1.1 mrg ;; On big-endian systems, Advanced SIMD mov<mode> patterns act in the
25 1.1 mrg ;; same way as movdi or movti would: the first byte of memory goes
26 1.1 mrg ;; into the most significant byte of the register and the last byte
27 1.1 mrg ;; of memory goes into the least significant byte of the register.
28 1.1 mrg ;; This is the most natural ordering for Advanced SIMD and matches
29 1.1 mrg ;; the ABI layout for 64-bit and 128-bit vector types.
30 1.1 mrg ;;
31 1.1 mrg ;; As a result, the order of bytes within the register is what GCC
32 1.1 mrg ;; expects for a big-endian target, and subreg offsets therefore work
33 1.1 mrg ;; as expected, with the first element in memory having subreg offset 0
34 1.1 mrg ;; and the last element in memory having the subreg offset associated
35 1.1 mrg ;; with a big-endian lowpart. However, this ordering also means that
36 1.1 mrg ;; GCC's lane numbering does not match the architecture's numbering:
37 1.1 mrg ;; GCC always treats the element at the lowest address in memory
38 1.1 mrg ;; (subreg offset 0) as element 0, while the architecture treats
39 1.1 mrg ;; the least significant end of the register as element 0.
40 1.1 mrg ;;
41 1.1 mrg ;; The situation for SVE is different. We want the layout of the
42 1.1 mrg ;; SVE register to be same for mov<mode> as it is for maskload<mode>:
43 1.1 mrg ;; logically, a mov<mode> load must be indistinguishable from a
44 1.1 mrg ;; maskload<mode> whose mask is all true. We therefore need the
45 1.1 mrg ;; register layout to match LD1 rather than LDR. The ABI layout of
46 1.1 mrg ;; SVE types also matches LD1 byte ordering rather than LDR byte ordering.
47 1.1 mrg ;;
48 1.1 mrg ;; As a result, the architecture lane numbering matches GCC's lane
49 1.1 mrg ;; numbering, with element 0 always being the first in memory.
50 1.1 mrg ;; However:
51 1.1 mrg ;;
52 1.1 mrg ;; - Applying a subreg offset to a register does not give the element
53 1.1 mrg ;; that GCC expects: the first element in memory has the subreg offset
54 1.1 mrg ;; associated with a big-endian lowpart while the last element in memory
55 1.1 mrg ;; has subreg offset 0. We handle this via TARGET_CAN_CHANGE_MODE_CLASS.
56 1.1 mrg ;;
57 1.1 mrg ;; - We cannot use LDR and STR for spill slots that might be accessed
58 1.1 mrg ;; via subregs, since although the elements have the order GCC expects,
59 1.1 mrg ;; the order of the bytes within the elements is different. We instead
60 1.1 mrg ;; access spill slots via LD1 and ST1, using secondary reloads to
61 1.1 mrg ;; reserve a predicate register.
62 1.1 mrg
63 1.1 mrg
64 1.1 mrg ;; SVE data moves.
65 1.1 mrg (define_expand "mov<mode>"
66 1.1 mrg [(set (match_operand:SVE_ALL 0 "nonimmediate_operand")
67 1.1 mrg (match_operand:SVE_ALL 1 "general_operand"))]
68 1.1 mrg "TARGET_SVE"
69 1.1 mrg {
70 1.1 mrg /* Use the predicated load and store patterns where possible.
71 1.1 mrg This is required for big-endian targets (see the comment at the
72 1.1 mrg head of the file) and increases the addressing choices for
73 1.1 mrg little-endian. */
74 1.1 mrg if ((MEM_P (operands[0]) || MEM_P (operands[1]))
75 1.1 mrg && can_create_pseudo_p ())
76 1.1 mrg {
77 1.1 mrg aarch64_expand_sve_mem_move (operands[0], operands[1], <VPRED>mode);
78 1.1 mrg DONE;
79 1.1 mrg }
80 1.1 mrg
81 1.1 mrg if (CONSTANT_P (operands[1]))
82 1.1 mrg {
83 1.1 mrg aarch64_expand_mov_immediate (operands[0], operands[1],
84 1.1 mrg gen_vec_duplicate<mode>);
85 1.1 mrg DONE;
86 1.1 mrg }
87 1.1 mrg
88 1.1 mrg /* Optimize subregs on big-endian targets: we can use REV[BHW]
89 1.1 mrg instead of going through memory. */
90 1.1 mrg if (BYTES_BIG_ENDIAN
91 1.1 mrg && aarch64_maybe_expand_sve_subreg_move (operands[0], operands[1]))
92 1.1 mrg DONE;
93 1.1 mrg }
94 1.1 mrg )
95 1.1 mrg
96 1.1 mrg ;; A pattern for optimizing SUBREGs that have a reinterpreting effect
97 1.1 mrg ;; on big-endian targets; see aarch64_maybe_expand_sve_subreg_move
98 1.1 mrg ;; for details. We use a special predicate for operand 2 to reduce
99 1.1 mrg ;; the number of patterns.
100 1.1 mrg (define_insn_and_split "*aarch64_sve_mov<mode>_subreg_be"
101 1.1 mrg [(set (match_operand:SVE_ALL 0 "aarch64_sve_nonimmediate_operand" "=w")
102 1.1 mrg (unspec:SVE_ALL
103 1.1 mrg [(match_operand:VNx16BI 1 "register_operand" "Upl")
104 1.1 mrg (match_operand 2 "aarch64_any_register_operand" "w")]
105 1.1 mrg UNSPEC_REV_SUBREG))]
106 1.1 mrg "TARGET_SVE && BYTES_BIG_ENDIAN"
107 1.1 mrg "#"
108 1.1 mrg "&& reload_completed"
109 1.1 mrg [(const_int 0)]
110 1.1 mrg {
111 1.1 mrg aarch64_split_sve_subreg_move (operands[0], operands[1], operands[2]);
112 1.1 mrg DONE;
113 1.1 mrg }
114 1.1 mrg )
115 1.1 mrg
116 1.1 mrg ;; Unpredicated moves (little-endian). Only allow memory operations
117 1.1 mrg ;; during and after RA; before RA we want the predicated load and
118 1.1 mrg ;; store patterns to be used instead.
119 1.1 mrg (define_insn "*aarch64_sve_mov<mode>_le"
120 1.1 mrg [(set (match_operand:SVE_ALL 0 "aarch64_sve_nonimmediate_operand" "=w, Utr, w, w")
121 1.1 mrg (match_operand:SVE_ALL 1 "aarch64_sve_general_operand" "Utr, w, w, Dn"))]
122 1.1 mrg "TARGET_SVE
123 1.1 mrg && !BYTES_BIG_ENDIAN
124 1.1 mrg && ((lra_in_progress || reload_completed)
125 1.1 mrg || (register_operand (operands[0], <MODE>mode)
126 1.1 mrg && nonmemory_operand (operands[1], <MODE>mode)))"
127 1.1 mrg "@
128 1.1 mrg ldr\t%0, %1
129 1.1 mrg str\t%1, %0
130 1.1 mrg mov\t%0.d, %1.d
131 1.1 mrg * return aarch64_output_sve_mov_immediate (operands[1]);"
132 1.1 mrg )
133 1.1 mrg
134 1.1 mrg ;; Unpredicated moves (big-endian). Memory accesses require secondary
135 1.1 mrg ;; reloads.
136 1.1 mrg (define_insn "*aarch64_sve_mov<mode>_be"
137 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w, w")
138 1.1 mrg (match_operand:SVE_ALL 1 "aarch64_nonmemory_operand" "w, Dn"))]
139 1.1 mrg "TARGET_SVE && BYTES_BIG_ENDIAN"
140 1.1 mrg "@
141 1.1 mrg mov\t%0.d, %1.d
142 1.1 mrg * return aarch64_output_sve_mov_immediate (operands[1]);"
143 1.1 mrg )
144 1.1 mrg
145 1.1 mrg ;; Handle big-endian memory reloads. We use byte PTRUE for all modes
146 1.1 mrg ;; to try to encourage reuse.
147 1.1 mrg (define_expand "aarch64_sve_reload_be"
148 1.1 mrg [(parallel
149 1.1 mrg [(set (match_operand 0)
150 1.1 mrg (match_operand 1))
151 1.1 mrg (clobber (match_operand:VNx16BI 2 "register_operand" "=Upl"))])]
152 1.1 mrg "TARGET_SVE && BYTES_BIG_ENDIAN"
153 1.1 mrg {
154 1.1 mrg /* Create a PTRUE. */
155 1.1 mrg emit_move_insn (operands[2], CONSTM1_RTX (VNx16BImode));
156 1.1 mrg
157 1.1 mrg /* Refer to the PTRUE in the appropriate mode for this move. */
158 1.1 mrg machine_mode mode = GET_MODE (operands[0]);
159 1.1 mrg machine_mode pred_mode
160 1.1 mrg = aarch64_sve_pred_mode (GET_MODE_UNIT_SIZE (mode)).require ();
161 1.1 mrg rtx pred = gen_lowpart (pred_mode, operands[2]);
162 1.1 mrg
163 1.1 mrg /* Emit a predicated load or store. */
164 1.1 mrg aarch64_emit_sve_pred_move (operands[0], pred, operands[1]);
165 1.1 mrg DONE;
166 1.1 mrg }
167 1.1 mrg )
168 1.1 mrg
169 1.1 mrg ;; A predicated load or store for which the predicate is known to be
170 1.1 mrg ;; all-true. Note that this pattern is generated directly by
171 1.1 mrg ;; aarch64_emit_sve_pred_move, so changes to this pattern will
172 1.1 mrg ;; need changes there as well.
173 1.1 mrg (define_insn "*pred_mov<mode>"
174 1.1 mrg [(set (match_operand:SVE_ALL 0 "nonimmediate_operand" "=w, m")
175 1.1 mrg (unspec:SVE_ALL
176 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
177 1.1 mrg (match_operand:SVE_ALL 2 "nonimmediate_operand" "m, w")]
178 1.1 mrg UNSPEC_MERGE_PTRUE))]
179 1.1 mrg "TARGET_SVE
180 1.1 mrg && (register_operand (operands[0], <MODE>mode)
181 1.1 mrg || register_operand (operands[2], <MODE>mode))"
182 1.1 mrg "@
183 1.1 mrg ld1<Vesize>\t%0.<Vetype>, %1/z, %2
184 1.1 mrg st1<Vesize>\t%2.<Vetype>, %1, %0"
185 1.1 mrg )
186 1.1 mrg
187 1.1 mrg (define_expand "movmisalign<mode>"
188 1.1 mrg [(set (match_operand:SVE_ALL 0 "nonimmediate_operand")
189 1.1 mrg (match_operand:SVE_ALL 1 "general_operand"))]
190 1.1 mrg "TARGET_SVE"
191 1.1 mrg {
192 1.1 mrg /* Equivalent to a normal move for our purpooses. */
193 1.1 mrg emit_move_insn (operands[0], operands[1]);
194 1.1 mrg DONE;
195 1.1 mrg }
196 1.1 mrg )
197 1.1 mrg
198 1.1 mrg (define_insn "maskload<mode><vpred>"
199 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
200 1.1 mrg (unspec:SVE_ALL
201 1.1 mrg [(match_operand:<VPRED> 2 "register_operand" "Upl")
202 1.1 mrg (match_operand:SVE_ALL 1 "memory_operand" "m")]
203 1.1 mrg UNSPEC_LD1_SVE))]
204 1.1 mrg "TARGET_SVE"
205 1.1 mrg "ld1<Vesize>\t%0.<Vetype>, %2/z, %1"
206 1.1 mrg )
207 1.1 mrg
208 1.1 mrg (define_insn "maskstore<mode><vpred>"
209 1.1 mrg [(set (match_operand:SVE_ALL 0 "memory_operand" "+m")
210 1.1 mrg (unspec:SVE_ALL [(match_operand:<VPRED> 2 "register_operand" "Upl")
211 1.1 mrg (match_operand:SVE_ALL 1 "register_operand" "w")
212 1.1 mrg (match_dup 0)]
213 1.1 mrg UNSPEC_ST1_SVE))]
214 1.1 mrg "TARGET_SVE"
215 1.1 mrg "st1<Vesize>\t%1.<Vetype>, %2, %0"
216 1.1 mrg )
217 1.1 mrg
218 1.1 mrg ;; Unpredicated gather loads.
219 1.1 mrg (define_expand "gather_load<mode>"
220 1.1 mrg [(set (match_operand:SVE_SD 0 "register_operand")
221 1.1 mrg (unspec:SVE_SD
222 1.1 mrg [(match_dup 5)
223 1.1 mrg (match_operand:DI 1 "aarch64_reg_or_zero")
224 1.1 mrg (match_operand:<V_INT_EQUIV> 2 "register_operand")
225 1.1 mrg (match_operand:DI 3 "const_int_operand")
226 1.1 mrg (match_operand:DI 4 "aarch64_gather_scale_operand_<Vesize>")
227 1.1 mrg (mem:BLK (scratch))]
228 1.1 mrg UNSPEC_LD1_GATHER))]
229 1.1 mrg "TARGET_SVE"
230 1.1 mrg {
231 1.1 mrg operands[5] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
232 1.1 mrg }
233 1.1 mrg )
234 1.1 mrg
235 1.1 mrg ;; Predicated gather loads for 32-bit elements. Operand 3 is true for
236 1.1 mrg ;; unsigned extension and false for signed extension.
237 1.1 mrg (define_insn "mask_gather_load<mode>"
238 1.1 mrg [(set (match_operand:SVE_S 0 "register_operand" "=w, w, w, w, w")
239 1.1 mrg (unspec:SVE_S
240 1.1 mrg [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl, Upl, Upl")
241 1.1 mrg (match_operand:DI 1 "aarch64_reg_or_zero" "Z, rk, rk, rk, rk")
242 1.1 mrg (match_operand:<V_INT_EQUIV> 2 "register_operand" "w, w, w, w, w")
243 1.1 mrg (match_operand:DI 3 "const_int_operand" "i, Z, Ui1, Z, Ui1")
244 1.1 mrg (match_operand:DI 4 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, i, i")
245 1.1 mrg (mem:BLK (scratch))]
246 1.1 mrg UNSPEC_LD1_GATHER))]
247 1.1 mrg "TARGET_SVE"
248 1.1 mrg "@
249 1.1 mrg ld1w\t%0.s, %5/z, [%2.s]
250 1.1 mrg ld1w\t%0.s, %5/z, [%1, %2.s, sxtw]
251 1.1 mrg ld1w\t%0.s, %5/z, [%1, %2.s, uxtw]
252 1.1 mrg ld1w\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
253 1.1 mrg ld1w\t%0.s, %5/z, [%1, %2.s, uxtw %p4]"
254 1.1 mrg )
255 1.1 mrg
256 1.1 mrg ;; Predicated gather loads for 64-bit elements. The value of operand 3
257 1.1 mrg ;; doesn't matter in this case.
258 1.1 mrg (define_insn "mask_gather_load<mode>"
259 1.1 mrg [(set (match_operand:SVE_D 0 "register_operand" "=w, w, w")
260 1.1 mrg (unspec:SVE_D
261 1.1 mrg [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl")
262 1.1 mrg (match_operand:DI 1 "aarch64_reg_or_zero" "Z, rk, rk")
263 1.1 mrg (match_operand:<V_INT_EQUIV> 2 "register_operand" "w, w, w")
264 1.1 mrg (match_operand:DI 3 "const_int_operand")
265 1.1 mrg (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, Ui1, i")
266 1.1 mrg (mem:BLK (scratch))]
267 1.1 mrg UNSPEC_LD1_GATHER))]
268 1.1 mrg "TARGET_SVE"
269 1.1 mrg "@
270 1.1 mrg ld1d\t%0.d, %5/z, [%2.d]
271 1.1 mrg ld1d\t%0.d, %5/z, [%1, %2.d]
272 1.1 mrg ld1d\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
273 1.1 mrg )
274 1.1 mrg
275 1.1 mrg ;; Unpredicated scatter store.
276 1.1 mrg (define_expand "scatter_store<mode>"
277 1.1 mrg [(set (mem:BLK (scratch))
278 1.1 mrg (unspec:BLK
279 1.1 mrg [(match_dup 5)
280 1.1 mrg (match_operand:DI 0 "aarch64_reg_or_zero")
281 1.1 mrg (match_operand:<V_INT_EQUIV> 1 "register_operand")
282 1.1 mrg (match_operand:DI 2 "const_int_operand")
283 1.1 mrg (match_operand:DI 3 "aarch64_gather_scale_operand_<Vesize>")
284 1.1 mrg (match_operand:SVE_SD 4 "register_operand")]
285 1.1 mrg UNSPEC_ST1_SCATTER))]
286 1.1 mrg "TARGET_SVE"
287 1.1 mrg {
288 1.1 mrg operands[5] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
289 1.1 mrg }
290 1.1 mrg )
291 1.1 mrg
292 1.1 mrg ;; Predicated scatter stores for 32-bit elements. Operand 2 is true for
293 1.1 mrg ;; unsigned extension and false for signed extension.
294 1.1 mrg (define_insn "mask_scatter_store<mode>"
295 1.1 mrg [(set (mem:BLK (scratch))
296 1.1 mrg (unspec:BLK
297 1.1 mrg [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl, Upl, Upl")
298 1.1 mrg (match_operand:DI 0 "aarch64_reg_or_zero" "Z, rk, rk, rk, rk")
299 1.1 mrg (match_operand:<V_INT_EQUIV> 1 "register_operand" "w, w, w, w, w")
300 1.1 mrg (match_operand:DI 2 "const_int_operand" "i, Z, Ui1, Z, Ui1")
301 1.1 mrg (match_operand:DI 3 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, i, i")
302 1.1 mrg (match_operand:SVE_S 4 "register_operand" "w, w, w, w, w")]
303 1.1 mrg UNSPEC_ST1_SCATTER))]
304 1.1 mrg "TARGET_SVE"
305 1.1 mrg "@
306 1.1 mrg st1w\t%4.s, %5, [%1.s]
307 1.1 mrg st1w\t%4.s, %5, [%0, %1.s, sxtw]
308 1.1 mrg st1w\t%4.s, %5, [%0, %1.s, uxtw]
309 1.1 mrg st1w\t%4.s, %5, [%0, %1.s, sxtw %p3]
310 1.1 mrg st1w\t%4.s, %5, [%0, %1.s, uxtw %p3]"
311 1.1 mrg )
312 1.1 mrg
313 1.1 mrg ;; Predicated scatter stores for 64-bit elements. The value of operand 2
314 1.1 mrg ;; doesn't matter in this case.
315 1.1 mrg (define_insn "mask_scatter_store<mode>"
316 1.1 mrg [(set (mem:BLK (scratch))
317 1.1 mrg (unspec:BLK
318 1.1 mrg [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl")
319 1.1 mrg (match_operand:DI 0 "aarch64_reg_or_zero" "Z, rk, rk")
320 1.1 mrg (match_operand:<V_INT_EQUIV> 1 "register_operand" "w, w, w")
321 1.1 mrg (match_operand:DI 2 "const_int_operand")
322 1.1 mrg (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, Ui1, i")
323 1.1 mrg (match_operand:SVE_D 4 "register_operand" "w, w, w")]
324 1.1 mrg UNSPEC_ST1_SCATTER))]
325 1.1 mrg "TARGET_SVE"
326 1.1 mrg "@
327 1.1 mrg st1d\t%4.d, %5, [%1.d]
328 1.1 mrg st1d\t%4.d, %5, [%0, %1.d]
329 1.1 mrg st1d\t%4.d, %5, [%0, %1.d, lsl %p3]"
330 1.1 mrg )
331 1.1 mrg
332 1.1 mrg ;; SVE structure moves.
333 1.1 mrg (define_expand "mov<mode>"
334 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "nonimmediate_operand")
335 1.1 mrg (match_operand:SVE_STRUCT 1 "general_operand"))]
336 1.1 mrg "TARGET_SVE"
337 1.1 mrg {
338 1.1 mrg /* Big-endian loads and stores need to be done via LD1 and ST1;
339 1.1 mrg see the comment at the head of the file for details. */
340 1.1 mrg if ((MEM_P (operands[0]) || MEM_P (operands[1]))
341 1.1 mrg && BYTES_BIG_ENDIAN)
342 1.1 mrg {
343 1.1 mrg gcc_assert (can_create_pseudo_p ());
344 1.1 mrg aarch64_expand_sve_mem_move (operands[0], operands[1], <VPRED>mode);
345 1.1 mrg DONE;
346 1.1 mrg }
347 1.1 mrg
348 1.1 mrg if (CONSTANT_P (operands[1]))
349 1.1 mrg {
350 1.1 mrg aarch64_expand_mov_immediate (operands[0], operands[1]);
351 1.1 mrg DONE;
352 1.1 mrg }
353 1.1 mrg }
354 1.1 mrg )
355 1.1 mrg
356 1.1 mrg ;; Unpredicated structure moves (little-endian).
357 1.1 mrg (define_insn "*aarch64_sve_mov<mode>_le"
358 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "aarch64_sve_nonimmediate_operand" "=w, Utr, w, w")
359 1.1 mrg (match_operand:SVE_STRUCT 1 "aarch64_sve_general_operand" "Utr, w, w, Dn"))]
360 1.1 mrg "TARGET_SVE && !BYTES_BIG_ENDIAN"
361 1.1 mrg "#"
362 1.1 mrg [(set_attr "length" "<insn_length>")]
363 1.1 mrg )
364 1.1 mrg
365 1.1 mrg ;; Unpredicated structure moves (big-endian). Memory accesses require
366 1.1 mrg ;; secondary reloads.
367 1.1 mrg (define_insn "*aarch64_sve_mov<mode>_le"
368 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "register_operand" "=w, w")
369 1.1 mrg (match_operand:SVE_STRUCT 1 "aarch64_nonmemory_operand" "w, Dn"))]
370 1.1 mrg "TARGET_SVE && BYTES_BIG_ENDIAN"
371 1.1 mrg "#"
372 1.1 mrg [(set_attr "length" "<insn_length>")]
373 1.1 mrg )
374 1.1 mrg
375 1.1 mrg ;; Split unpredicated structure moves into pieces. This is the same
376 1.1 mrg ;; for both big-endian and little-endian code, although it only needs
377 1.1 mrg ;; to handle memory operands for little-endian code.
378 1.1 mrg (define_split
379 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "aarch64_sve_nonimmediate_operand")
380 1.1 mrg (match_operand:SVE_STRUCT 1 "aarch64_sve_general_operand"))]
381 1.1 mrg "TARGET_SVE && reload_completed"
382 1.1 mrg [(const_int 0)]
383 1.1 mrg {
384 1.1 mrg rtx dest = operands[0];
385 1.1 mrg rtx src = operands[1];
386 1.1 mrg if (REG_P (dest) && REG_P (src))
387 1.1 mrg aarch64_simd_emit_reg_reg_move (operands, <VSINGLE>mode, <vector_count>);
388 1.1 mrg else
389 1.1 mrg for (unsigned int i = 0; i < <vector_count>; ++i)
390 1.1 mrg {
391 1.1 mrg rtx subdest = simplify_gen_subreg (<VSINGLE>mode, dest, <MODE>mode,
392 1.1 mrg i * BYTES_PER_SVE_VECTOR);
393 1.1 mrg rtx subsrc = simplify_gen_subreg (<VSINGLE>mode, src, <MODE>mode,
394 1.1 mrg i * BYTES_PER_SVE_VECTOR);
395 1.1 mrg emit_insn (gen_rtx_SET (subdest, subsrc));
396 1.1 mrg }
397 1.1 mrg DONE;
398 1.1 mrg }
399 1.1 mrg )
400 1.1 mrg
401 1.1 mrg ;; Predicated structure moves. This works for both endiannesses but in
402 1.1 mrg ;; practice is only useful for big-endian.
403 1.1 mrg (define_insn_and_split "pred_mov<mode>"
404 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "aarch64_sve_struct_nonimmediate_operand" "=w, Utx")
405 1.1 mrg (unspec:SVE_STRUCT
406 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
407 1.1 mrg (match_operand:SVE_STRUCT 2 "aarch64_sve_struct_nonimmediate_operand" "Utx, w")]
408 1.1 mrg UNSPEC_MERGE_PTRUE))]
409 1.1 mrg "TARGET_SVE
410 1.1 mrg && (register_operand (operands[0], <MODE>mode)
411 1.1 mrg || register_operand (operands[2], <MODE>mode))"
412 1.1 mrg "#"
413 1.1 mrg "&& reload_completed"
414 1.1 mrg [(const_int 0)]
415 1.1 mrg {
416 1.1 mrg for (unsigned int i = 0; i < <vector_count>; ++i)
417 1.1 mrg {
418 1.1 mrg rtx subdest = simplify_gen_subreg (<VSINGLE>mode, operands[0],
419 1.1 mrg <MODE>mode,
420 1.1 mrg i * BYTES_PER_SVE_VECTOR);
421 1.1 mrg rtx subsrc = simplify_gen_subreg (<VSINGLE>mode, operands[2],
422 1.1 mrg <MODE>mode,
423 1.1 mrg i * BYTES_PER_SVE_VECTOR);
424 1.1 mrg aarch64_emit_sve_pred_move (subdest, operands[1], subsrc);
425 1.1 mrg }
426 1.1 mrg DONE;
427 1.1 mrg }
428 1.1 mrg [(set_attr "length" "<insn_length>")]
429 1.1 mrg )
430 1.1 mrg
431 1.1 mrg (define_expand "mov<mode>"
432 1.1 mrg [(set (match_operand:PRED_ALL 0 "nonimmediate_operand")
433 1.1 mrg (match_operand:PRED_ALL 1 "general_operand"))]
434 1.1 mrg "TARGET_SVE"
435 1.1 mrg {
436 1.1 mrg if (GET_CODE (operands[0]) == MEM)
437 1.1 mrg operands[1] = force_reg (<MODE>mode, operands[1]);
438 1.1 mrg }
439 1.1 mrg )
440 1.1 mrg
441 1.1 mrg (define_insn "*aarch64_sve_mov<mode>"
442 1.1 mrg [(set (match_operand:PRED_ALL 0 "nonimmediate_operand" "=Upa, m, Upa, Upa, Upa")
443 1.1 mrg (match_operand:PRED_ALL 1 "general_operand" "Upa, Upa, m, Dz, Dm"))]
444 1.1 mrg "TARGET_SVE
445 1.1 mrg && (register_operand (operands[0], <MODE>mode)
446 1.1 mrg || register_operand (operands[1], <MODE>mode))"
447 1.1 mrg "@
448 1.1 mrg mov\t%0.b, %1.b
449 1.1 mrg str\t%1, %0
450 1.1 mrg ldr\t%0, %1
451 1.1 mrg pfalse\t%0.b
452 1.1 mrg * return aarch64_output_ptrue (<MODE>mode, '<Vetype>');"
453 1.1 mrg )
454 1.1 mrg
455 1.1 mrg ;; Handle extractions from a predicate by converting to an integer vector
456 1.1 mrg ;; and extracting from there.
457 1.1 mrg (define_expand "vec_extract<vpred><Vel>"
458 1.1 mrg [(match_operand:<VEL> 0 "register_operand")
459 1.1 mrg (match_operand:<VPRED> 1 "register_operand")
460 1.1 mrg (match_operand:SI 2 "nonmemory_operand")
461 1.1 mrg ;; Dummy operand to which we can attach the iterator.
462 1.1 mrg (reg:SVE_I V0_REGNUM)]
463 1.1 mrg "TARGET_SVE"
464 1.1 mrg {
465 1.1 mrg rtx tmp = gen_reg_rtx (<MODE>mode);
466 1.1 mrg emit_insn (gen_aarch64_sve_dup<mode>_const (tmp, operands[1],
467 1.1 mrg CONST1_RTX (<MODE>mode),
468 1.1 mrg CONST0_RTX (<MODE>mode)));
469 1.1 mrg emit_insn (gen_vec_extract<mode><Vel> (operands[0], tmp, operands[2]));
470 1.1 mrg DONE;
471 1.1 mrg }
472 1.1 mrg )
473 1.1 mrg
474 1.1 mrg (define_expand "vec_extract<mode><Vel>"
475 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand")
476 1.1 mrg (vec_select:<VEL>
477 1.1 mrg (match_operand:SVE_ALL 1 "register_operand")
478 1.1 mrg (parallel [(match_operand:SI 2 "nonmemory_operand")])))]
479 1.1 mrg "TARGET_SVE"
480 1.1 mrg {
481 1.1 mrg poly_int64 val;
482 1.1 mrg if (poly_int_rtx_p (operands[2], &val)
483 1.1 mrg && known_eq (val, GET_MODE_NUNITS (<MODE>mode) - 1))
484 1.1 mrg {
485 1.1 mrg /* The last element can be extracted with a LASTB and a false
486 1.1 mrg predicate. */
487 1.1 mrg rtx sel = force_reg (<VPRED>mode, CONST0_RTX (<VPRED>mode));
488 1.1 mrg emit_insn (gen_extract_last_<mode> (operands[0], sel, operands[1]));
489 1.1 mrg DONE;
490 1.1 mrg }
491 1.1 mrg if (!CONST_INT_P (operands[2]))
492 1.1 mrg {
493 1.1 mrg /* Create an index with operand[2] as the base and -1 as the step.
494 1.1 mrg It will then be zero for the element we care about. */
495 1.1 mrg rtx index = gen_lowpart (<VEL_INT>mode, operands[2]);
496 1.1 mrg index = force_reg (<VEL_INT>mode, index);
497 1.1 mrg rtx series = gen_reg_rtx (<V_INT_EQUIV>mode);
498 1.1 mrg emit_insn (gen_vec_series<v_int_equiv> (series, index, constm1_rtx));
499 1.1 mrg
500 1.1 mrg /* Get a predicate that is true for only that element. */
501 1.1 mrg rtx zero = CONST0_RTX (<V_INT_EQUIV>mode);
502 1.1 mrg rtx cmp = gen_rtx_EQ (<V_INT_EQUIV>mode, series, zero);
503 1.1 mrg rtx sel = gen_reg_rtx (<VPRED>mode);
504 1.1 mrg emit_insn (gen_vec_cmp<v_int_equiv><vpred> (sel, cmp, series, zero));
505 1.1 mrg
506 1.1 mrg /* Select the element using LASTB. */
507 1.1 mrg emit_insn (gen_extract_last_<mode> (operands[0], sel, operands[1]));
508 1.1 mrg DONE;
509 1.1 mrg }
510 1.1 mrg }
511 1.1 mrg )
512 1.1 mrg
513 1.1 mrg ;; Extract element zero. This is a special case because we want to force
514 1.1 mrg ;; the registers to be the same for the second alternative, and then
515 1.1 mrg ;; split the instruction into nothing after RA.
516 1.1 mrg (define_insn_and_split "*vec_extract<mode><Vel>_0"
517 1.1 mrg [(set (match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand" "=r, w, Utv")
518 1.1 mrg (vec_select:<VEL>
519 1.1 mrg (match_operand:SVE_ALL 1 "register_operand" "w, 0, w")
520 1.1 mrg (parallel [(const_int 0)])))]
521 1.1 mrg "TARGET_SVE"
522 1.1 mrg {
523 1.1 mrg operands[1] = gen_rtx_REG (<V128>mode, REGNO (operands[1]));
524 1.1 mrg switch (which_alternative)
525 1.1 mrg {
526 1.1 mrg case 0:
527 1.1 mrg return "umov\\t%<vwcore>0, %1.<Vetype>[0]";
528 1.1 mrg case 1:
529 1.1 mrg return "#";
530 1.1 mrg case 2:
531 1.1 mrg return "st1\\t{%1.<Vetype>}[0], %0";
532 1.1 mrg default:
533 1.1 mrg gcc_unreachable ();
534 1.1 mrg }
535 1.1 mrg }
536 1.1 mrg "&& reload_completed
537 1.1 mrg && REG_P (operands[0])
538 1.1 mrg && REGNO (operands[0]) == REGNO (operands[1])"
539 1.1 mrg [(const_int 0)]
540 1.1 mrg {
541 1.1 mrg emit_note (NOTE_INSN_DELETED);
542 1.1 mrg DONE;
543 1.1 mrg }
544 1.1 mrg [(set_attr "type" "neon_to_gp_q, untyped, neon_store1_one_lane_q")]
545 1.1 mrg )
546 1.1 mrg
547 1.1 mrg ;; Extract an element from the Advanced SIMD portion of the register.
548 1.1 mrg ;; We don't just reuse the aarch64-simd.md pattern because we don't
549 1.1 mrg ;; want any change in lane number on big-endian targets.
550 1.1 mrg (define_insn "*vec_extract<mode><Vel>_v128"
551 1.1 mrg [(set (match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand" "=r, w, Utv")
552 1.1 mrg (vec_select:<VEL>
553 1.1 mrg (match_operand:SVE_ALL 1 "register_operand" "w, w, w")
554 1.1 mrg (parallel [(match_operand:SI 2 "const_int_operand")])))]
555 1.1 mrg "TARGET_SVE
556 1.1 mrg && IN_RANGE (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode), 1, 15)"
557 1.1 mrg {
558 1.1 mrg operands[1] = gen_rtx_REG (<V128>mode, REGNO (operands[1]));
559 1.1 mrg switch (which_alternative)
560 1.1 mrg {
561 1.1 mrg case 0:
562 1.1 mrg return "umov\\t%<vwcore>0, %1.<Vetype>[%2]";
563 1.1 mrg case 1:
564 1.1 mrg return "dup\\t%<Vetype>0, %1.<Vetype>[%2]";
565 1.1 mrg case 2:
566 1.1 mrg return "st1\\t{%1.<Vetype>}[%2], %0";
567 1.1 mrg default:
568 1.1 mrg gcc_unreachable ();
569 1.1 mrg }
570 1.1 mrg }
571 1.1 mrg [(set_attr "type" "neon_to_gp_q, neon_dup_q, neon_store1_one_lane_q")]
572 1.1 mrg )
573 1.1 mrg
574 1.1 mrg ;; Extract an element in the range of DUP. This pattern allows the
575 1.1 mrg ;; source and destination to be different.
576 1.1 mrg (define_insn "*vec_extract<mode><Vel>_dup"
577 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
578 1.1 mrg (vec_select:<VEL>
579 1.1 mrg (match_operand:SVE_ALL 1 "register_operand" "w")
580 1.1 mrg (parallel [(match_operand:SI 2 "const_int_operand")])))]
581 1.1 mrg "TARGET_SVE
582 1.1 mrg && IN_RANGE (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode), 16, 63)"
583 1.1 mrg {
584 1.1 mrg operands[0] = gen_rtx_REG (<MODE>mode, REGNO (operands[0]));
585 1.1 mrg return "dup\t%0.<Vetype>, %1.<Vetype>[%2]";
586 1.1 mrg }
587 1.1 mrg )
588 1.1 mrg
589 1.1 mrg ;; Extract an element outside the range of DUP. This pattern requires the
590 1.1 mrg ;; source and destination to be the same.
591 1.1 mrg (define_insn "*vec_extract<mode><Vel>_ext"
592 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
593 1.1 mrg (vec_select:<VEL>
594 1.1 mrg (match_operand:SVE_ALL 1 "register_operand" "0")
595 1.1 mrg (parallel [(match_operand:SI 2 "const_int_operand")])))]
596 1.1 mrg "TARGET_SVE && INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode) >= 64"
597 1.1 mrg {
598 1.1 mrg operands[0] = gen_rtx_REG (<MODE>mode, REGNO (operands[0]));
599 1.1 mrg operands[2] = GEN_INT (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode));
600 1.1 mrg return "ext\t%0.b, %0.b, %0.b, #%2";
601 1.1 mrg }
602 1.1 mrg )
603 1.1 mrg
604 1.1 mrg ;; Extract the last active element of operand 1 into operand 0.
605 1.1 mrg ;; If no elements are active, extract the last inactive element instead.
606 1.1 mrg (define_insn "extract_last_<mode>"
607 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=r, w")
608 1.1 mrg (unspec:<VEL>
609 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
610 1.1 mrg (match_operand:SVE_ALL 2 "register_operand" "w, w")]
611 1.1 mrg UNSPEC_LASTB))]
612 1.1 mrg "TARGET_SVE"
613 1.1 mrg "@
614 1.1 mrg lastb\t%<vwcore>0, %1, %2.<Vetype>
615 1.1 mrg lastb\t%<Vetype>0, %1, %2.<Vetype>"
616 1.1 mrg )
617 1.1 mrg
618 1.1 mrg (define_expand "vec_duplicate<mode>"
619 1.1 mrg [(parallel
620 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand")
621 1.1 mrg (vec_duplicate:SVE_ALL
622 1.1 mrg (match_operand:<VEL> 1 "aarch64_sve_dup_operand")))
623 1.1 mrg (clobber (scratch:<VPRED>))])]
624 1.1 mrg "TARGET_SVE"
625 1.1 mrg {
626 1.1 mrg if (MEM_P (operands[1]))
627 1.1 mrg {
628 1.1 mrg rtx ptrue = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
629 1.1 mrg emit_insn (gen_sve_ld1r<mode> (operands[0], ptrue, operands[1],
630 1.1 mrg CONST0_RTX (<MODE>mode)));
631 1.1 mrg DONE;
632 1.1 mrg }
633 1.1 mrg }
634 1.1 mrg )
635 1.1 mrg
636 1.1 mrg ;; Accept memory operands for the benefit of combine, and also in case
637 1.1 mrg ;; the scalar input gets spilled to memory during RA. We want to split
638 1.1 mrg ;; the load at the first opportunity in order to allow the PTRUE to be
639 1.1 mrg ;; optimized with surrounding code.
640 1.1 mrg (define_insn_and_split "*vec_duplicate<mode>_reg"
641 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w, w, w")
642 1.1 mrg (vec_duplicate:SVE_ALL
643 1.1 mrg (match_operand:<VEL> 1 "aarch64_sve_dup_operand" "r, w, Uty")))
644 1.1 mrg (clobber (match_scratch:<VPRED> 2 "=X, X, Upl"))]
645 1.1 mrg "TARGET_SVE"
646 1.1 mrg "@
647 1.1 mrg mov\t%0.<Vetype>, %<vwcore>1
648 1.1 mrg mov\t%0.<Vetype>, %<Vetype>1
649 1.1 mrg #"
650 1.1 mrg "&& MEM_P (operands[1])"
651 1.1 mrg [(const_int 0)]
652 1.1 mrg {
653 1.1 mrg if (GET_CODE (operands[2]) == SCRATCH)
654 1.1 mrg operands[2] = gen_reg_rtx (<VPRED>mode);
655 1.1 mrg emit_move_insn (operands[2], CONSTM1_RTX (<VPRED>mode));
656 1.1 mrg emit_insn (gen_sve_ld1r<mode> (operands[0], operands[2], operands[1],
657 1.1 mrg CONST0_RTX (<MODE>mode)));
658 1.1 mrg DONE;
659 1.1 mrg }
660 1.1 mrg [(set_attr "length" "4,4,8")]
661 1.1 mrg )
662 1.1 mrg
663 1.1 mrg ;; This is used for vec_duplicate<mode>s from memory, but can also
664 1.1 mrg ;; be used by combine to optimize selects of a a vec_duplicate<mode>
665 1.1 mrg ;; with zero.
666 1.1 mrg (define_insn "sve_ld1r<mode>"
667 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
668 1.1 mrg (unspec:SVE_ALL
669 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
670 1.1 mrg (vec_duplicate:SVE_ALL
671 1.1 mrg (match_operand:<VEL> 2 "aarch64_sve_ld1r_operand" "Uty"))
672 1.1 mrg (match_operand:SVE_ALL 3 "aarch64_simd_imm_zero")]
673 1.1 mrg UNSPEC_SEL))]
674 1.1 mrg "TARGET_SVE"
675 1.1 mrg "ld1r<Vesize>\t%0.<Vetype>, %1/z, %2"
676 1.1 mrg )
677 1.1 mrg
678 1.1 mrg ;; Load 128 bits from memory and duplicate to fill a vector. Since there
679 1.1 mrg ;; are so few operations on 128-bit "elements", we don't define a VNx1TI
680 1.1 mrg ;; and simply use vectors of bytes instead.
681 1.1 mrg (define_insn "*sve_ld1rq<Vesize>"
682 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
683 1.1 mrg (unspec:SVE_ALL
684 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
685 1.1 mrg (match_operand:TI 2 "aarch64_sve_ld1r_operand" "Uty")]
686 1.1 mrg UNSPEC_LD1RQ))]
687 1.1 mrg "TARGET_SVE"
688 1.1 mrg "ld1rq<Vesize>\t%0.<Vetype>, %1/z, %2"
689 1.1 mrg )
690 1.1 mrg
691 1.1 mrg ;; Implement a predicate broadcast by shifting the low bit of the scalar
692 1.1 mrg ;; input into the top bit and using a WHILELO. An alternative would be to
693 1.1 mrg ;; duplicate the input and do a compare with zero.
694 1.1 mrg (define_expand "vec_duplicate<mode>"
695 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand")
696 1.1 mrg (vec_duplicate:PRED_ALL (match_operand 1 "register_operand")))]
697 1.1 mrg "TARGET_SVE"
698 1.1 mrg {
699 1.1 mrg rtx tmp = gen_reg_rtx (DImode);
700 1.1 mrg rtx op1 = gen_lowpart (DImode, operands[1]);
701 1.1 mrg emit_insn (gen_ashldi3 (tmp, op1, gen_int_mode (63, DImode)));
702 1.1 mrg emit_insn (gen_while_ultdi<mode> (operands[0], const0_rtx, tmp));
703 1.1 mrg DONE;
704 1.1 mrg }
705 1.1 mrg )
706 1.1 mrg
707 1.1 mrg (define_insn "vec_series<mode>"
708 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w, w, w")
709 1.1 mrg (vec_series:SVE_I
710 1.1 mrg (match_operand:<VEL> 1 "aarch64_sve_index_operand" "Usi, r, r")
711 1.1 mrg (match_operand:<VEL> 2 "aarch64_sve_index_operand" "r, Usi, r")))]
712 1.1 mrg "TARGET_SVE"
713 1.1 mrg "@
714 1.1 mrg index\t%0.<Vetype>, #%1, %<vw>2
715 1.1 mrg index\t%0.<Vetype>, %<vw>1, #%2
716 1.1 mrg index\t%0.<Vetype>, %<vw>1, %<vw>2"
717 1.1 mrg )
718 1.1 mrg
719 1.1 mrg ;; Optimize {x, x, x, x, ...} + {0, n, 2*n, 3*n, ...} if n is in range
720 1.1 mrg ;; of an INDEX instruction.
721 1.1 mrg (define_insn "*vec_series<mode>_plus"
722 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w")
723 1.1 mrg (plus:SVE_I
724 1.1 mrg (vec_duplicate:SVE_I
725 1.1 mrg (match_operand:<VEL> 1 "register_operand" "r"))
726 1.1 mrg (match_operand:SVE_I 2 "immediate_operand")))]
727 1.1 mrg "TARGET_SVE && aarch64_check_zero_based_sve_index_immediate (operands[2])"
728 1.1 mrg {
729 1.1 mrg operands[2] = aarch64_check_zero_based_sve_index_immediate (operands[2]);
730 1.1 mrg return "index\t%0.<Vetype>, %<vw>1, #%2";
731 1.1 mrg }
732 1.1 mrg )
733 1.1 mrg
734 1.1 mrg ;; Unpredicated LD[234].
735 1.1 mrg (define_expand "vec_load_lanes<mode><vsingle>"
736 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "register_operand")
737 1.1 mrg (unspec:SVE_STRUCT
738 1.1 mrg [(match_dup 2)
739 1.1 mrg (match_operand:SVE_STRUCT 1 "memory_operand")]
740 1.1 mrg UNSPEC_LDN))]
741 1.1 mrg "TARGET_SVE"
742 1.1 mrg {
743 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
744 1.1 mrg }
745 1.1 mrg )
746 1.1 mrg
747 1.1 mrg ;; Predicated LD[234].
748 1.1 mrg (define_insn "vec_mask_load_lanes<mode><vsingle>"
749 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "register_operand" "=w")
750 1.1 mrg (unspec:SVE_STRUCT
751 1.1 mrg [(match_operand:<VPRED> 2 "register_operand" "Upl")
752 1.1 mrg (match_operand:SVE_STRUCT 1 "memory_operand" "m")]
753 1.1 mrg UNSPEC_LDN))]
754 1.1 mrg "TARGET_SVE"
755 1.1 mrg "ld<vector_count><Vesize>\t%0, %2/z, %1"
756 1.1 mrg )
757 1.1 mrg
758 1.1 mrg ;; Unpredicated ST[234]. This is always a full update, so the dependence
759 1.1 mrg ;; on the old value of the memory location (via (match_dup 0)) is redundant.
760 1.1 mrg ;; There doesn't seem to be any obvious benefit to treating the all-true
761 1.1 mrg ;; case differently though. In particular, it's very unlikely that we'll
762 1.1 mrg ;; only find out during RTL that a store_lanes is dead.
763 1.1 mrg (define_expand "vec_store_lanes<mode><vsingle>"
764 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "memory_operand")
765 1.1 mrg (unspec:SVE_STRUCT
766 1.1 mrg [(match_dup 2)
767 1.1 mrg (match_operand:SVE_STRUCT 1 "register_operand")
768 1.1 mrg (match_dup 0)]
769 1.1 mrg UNSPEC_STN))]
770 1.1 mrg "TARGET_SVE"
771 1.1 mrg {
772 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
773 1.1 mrg }
774 1.1 mrg )
775 1.1 mrg
776 1.1 mrg ;; Predicated ST[234].
777 1.1 mrg (define_insn "vec_mask_store_lanes<mode><vsingle>"
778 1.1 mrg [(set (match_operand:SVE_STRUCT 0 "memory_operand" "+m")
779 1.1 mrg (unspec:SVE_STRUCT
780 1.1 mrg [(match_operand:<VPRED> 2 "register_operand" "Upl")
781 1.1 mrg (match_operand:SVE_STRUCT 1 "register_operand" "w")
782 1.1 mrg (match_dup 0)]
783 1.1 mrg UNSPEC_STN))]
784 1.1 mrg "TARGET_SVE"
785 1.1 mrg "st<vector_count><Vesize>\t%1, %2, %0"
786 1.1 mrg )
787 1.1 mrg
788 1.1 mrg (define_expand "vec_perm<mode>"
789 1.1 mrg [(match_operand:SVE_ALL 0 "register_operand")
790 1.1 mrg (match_operand:SVE_ALL 1 "register_operand")
791 1.1 mrg (match_operand:SVE_ALL 2 "register_operand")
792 1.1 mrg (match_operand:<V_INT_EQUIV> 3 "aarch64_sve_vec_perm_operand")]
793 1.1 mrg "TARGET_SVE && GET_MODE_NUNITS (<MODE>mode).is_constant ()"
794 1.1 mrg {
795 1.1 mrg aarch64_expand_sve_vec_perm (operands[0], operands[1],
796 1.1 mrg operands[2], operands[3]);
797 1.1 mrg DONE;
798 1.1 mrg }
799 1.1 mrg )
800 1.1 mrg
801 1.1 mrg (define_insn "*aarch64_sve_tbl<mode>"
802 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
803 1.1 mrg (unspec:SVE_ALL
804 1.1 mrg [(match_operand:SVE_ALL 1 "register_operand" "w")
805 1.1 mrg (match_operand:<V_INT_EQUIV> 2 "register_operand" "w")]
806 1.1 mrg UNSPEC_TBL))]
807 1.1 mrg "TARGET_SVE"
808 1.1 mrg "tbl\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
809 1.1 mrg )
810 1.1 mrg
811 1.1 mrg (define_insn "*aarch64_sve_<perm_insn><perm_hilo><mode>"
812 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
813 1.1 mrg (unspec:PRED_ALL [(match_operand:PRED_ALL 1 "register_operand" "Upa")
814 1.1 mrg (match_operand:PRED_ALL 2 "register_operand" "Upa")]
815 1.1 mrg PERMUTE))]
816 1.1 mrg "TARGET_SVE"
817 1.1 mrg "<perm_insn><perm_hilo>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
818 1.1 mrg )
819 1.1 mrg
820 1.1 mrg (define_insn "aarch64_sve_<perm_insn><perm_hilo><mode>"
821 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
822 1.1 mrg (unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "w")
823 1.1 mrg (match_operand:SVE_ALL 2 "register_operand" "w")]
824 1.1 mrg PERMUTE))]
825 1.1 mrg "TARGET_SVE"
826 1.1 mrg "<perm_insn><perm_hilo>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
827 1.1 mrg )
828 1.1 mrg
829 1.1 mrg (define_insn "*aarch64_sve_rev64<mode>"
830 1.1 mrg [(set (match_operand:SVE_BHS 0 "register_operand" "=w")
831 1.1 mrg (unspec:SVE_BHS
832 1.1 mrg [(match_operand:VNx2BI 1 "register_operand" "Upl")
833 1.1 mrg (unspec:SVE_BHS [(match_operand:SVE_BHS 2 "register_operand" "w")]
834 1.1 mrg UNSPEC_REV64)]
835 1.1 mrg UNSPEC_MERGE_PTRUE))]
836 1.1 mrg "TARGET_SVE"
837 1.1 mrg "rev<Vesize>\t%0.d, %1/m, %2.d"
838 1.1 mrg )
839 1.1 mrg
840 1.1 mrg (define_insn "*aarch64_sve_rev32<mode>"
841 1.1 mrg [(set (match_operand:SVE_BH 0 "register_operand" "=w")
842 1.1 mrg (unspec:SVE_BH
843 1.1 mrg [(match_operand:VNx4BI 1 "register_operand" "Upl")
844 1.1 mrg (unspec:SVE_BH [(match_operand:SVE_BH 2 "register_operand" "w")]
845 1.1 mrg UNSPEC_REV32)]
846 1.1 mrg UNSPEC_MERGE_PTRUE))]
847 1.1 mrg "TARGET_SVE"
848 1.1 mrg "rev<Vesize>\t%0.s, %1/m, %2.s"
849 1.1 mrg )
850 1.1 mrg
851 1.1 mrg (define_insn "*aarch64_sve_rev16vnx16qi"
852 1.1 mrg [(set (match_operand:VNx16QI 0 "register_operand" "=w")
853 1.1 mrg (unspec:VNx16QI
854 1.1 mrg [(match_operand:VNx8BI 1 "register_operand" "Upl")
855 1.1 mrg (unspec:VNx16QI [(match_operand:VNx16QI 2 "register_operand" "w")]
856 1.1 mrg UNSPEC_REV16)]
857 1.1 mrg UNSPEC_MERGE_PTRUE))]
858 1.1 mrg "TARGET_SVE"
859 1.1 mrg "revb\t%0.h, %1/m, %2.h"
860 1.1 mrg )
861 1.1 mrg
862 1.1 mrg (define_insn "*aarch64_sve_rev<mode>"
863 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
864 1.1 mrg (unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "w")]
865 1.1 mrg UNSPEC_REV))]
866 1.1 mrg "TARGET_SVE"
867 1.1 mrg "rev\t%0.<Vetype>, %1.<Vetype>")
868 1.1 mrg
869 1.1 mrg (define_insn "*aarch64_sve_dup_lane<mode>"
870 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
871 1.1 mrg (vec_duplicate:SVE_ALL
872 1.1 mrg (vec_select:<VEL>
873 1.1 mrg (match_operand:SVE_ALL 1 "register_operand" "w")
874 1.1 mrg (parallel [(match_operand:SI 2 "const_int_operand")]))))]
875 1.1 mrg "TARGET_SVE
876 1.1 mrg && IN_RANGE (INTVAL (operands[2]) * GET_MODE_SIZE (<VEL>mode), 0, 63)"
877 1.1 mrg "dup\t%0.<Vetype>, %1.<Vetype>[%2]"
878 1.1 mrg )
879 1.1 mrg
880 1.1 mrg ;; Note that the immediate (third) operand is the lane index not
881 1.1 mrg ;; the byte index.
882 1.1 mrg (define_insn "*aarch64_sve_ext<mode>"
883 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
884 1.1 mrg (unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "0")
885 1.1 mrg (match_operand:SVE_ALL 2 "register_operand" "w")
886 1.1 mrg (match_operand:SI 3 "const_int_operand")]
887 1.1 mrg UNSPEC_EXT))]
888 1.1 mrg "TARGET_SVE
889 1.1 mrg && IN_RANGE (INTVAL (operands[3]) * GET_MODE_SIZE (<VEL>mode), 0, 255)"
890 1.1 mrg {
891 1.1 mrg operands[3] = GEN_INT (INTVAL (operands[3]) * GET_MODE_SIZE (<VEL>mode));
892 1.1 mrg return "ext\\t%0.b, %0.b, %2.b, #%3";
893 1.1 mrg }
894 1.1 mrg )
895 1.1 mrg
896 1.1 mrg (define_insn "add<mode>3"
897 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w, w, w, w")
898 1.1 mrg (plus:SVE_I
899 1.1 mrg (match_operand:SVE_I 1 "register_operand" "%0, 0, 0, w")
900 1.1 mrg (match_operand:SVE_I 2 "aarch64_sve_add_operand" "vsa, vsn, vsi, w")))]
901 1.1 mrg "TARGET_SVE"
902 1.1 mrg "@
903 1.1 mrg add\t%0.<Vetype>, %0.<Vetype>, #%D2
904 1.1 mrg sub\t%0.<Vetype>, %0.<Vetype>, #%N2
905 1.1 mrg * return aarch64_output_sve_inc_dec_immediate (\"%0.<Vetype>\", operands[2]);
906 1.1 mrg add\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
907 1.1 mrg )
908 1.1 mrg
909 1.1 mrg (define_insn "sub<mode>3"
910 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w, w")
911 1.1 mrg (minus:SVE_I
912 1.1 mrg (match_operand:SVE_I 1 "aarch64_sve_arith_operand" "w, vsa")
913 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w, 0")))]
914 1.1 mrg "TARGET_SVE"
915 1.1 mrg "@
916 1.1 mrg sub\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>
917 1.1 mrg subr\t%0.<Vetype>, %0.<Vetype>, #%D1"
918 1.1 mrg )
919 1.1 mrg
920 1.1 mrg ;; Unpredicated multiplication.
921 1.1 mrg (define_expand "mul<mode>3"
922 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand")
923 1.1 mrg (unspec:SVE_I
924 1.1 mrg [(match_dup 3)
925 1.1 mrg (mult:SVE_I
926 1.1 mrg (match_operand:SVE_I 1 "register_operand")
927 1.1 mrg (match_operand:SVE_I 2 "aarch64_sve_mul_operand"))]
928 1.1 mrg UNSPEC_MERGE_PTRUE))]
929 1.1 mrg "TARGET_SVE"
930 1.1 mrg {
931 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
932 1.1 mrg }
933 1.1 mrg )
934 1.1 mrg
935 1.1 mrg ;; Multiplication predicated with a PTRUE. We don't actually need the
936 1.1 mrg ;; predicate for the first alternative, but using Upa or X isn't likely
937 1.1 mrg ;; to gain much and would make the instruction seem less uniform to the
938 1.1 mrg ;; register allocator.
939 1.1 mrg (define_insn "*mul<mode>3"
940 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w, w")
941 1.1 mrg (unspec:SVE_I
942 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
943 1.1 mrg (mult:SVE_I
944 1.1 mrg (match_operand:SVE_I 2 "register_operand" "%0, 0")
945 1.1 mrg (match_operand:SVE_I 3 "aarch64_sve_mul_operand" "vsm, w"))]
946 1.1 mrg UNSPEC_MERGE_PTRUE))]
947 1.1 mrg "TARGET_SVE"
948 1.1 mrg "@
949 1.1 mrg mul\t%0.<Vetype>, %0.<Vetype>, #%3
950 1.1 mrg mul\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
951 1.1 mrg )
952 1.1 mrg
953 1.1 mrg (define_insn "*madd<mode>"
954 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w, w")
955 1.1 mrg (plus:SVE_I
956 1.1 mrg (unspec:SVE_I
957 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
958 1.1 mrg (mult:SVE_I (match_operand:SVE_I 2 "register_operand" "%0, w")
959 1.1 mrg (match_operand:SVE_I 3 "register_operand" "w, w"))]
960 1.1 mrg UNSPEC_MERGE_PTRUE)
961 1.1 mrg (match_operand:SVE_I 4 "register_operand" "w, 0")))]
962 1.1 mrg "TARGET_SVE"
963 1.1 mrg "@
964 1.1 mrg mad\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
965 1.1 mrg mla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>"
966 1.1 mrg )
967 1.1 mrg
968 1.1 mrg (define_insn "*msub<mode>3"
969 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w, w")
970 1.1 mrg (minus:SVE_I
971 1.1 mrg (match_operand:SVE_I 4 "register_operand" "w, 0")
972 1.1 mrg (unspec:SVE_I
973 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
974 1.1 mrg (mult:SVE_I (match_operand:SVE_I 2 "register_operand" "%0, w")
975 1.1 mrg (match_operand:SVE_I 3 "register_operand" "w, w"))]
976 1.1 mrg UNSPEC_MERGE_PTRUE)))]
977 1.1 mrg "TARGET_SVE"
978 1.1 mrg "@
979 1.1 mrg msb\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>
980 1.1 mrg mls\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>"
981 1.1 mrg )
982 1.1 mrg
983 1.1 mrg ;; Unpredicated highpart multiplication.
984 1.1 mrg (define_expand "<su>mul<mode>3_highpart"
985 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand")
986 1.1 mrg (unspec:SVE_I
987 1.1 mrg [(match_dup 3)
988 1.1 mrg (unspec:SVE_I [(match_operand:SVE_I 1 "register_operand")
989 1.1 mrg (match_operand:SVE_I 2 "register_operand")]
990 1.1 mrg MUL_HIGHPART)]
991 1.1 mrg UNSPEC_MERGE_PTRUE))]
992 1.1 mrg "TARGET_SVE"
993 1.1 mrg {
994 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
995 1.1 mrg }
996 1.1 mrg )
997 1.1 mrg
998 1.1 mrg ;; Predicated highpart multiplication.
999 1.1 mrg (define_insn "*<su>mul<mode>3_highpart"
1000 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w")
1001 1.1 mrg (unspec:SVE_I
1002 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
1003 1.1 mrg (unspec:SVE_I [(match_operand:SVE_I 2 "register_operand" "%0")
1004 1.1 mrg (match_operand:SVE_I 3 "register_operand" "w")]
1005 1.1 mrg MUL_HIGHPART)]
1006 1.1 mrg UNSPEC_MERGE_PTRUE))]
1007 1.1 mrg "TARGET_SVE"
1008 1.1 mrg "<su>mulh\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
1009 1.1 mrg )
1010 1.1 mrg
1011 1.1 mrg ;; Unpredicated NEG, NOT and POPCOUNT.
1012 1.1 mrg (define_expand "<optab><mode>2"
1013 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand")
1014 1.1 mrg (unspec:SVE_I
1015 1.1 mrg [(match_dup 2)
1016 1.1 mrg (SVE_INT_UNARY:SVE_I (match_operand:SVE_I 1 "register_operand"))]
1017 1.1 mrg UNSPEC_MERGE_PTRUE))]
1018 1.1 mrg "TARGET_SVE"
1019 1.1 mrg {
1020 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1021 1.1 mrg }
1022 1.1 mrg )
1023 1.1 mrg
1024 1.1 mrg ;; NEG, NOT and POPCOUNT predicated with a PTRUE.
1025 1.1 mrg (define_insn "*<optab><mode>2"
1026 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w")
1027 1.1 mrg (unspec:SVE_I
1028 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
1029 1.1 mrg (SVE_INT_UNARY:SVE_I
1030 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w"))]
1031 1.1 mrg UNSPEC_MERGE_PTRUE))]
1032 1.1 mrg "TARGET_SVE"
1033 1.1 mrg "<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
1034 1.1 mrg )
1035 1.1 mrg
1036 1.1 mrg ;; Vector AND, ORR and XOR.
1037 1.1 mrg (define_insn "<optab><mode>3"
1038 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w, w")
1039 1.1 mrg (LOGICAL:SVE_I
1040 1.1 mrg (match_operand:SVE_I 1 "register_operand" "%0, w")
1041 1.1 mrg (match_operand:SVE_I 2 "aarch64_sve_logical_operand" "vsl, w")))]
1042 1.1 mrg "TARGET_SVE"
1043 1.1 mrg "@
1044 1.1 mrg <logical>\t%0.<Vetype>, %0.<Vetype>, #%C2
1045 1.1 mrg <logical>\t%0.d, %1.d, %2.d"
1046 1.1 mrg )
1047 1.1 mrg
1048 1.1 mrg ;; Vector AND, ORR and XOR on floating-point modes. We avoid subregs
1049 1.1 mrg ;; by providing this, but we need to use UNSPECs since rtx logical ops
1050 1.1 mrg ;; aren't defined for floating-point modes.
1051 1.1 mrg (define_insn "*<optab><mode>3"
1052 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w")
1053 1.1 mrg (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "w")
1054 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w")]
1055 1.1 mrg LOGICALF))]
1056 1.1 mrg "TARGET_SVE"
1057 1.1 mrg "<logicalf_op>\t%0.d, %1.d, %2.d"
1058 1.1 mrg )
1059 1.1 mrg
1060 1.1 mrg ;; REG_EQUAL notes on "not<mode>3" should ensure that we can generate
1061 1.1 mrg ;; this pattern even though the NOT instruction itself is predicated.
1062 1.1 mrg (define_insn "bic<mode>3"
1063 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w")
1064 1.1 mrg (and:SVE_I
1065 1.1 mrg (not:SVE_I (match_operand:SVE_I 1 "register_operand" "w"))
1066 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w")))]
1067 1.1 mrg "TARGET_SVE"
1068 1.1 mrg "bic\t%0.d, %2.d, %1.d"
1069 1.1 mrg )
1070 1.1 mrg
1071 1.1 mrg ;; Predicate AND. We can reuse one of the inputs as the GP.
1072 1.1 mrg (define_insn "and<mode>3"
1073 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
1074 1.1 mrg (and:PRED_ALL (match_operand:PRED_ALL 1 "register_operand" "Upa")
1075 1.1 mrg (match_operand:PRED_ALL 2 "register_operand" "Upa")))]
1076 1.1 mrg "TARGET_SVE"
1077 1.1 mrg "and\t%0.b, %1/z, %1.b, %2.b"
1078 1.1 mrg )
1079 1.1 mrg
1080 1.1 mrg ;; Unpredicated predicate ORR and XOR.
1081 1.1 mrg (define_expand "<optab><mode>3"
1082 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand")
1083 1.1 mrg (and:PRED_ALL
1084 1.1 mrg (LOGICAL_OR:PRED_ALL
1085 1.1 mrg (match_operand:PRED_ALL 1 "register_operand")
1086 1.1 mrg (match_operand:PRED_ALL 2 "register_operand"))
1087 1.1 mrg (match_dup 3)))]
1088 1.1 mrg "TARGET_SVE"
1089 1.1 mrg {
1090 1.1 mrg operands[3] = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
1091 1.1 mrg }
1092 1.1 mrg )
1093 1.1 mrg
1094 1.1 mrg ;; Predicated predicate ORR and XOR.
1095 1.1 mrg (define_insn "pred_<optab><mode>3"
1096 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
1097 1.1 mrg (and:PRED_ALL
1098 1.1 mrg (LOGICAL:PRED_ALL
1099 1.1 mrg (match_operand:PRED_ALL 2 "register_operand" "Upa")
1100 1.1 mrg (match_operand:PRED_ALL 3 "register_operand" "Upa"))
1101 1.1 mrg (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
1102 1.1 mrg "TARGET_SVE"
1103 1.1 mrg "<logical>\t%0.b, %1/z, %2.b, %3.b"
1104 1.1 mrg )
1105 1.1 mrg
1106 1.1 mrg ;; Perform a logical operation on operands 2 and 3, using operand 1 as
1107 1.1 mrg ;; the GP (which is known to be a PTRUE). Store the result in operand 0
1108 1.1 mrg ;; and set the flags in the same way as for PTEST. The (and ...) in the
1109 1.1 mrg ;; UNSPEC_PTEST_PTRUE is logically redundant, but means that the tested
1110 1.1 mrg ;; value is structurally equivalent to rhs of the second set.
1111 1.1 mrg (define_insn "*<optab><mode>3_cc"
1112 1.1 mrg [(set (reg:CC CC_REGNUM)
1113 1.1 mrg (compare:CC
1114 1.1 mrg (unspec:SI [(match_operand:PRED_ALL 1 "register_operand" "Upa")
1115 1.1 mrg (and:PRED_ALL
1116 1.1 mrg (LOGICAL:PRED_ALL
1117 1.1 mrg (match_operand:PRED_ALL 2 "register_operand" "Upa")
1118 1.1 mrg (match_operand:PRED_ALL 3 "register_operand" "Upa"))
1119 1.1 mrg (match_dup 1))]
1120 1.1 mrg UNSPEC_PTEST_PTRUE)
1121 1.1 mrg (const_int 0)))
1122 1.1 mrg (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
1123 1.1 mrg (and:PRED_ALL (LOGICAL:PRED_ALL (match_dup 2) (match_dup 3))
1124 1.1 mrg (match_dup 1)))]
1125 1.1 mrg "TARGET_SVE"
1126 1.1 mrg "<logical>s\t%0.b, %1/z, %2.b, %3.b"
1127 1.1 mrg )
1128 1.1 mrg
1129 1.1 mrg ;; Unpredicated predicate inverse.
1130 1.1 mrg (define_expand "one_cmpl<mode>2"
1131 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand")
1132 1.1 mrg (and:PRED_ALL
1133 1.1 mrg (not:PRED_ALL (match_operand:PRED_ALL 1 "register_operand"))
1134 1.1 mrg (match_dup 2)))]
1135 1.1 mrg "TARGET_SVE"
1136 1.1 mrg {
1137 1.1 mrg operands[2] = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
1138 1.1 mrg }
1139 1.1 mrg )
1140 1.1 mrg
1141 1.1 mrg ;; Predicated predicate inverse.
1142 1.1 mrg (define_insn "*one_cmpl<mode>3"
1143 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
1144 1.1 mrg (and:PRED_ALL
1145 1.1 mrg (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand" "Upa"))
1146 1.1 mrg (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
1147 1.1 mrg "TARGET_SVE"
1148 1.1 mrg "not\t%0.b, %1/z, %2.b"
1149 1.1 mrg )
1150 1.1 mrg
1151 1.1 mrg ;; Predicated predicate BIC and ORN.
1152 1.1 mrg (define_insn "*<nlogical><mode>3"
1153 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
1154 1.1 mrg (and:PRED_ALL
1155 1.1 mrg (NLOGICAL:PRED_ALL
1156 1.1 mrg (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand" "Upa"))
1157 1.1 mrg (match_operand:PRED_ALL 3 "register_operand" "Upa"))
1158 1.1 mrg (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
1159 1.1 mrg "TARGET_SVE"
1160 1.1 mrg "<nlogical>\t%0.b, %1/z, %3.b, %2.b"
1161 1.1 mrg )
1162 1.1 mrg
1163 1.1 mrg ;; Predicated predicate NAND and NOR.
1164 1.1 mrg (define_insn "*<logical_nn><mode>3"
1165 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
1166 1.1 mrg (and:PRED_ALL
1167 1.1 mrg (NLOGICAL:PRED_ALL
1168 1.1 mrg (not:PRED_ALL (match_operand:PRED_ALL 2 "register_operand" "Upa"))
1169 1.1 mrg (not:PRED_ALL (match_operand:PRED_ALL 3 "register_operand" "Upa")))
1170 1.1 mrg (match_operand:PRED_ALL 1 "register_operand" "Upa")))]
1171 1.1 mrg "TARGET_SVE"
1172 1.1 mrg "<logical_nn>\t%0.b, %1/z, %2.b, %3.b"
1173 1.1 mrg )
1174 1.1 mrg
1175 1.1 mrg ;; Unpredicated LSL, LSR and ASR by a vector.
1176 1.1 mrg (define_expand "v<optab><mode>3"
1177 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand")
1178 1.1 mrg (unspec:SVE_I
1179 1.1 mrg [(match_dup 3)
1180 1.1 mrg (ASHIFT:SVE_I
1181 1.1 mrg (match_operand:SVE_I 1 "register_operand")
1182 1.1 mrg (match_operand:SVE_I 2 "aarch64_sve_<lr>shift_operand"))]
1183 1.1 mrg UNSPEC_MERGE_PTRUE))]
1184 1.1 mrg "TARGET_SVE"
1185 1.1 mrg {
1186 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1187 1.1 mrg }
1188 1.1 mrg )
1189 1.1 mrg
1190 1.1 mrg ;; LSL, LSR and ASR by a vector, predicated with a PTRUE. We don't
1191 1.1 mrg ;; actually need the predicate for the first alternative, but using Upa
1192 1.1 mrg ;; or X isn't likely to gain much and would make the instruction seem
1193 1.1 mrg ;; less uniform to the register allocator.
1194 1.1 mrg (define_insn "*v<optab><mode>3"
1195 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w, w")
1196 1.1 mrg (unspec:SVE_I
1197 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1198 1.1 mrg (ASHIFT:SVE_I
1199 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w, 0")
1200 1.1 mrg (match_operand:SVE_I 3 "aarch64_sve_<lr>shift_operand" "D<lr>, w"))]
1201 1.1 mrg UNSPEC_MERGE_PTRUE))]
1202 1.1 mrg "TARGET_SVE"
1203 1.1 mrg "@
1204 1.1 mrg <shift>\t%0.<Vetype>, %2.<Vetype>, #%3
1205 1.1 mrg <shift>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
1206 1.1 mrg )
1207 1.1 mrg
1208 1.1 mrg ;; LSL, LSR and ASR by a scalar, which expands into one of the vector
1209 1.1 mrg ;; shifts above.
1210 1.1 mrg (define_expand "<ASHIFT:optab><mode>3"
1211 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand")
1212 1.1 mrg (ASHIFT:SVE_I (match_operand:SVE_I 1 "register_operand")
1213 1.1 mrg (match_operand:<VEL> 2 "general_operand")))]
1214 1.1 mrg "TARGET_SVE"
1215 1.1 mrg {
1216 1.1 mrg rtx amount;
1217 1.1 mrg if (CONST_INT_P (operands[2]))
1218 1.1 mrg {
1219 1.1 mrg amount = gen_const_vec_duplicate (<MODE>mode, operands[2]);
1220 1.1 mrg if (!aarch64_sve_<lr>shift_operand (operands[2], <MODE>mode))
1221 1.1 mrg amount = force_reg (<MODE>mode, amount);
1222 1.1 mrg }
1223 1.1 mrg else
1224 1.1 mrg {
1225 1.1 mrg amount = gen_reg_rtx (<MODE>mode);
1226 1.1 mrg emit_insn (gen_vec_duplicate<mode> (amount,
1227 1.1 mrg convert_to_mode (<VEL>mode,
1228 1.1 mrg operands[2], 0)));
1229 1.1 mrg }
1230 1.1 mrg emit_insn (gen_v<optab><mode>3 (operands[0], operands[1], amount));
1231 1.1 mrg DONE;
1232 1.1 mrg }
1233 1.1 mrg )
1234 1.1 mrg
1235 1.1 mrg ;; Test all bits of operand 1. Operand 0 is a GP that is known to hold PTRUE.
1236 1.1 mrg ;;
1237 1.1 mrg ;; Using UNSPEC_PTEST_PTRUE allows combine patterns to assume that the GP
1238 1.1 mrg ;; is a PTRUE even if the optimizers haven't yet been able to propagate
1239 1.1 mrg ;; the constant. We would use a separate unspec code for PTESTs involving
1240 1.1 mrg ;; GPs that might not be PTRUEs.
1241 1.1 mrg (define_insn "ptest_ptrue<mode>"
1242 1.1 mrg [(set (reg:CC CC_REGNUM)
1243 1.1 mrg (compare:CC
1244 1.1 mrg (unspec:SI [(match_operand:PRED_ALL 0 "register_operand" "Upa")
1245 1.1 mrg (match_operand:PRED_ALL 1 "register_operand" "Upa")]
1246 1.1 mrg UNSPEC_PTEST_PTRUE)
1247 1.1 mrg (const_int 0)))]
1248 1.1 mrg "TARGET_SVE"
1249 1.1 mrg "ptest\t%0, %1.b"
1250 1.1 mrg )
1251 1.1 mrg
1252 1.1 mrg ;; Set element I of the result if operand1 + J < operand2 for all J in [0, I].
1253 1.1 mrg ;; with the comparison being unsigned.
1254 1.1 mrg (define_insn "while_ult<GPI:mode><PRED_ALL:mode>"
1255 1.1 mrg [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
1256 1.1 mrg (unspec:PRED_ALL [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
1257 1.1 mrg (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
1258 1.1 mrg UNSPEC_WHILE_LO))
1259 1.1 mrg (clobber (reg:CC CC_REGNUM))]
1260 1.1 mrg "TARGET_SVE"
1261 1.1 mrg "whilelo\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
1262 1.1 mrg )
1263 1.1 mrg
1264 1.1 mrg ;; WHILELO sets the flags in the same way as a PTEST with a PTRUE GP.
1265 1.1 mrg ;; Handle the case in which both results are useful. The GP operand
1266 1.1 mrg ;; to the PTEST isn't needed, so we allow it to be anything.
1267 1.1 mrg (define_insn_and_split "while_ult<GPI:mode><PRED_ALL:mode>_cc"
1268 1.1 mrg [(set (reg:CC CC_REGNUM)
1269 1.1 mrg (compare:CC
1270 1.1 mrg (unspec:SI [(match_operand:PRED_ALL 1)
1271 1.1 mrg (unspec:PRED_ALL
1272 1.1 mrg [(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")
1273 1.1 mrg (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")]
1274 1.1 mrg UNSPEC_WHILE_LO)]
1275 1.1 mrg UNSPEC_PTEST_PTRUE)
1276 1.1 mrg (const_int 0)))
1277 1.1 mrg (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
1278 1.1 mrg (unspec:PRED_ALL [(match_dup 2)
1279 1.1 mrg (match_dup 3)]
1280 1.1 mrg UNSPEC_WHILE_LO))]
1281 1.1 mrg "TARGET_SVE"
1282 1.1 mrg "whilelo\t%0.<PRED_ALL:Vetype>, %<w>2, %<w>3"
1283 1.1 mrg ;; Force the compiler to drop the unused predicate operand, so that we
1284 1.1 mrg ;; don't have an unnecessary PTRUE.
1285 1.1 mrg "&& !CONSTANT_P (operands[1])"
1286 1.1 mrg [(const_int 0)]
1287 1.1 mrg {
1288 1.1 mrg emit_insn (gen_while_ult<GPI:mode><PRED_ALL:mode>_cc
1289 1.1 mrg (operands[0], CONSTM1_RTX (<MODE>mode),
1290 1.1 mrg operands[2], operands[3]));
1291 1.1 mrg DONE;
1292 1.1 mrg }
1293 1.1 mrg )
1294 1.1 mrg
1295 1.1 mrg ;; Predicated integer comparison.
1296 1.1 mrg (define_insn "*vec_cmp<cmp_op>_<mode>"
1297 1.1 mrg [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
1298 1.1 mrg (unspec:<VPRED>
1299 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1300 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w, w")
1301 1.1 mrg (match_operand:SVE_I 3 "aarch64_sve_cmp_<imm_con>_operand" "<imm_con>, w")]
1302 1.1 mrg SVE_COND_INT_CMP))
1303 1.1 mrg (clobber (reg:CC CC_REGNUM))]
1304 1.1 mrg "TARGET_SVE"
1305 1.1 mrg "@
1306 1.1 mrg cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
1307 1.1 mrg cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
1308 1.1 mrg )
1309 1.1 mrg
1310 1.1 mrg ;; Predicated integer comparison in which only the flags result is interesting.
1311 1.1 mrg (define_insn "*vec_cmp<cmp_op>_<mode>_ptest"
1312 1.1 mrg [(set (reg:CC CC_REGNUM)
1313 1.1 mrg (compare:CC
1314 1.1 mrg (unspec:SI
1315 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1316 1.1 mrg (unspec:<VPRED>
1317 1.1 mrg [(match_dup 1)
1318 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w, w")
1319 1.1 mrg (match_operand:SVE_I 3 "aarch64_sve_cmp_<imm_con>_operand" "<imm_con>, w")]
1320 1.1 mrg SVE_COND_INT_CMP)]
1321 1.1 mrg UNSPEC_PTEST_PTRUE)
1322 1.1 mrg (const_int 0)))
1323 1.1 mrg (clobber (match_scratch:<VPRED> 0 "=Upa, Upa"))]
1324 1.1 mrg "TARGET_SVE"
1325 1.1 mrg "@
1326 1.1 mrg cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
1327 1.1 mrg cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
1328 1.1 mrg )
1329 1.1 mrg
1330 1.1 mrg ;; Predicated comparison in which both the flag and predicate results
1331 1.1 mrg ;; are interesting.
1332 1.1 mrg (define_insn "*vec_cmp<cmp_op>_<mode>_cc"
1333 1.1 mrg [(set (reg:CC CC_REGNUM)
1334 1.1 mrg (compare:CC
1335 1.1 mrg (unspec:SI
1336 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1337 1.1 mrg (unspec:<VPRED>
1338 1.1 mrg [(match_dup 1)
1339 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w, w")
1340 1.1 mrg (match_operand:SVE_I 3 "aarch64_sve_cmp_<imm_con>_operand" "<imm_con>, w")]
1341 1.1 mrg SVE_COND_INT_CMP)]
1342 1.1 mrg UNSPEC_PTEST_PTRUE)
1343 1.1 mrg (const_int 0)))
1344 1.1 mrg (set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
1345 1.1 mrg (unspec:<VPRED>
1346 1.1 mrg [(match_dup 1)
1347 1.1 mrg (match_dup 2)
1348 1.1 mrg (match_dup 3)]
1349 1.1 mrg SVE_COND_INT_CMP))]
1350 1.1 mrg "TARGET_SVE"
1351 1.1 mrg "@
1352 1.1 mrg cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
1353 1.1 mrg cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
1354 1.1 mrg )
1355 1.1 mrg
1356 1.1 mrg ;; Predicated floating-point comparison (excluding FCMUO, which doesn't
1357 1.1 mrg ;; allow #0.0 as an operand).
1358 1.1 mrg (define_insn "*vec_fcm<cmp_op><mode>"
1359 1.1 mrg [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
1360 1.1 mrg (unspec:<VPRED>
1361 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1362 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w, w")
1363 1.1 mrg (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w")]
1364 1.1 mrg SVE_COND_FP_CMP))]
1365 1.1 mrg "TARGET_SVE"
1366 1.1 mrg "@
1367 1.1 mrg fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #0.0
1368 1.1 mrg fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
1369 1.1 mrg )
1370 1.1 mrg
1371 1.1 mrg ;; Predicated FCMUO.
1372 1.1 mrg (define_insn "*vec_fcmuo<mode>"
1373 1.1 mrg [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
1374 1.1 mrg (unspec:<VPRED>
1375 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
1376 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w")
1377 1.1 mrg (match_operand:SVE_F 3 "register_operand" "w")]
1378 1.1 mrg UNSPEC_COND_UO))]
1379 1.1 mrg "TARGET_SVE"
1380 1.1 mrg "fcmuo\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
1381 1.1 mrg )
1382 1.1 mrg
1383 1.1 mrg ;; vcond_mask operand order: true, false, mask
1384 1.1 mrg ;; UNSPEC_SEL operand order: mask, true, false (as for VEC_COND_EXPR)
1385 1.1 mrg ;; SEL operand order: mask, true, false
1386 1.1 mrg (define_insn "vcond_mask_<mode><vpred>"
1387 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
1388 1.1 mrg (unspec:SVE_ALL
1389 1.1 mrg [(match_operand:<VPRED> 3 "register_operand" "Upa")
1390 1.1 mrg (match_operand:SVE_ALL 1 "register_operand" "w")
1391 1.1 mrg (match_operand:SVE_ALL 2 "register_operand" "w")]
1392 1.1 mrg UNSPEC_SEL))]
1393 1.1 mrg "TARGET_SVE"
1394 1.1 mrg "sel\t%0.<Vetype>, %3, %1.<Vetype>, %2.<Vetype>"
1395 1.1 mrg )
1396 1.1 mrg
1397 1.1 mrg ;; Selects between a duplicated immediate and zero.
1398 1.1 mrg (define_insn "aarch64_sve_dup<mode>_const"
1399 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w")
1400 1.1 mrg (unspec:SVE_I
1401 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
1402 1.1 mrg (match_operand:SVE_I 2 "aarch64_sve_dup_immediate")
1403 1.1 mrg (match_operand:SVE_I 3 "aarch64_simd_imm_zero")]
1404 1.1 mrg UNSPEC_SEL))]
1405 1.1 mrg "TARGET_SVE"
1406 1.1 mrg "mov\t%0.<Vetype>, %1/z, #%2"
1407 1.1 mrg )
1408 1.1 mrg
1409 1.1 mrg ;; Integer (signed) vcond. Don't enforce an immediate range here, since it
1410 1.1 mrg ;; depends on the comparison; leave it to aarch64_expand_sve_vcond instead.
1411 1.1 mrg (define_expand "vcond<mode><v_int_equiv>"
1412 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand")
1413 1.1 mrg (if_then_else:SVE_ALL
1414 1.1 mrg (match_operator 3 "comparison_operator"
1415 1.1 mrg [(match_operand:<V_INT_EQUIV> 4 "register_operand")
1416 1.1 mrg (match_operand:<V_INT_EQUIV> 5 "nonmemory_operand")])
1417 1.1 mrg (match_operand:SVE_ALL 1 "register_operand")
1418 1.1 mrg (match_operand:SVE_ALL 2 "register_operand")))]
1419 1.1 mrg "TARGET_SVE"
1420 1.1 mrg {
1421 1.1 mrg aarch64_expand_sve_vcond (<MODE>mode, <V_INT_EQUIV>mode, operands);
1422 1.1 mrg DONE;
1423 1.1 mrg }
1424 1.1 mrg )
1425 1.1 mrg
1426 1.1 mrg ;; Integer vcondu. Don't enforce an immediate range here, since it
1427 1.1 mrg ;; depends on the comparison; leave it to aarch64_expand_sve_vcond instead.
1428 1.1 mrg (define_expand "vcondu<mode><v_int_equiv>"
1429 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand")
1430 1.1 mrg (if_then_else:SVE_ALL
1431 1.1 mrg (match_operator 3 "comparison_operator"
1432 1.1 mrg [(match_operand:<V_INT_EQUIV> 4 "register_operand")
1433 1.1 mrg (match_operand:<V_INT_EQUIV> 5 "nonmemory_operand")])
1434 1.1 mrg (match_operand:SVE_ALL 1 "register_operand")
1435 1.1 mrg (match_operand:SVE_ALL 2 "register_operand")))]
1436 1.1 mrg "TARGET_SVE"
1437 1.1 mrg {
1438 1.1 mrg aarch64_expand_sve_vcond (<MODE>mode, <V_INT_EQUIV>mode, operands);
1439 1.1 mrg DONE;
1440 1.1 mrg }
1441 1.1 mrg )
1442 1.1 mrg
1443 1.1 mrg ;; Floating-point vcond. All comparisons except FCMUO allow a zero
1444 1.1 mrg ;; operand; aarch64_expand_sve_vcond handles the case of an FCMUO
1445 1.1 mrg ;; with zero.
1446 1.1 mrg (define_expand "vcond<mode><v_fp_equiv>"
1447 1.1 mrg [(set (match_operand:SVE_SD 0 "register_operand")
1448 1.1 mrg (if_then_else:SVE_SD
1449 1.1 mrg (match_operator 3 "comparison_operator"
1450 1.1 mrg [(match_operand:<V_FP_EQUIV> 4 "register_operand")
1451 1.1 mrg (match_operand:<V_FP_EQUIV> 5 "aarch64_simd_reg_or_zero")])
1452 1.1 mrg (match_operand:SVE_SD 1 "register_operand")
1453 1.1 mrg (match_operand:SVE_SD 2 "register_operand")))]
1454 1.1 mrg "TARGET_SVE"
1455 1.1 mrg {
1456 1.1 mrg aarch64_expand_sve_vcond (<MODE>mode, <V_FP_EQUIV>mode, operands);
1457 1.1 mrg DONE;
1458 1.1 mrg }
1459 1.1 mrg )
1460 1.1 mrg
1461 1.1 mrg ;; Signed integer comparisons. Don't enforce an immediate range here, since
1462 1.1 mrg ;; it depends on the comparison; leave it to aarch64_expand_sve_vec_cmp_int
1463 1.1 mrg ;; instead.
1464 1.1 mrg (define_expand "vec_cmp<mode><vpred>"
1465 1.1 mrg [(parallel
1466 1.1 mrg [(set (match_operand:<VPRED> 0 "register_operand")
1467 1.1 mrg (match_operator:<VPRED> 1 "comparison_operator"
1468 1.1 mrg [(match_operand:SVE_I 2 "register_operand")
1469 1.1 mrg (match_operand:SVE_I 3 "nonmemory_operand")]))
1470 1.1 mrg (clobber (reg:CC CC_REGNUM))])]
1471 1.1 mrg "TARGET_SVE"
1472 1.1 mrg {
1473 1.1 mrg aarch64_expand_sve_vec_cmp_int (operands[0], GET_CODE (operands[1]),
1474 1.1 mrg operands[2], operands[3]);
1475 1.1 mrg DONE;
1476 1.1 mrg }
1477 1.1 mrg )
1478 1.1 mrg
1479 1.1 mrg ;; Unsigned integer comparisons. Don't enforce an immediate range here, since
1480 1.1 mrg ;; it depends on the comparison; leave it to aarch64_expand_sve_vec_cmp_int
1481 1.1 mrg ;; instead.
1482 1.1 mrg (define_expand "vec_cmpu<mode><vpred>"
1483 1.1 mrg [(parallel
1484 1.1 mrg [(set (match_operand:<VPRED> 0 "register_operand")
1485 1.1 mrg (match_operator:<VPRED> 1 "comparison_operator"
1486 1.1 mrg [(match_operand:SVE_I 2 "register_operand")
1487 1.1 mrg (match_operand:SVE_I 3 "nonmemory_operand")]))
1488 1.1 mrg (clobber (reg:CC CC_REGNUM))])]
1489 1.1 mrg "TARGET_SVE"
1490 1.1 mrg {
1491 1.1 mrg aarch64_expand_sve_vec_cmp_int (operands[0], GET_CODE (operands[1]),
1492 1.1 mrg operands[2], operands[3]);
1493 1.1 mrg DONE;
1494 1.1 mrg }
1495 1.1 mrg )
1496 1.1 mrg
1497 1.1 mrg ;; Floating-point comparisons. All comparisons except FCMUO allow a zero
1498 1.1 mrg ;; operand; aarch64_expand_sve_vec_cmp_float handles the case of an FCMUO
1499 1.1 mrg ;; with zero.
1500 1.1 mrg (define_expand "vec_cmp<mode><vpred>"
1501 1.1 mrg [(set (match_operand:<VPRED> 0 "register_operand")
1502 1.1 mrg (match_operator:<VPRED> 1 "comparison_operator"
1503 1.1 mrg [(match_operand:SVE_F 2 "register_operand")
1504 1.1 mrg (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero")]))]
1505 1.1 mrg "TARGET_SVE"
1506 1.1 mrg {
1507 1.1 mrg aarch64_expand_sve_vec_cmp_float (operands[0], GET_CODE (operands[1]),
1508 1.1 mrg operands[2], operands[3], false);
1509 1.1 mrg DONE;
1510 1.1 mrg }
1511 1.1 mrg )
1512 1.1 mrg
1513 1.1 mrg ;; Branch based on predicate equality or inequality.
1514 1.1 mrg (define_expand "cbranch<mode>4"
1515 1.1 mrg [(set (pc)
1516 1.1 mrg (if_then_else
1517 1.1 mrg (match_operator 0 "aarch64_equality_operator"
1518 1.1 mrg [(match_operand:PRED_ALL 1 "register_operand")
1519 1.1 mrg (match_operand:PRED_ALL 2 "aarch64_simd_reg_or_zero")])
1520 1.1 mrg (label_ref (match_operand 3 ""))
1521 1.1 mrg (pc)))]
1522 1.1 mrg ""
1523 1.1 mrg {
1524 1.1 mrg rtx ptrue = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
1525 1.1 mrg rtx pred;
1526 1.1 mrg if (operands[2] == CONST0_RTX (<MODE>mode))
1527 1.1 mrg pred = operands[1];
1528 1.1 mrg else
1529 1.1 mrg {
1530 1.1 mrg pred = gen_reg_rtx (<MODE>mode);
1531 1.1 mrg emit_insn (gen_pred_xor<mode>3 (pred, ptrue, operands[1],
1532 1.1 mrg operands[2]));
1533 1.1 mrg }
1534 1.1 mrg emit_insn (gen_ptest_ptrue<mode> (ptrue, pred));
1535 1.1 mrg operands[1] = gen_rtx_REG (CCmode, CC_REGNUM);
1536 1.1 mrg operands[2] = const0_rtx;
1537 1.1 mrg }
1538 1.1 mrg )
1539 1.1 mrg
1540 1.1 mrg ;; Unpredicated integer MIN/MAX.
1541 1.1 mrg (define_expand "<su><maxmin><mode>3"
1542 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand")
1543 1.1 mrg (unspec:SVE_I
1544 1.1 mrg [(match_dup 3)
1545 1.1 mrg (MAXMIN:SVE_I (match_operand:SVE_I 1 "register_operand")
1546 1.1 mrg (match_operand:SVE_I 2 "register_operand"))]
1547 1.1 mrg UNSPEC_MERGE_PTRUE))]
1548 1.1 mrg "TARGET_SVE"
1549 1.1 mrg {
1550 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1551 1.1 mrg }
1552 1.1 mrg )
1553 1.1 mrg
1554 1.1 mrg ;; Integer MIN/MAX predicated with a PTRUE.
1555 1.1 mrg (define_insn "*<su><maxmin><mode>3"
1556 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w")
1557 1.1 mrg (unspec:SVE_I
1558 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
1559 1.1 mrg (MAXMIN:SVE_I (match_operand:SVE_I 2 "register_operand" "%0")
1560 1.1 mrg (match_operand:SVE_I 3 "register_operand" "w"))]
1561 1.1 mrg UNSPEC_MERGE_PTRUE))]
1562 1.1 mrg "TARGET_SVE"
1563 1.1 mrg "<su><maxmin>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
1564 1.1 mrg )
1565 1.1 mrg
1566 1.1 mrg ;; Unpredicated floating-point MIN/MAX.
1567 1.1 mrg (define_expand "<su><maxmin><mode>3"
1568 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1569 1.1 mrg (unspec:SVE_F
1570 1.1 mrg [(match_dup 3)
1571 1.1 mrg (FMAXMIN:SVE_F (match_operand:SVE_F 1 "register_operand")
1572 1.1 mrg (match_operand:SVE_F 2 "register_operand"))]
1573 1.1 mrg UNSPEC_MERGE_PTRUE))]
1574 1.1 mrg "TARGET_SVE"
1575 1.1 mrg {
1576 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1577 1.1 mrg }
1578 1.1 mrg )
1579 1.1 mrg
1580 1.1 mrg ;; Floating-point MIN/MAX predicated with a PTRUE.
1581 1.1 mrg (define_insn "*<su><maxmin><mode>3"
1582 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w")
1583 1.1 mrg (unspec:SVE_F
1584 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
1585 1.1 mrg (FMAXMIN:SVE_F (match_operand:SVE_F 2 "register_operand" "%0")
1586 1.1 mrg (match_operand:SVE_F 3 "register_operand" "w"))]
1587 1.1 mrg UNSPEC_MERGE_PTRUE))]
1588 1.1 mrg "TARGET_SVE"
1589 1.1 mrg "f<maxmin>nm\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
1590 1.1 mrg )
1591 1.1 mrg
1592 1.1 mrg ;; Unpredicated fmin/fmax.
1593 1.1 mrg (define_expand "<maxmin_uns><mode>3"
1594 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1595 1.1 mrg (unspec:SVE_F
1596 1.1 mrg [(match_dup 3)
1597 1.1 mrg (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand")
1598 1.1 mrg (match_operand:SVE_F 2 "register_operand")]
1599 1.1 mrg FMAXMIN_UNS)]
1600 1.1 mrg UNSPEC_MERGE_PTRUE))]
1601 1.1 mrg "TARGET_SVE"
1602 1.1 mrg {
1603 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1604 1.1 mrg }
1605 1.1 mrg )
1606 1.1 mrg
1607 1.1 mrg ;; fmin/fmax predicated with a PTRUE.
1608 1.1 mrg (define_insn "*<maxmin_uns><mode>3"
1609 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w")
1610 1.1 mrg (unspec:SVE_F
1611 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
1612 1.1 mrg (unspec:SVE_F [(match_operand:SVE_F 2 "register_operand" "%0")
1613 1.1 mrg (match_operand:SVE_F 3 "register_operand" "w")]
1614 1.1 mrg FMAXMIN_UNS)]
1615 1.1 mrg UNSPEC_MERGE_PTRUE))]
1616 1.1 mrg "TARGET_SVE"
1617 1.1 mrg "<maxmin_uns_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
1618 1.1 mrg )
1619 1.1 mrg
1620 1.1 mrg ;; Predicated integer operations.
1621 1.1 mrg (define_insn "cond_<optab><mode>"
1622 1.1 mrg [(set (match_operand:SVE_I 0 "register_operand" "=w")
1623 1.1 mrg (unspec:SVE_I
1624 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
1625 1.1 mrg (match_operand:SVE_I 2 "register_operand" "0")
1626 1.1 mrg (match_operand:SVE_I 3 "register_operand" "w")]
1627 1.1 mrg SVE_COND_INT_OP))]
1628 1.1 mrg "TARGET_SVE"
1629 1.1 mrg "<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
1630 1.1 mrg )
1631 1.1 mrg
1632 1.1 mrg ;; Set operand 0 to the last active element in operand 3, or to tied
1633 1.1 mrg ;; operand 1 if no elements are active.
1634 1.1 mrg (define_insn "fold_extract_last_<mode>"
1635 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=r, w")
1636 1.1 mrg (unspec:<VEL>
1637 1.1 mrg [(match_operand:<VEL> 1 "register_operand" "0, 0")
1638 1.1 mrg (match_operand:<VPRED> 2 "register_operand" "Upl, Upl")
1639 1.1 mrg (match_operand:SVE_ALL 3 "register_operand" "w, w")]
1640 1.1 mrg UNSPEC_CLASTB))]
1641 1.1 mrg "TARGET_SVE"
1642 1.1 mrg "@
1643 1.1 mrg clastb\t%<vwcore>0, %2, %<vwcore>0, %3.<Vetype>
1644 1.1 mrg clastb\t%<vw>0, %2, %<vw>0, %3.<Vetype>"
1645 1.1 mrg )
1646 1.1 mrg
1647 1.1 mrg ;; Unpredicated integer add reduction.
1648 1.1 mrg (define_expand "reduc_plus_scal_<mode>"
1649 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand")
1650 1.1 mrg (unspec:<VEL> [(match_dup 2)
1651 1.1 mrg (match_operand:SVE_I 1 "register_operand")]
1652 1.1 mrg UNSPEC_ADDV))]
1653 1.1 mrg "TARGET_SVE"
1654 1.1 mrg {
1655 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1656 1.1 mrg }
1657 1.1 mrg )
1658 1.1 mrg
1659 1.1 mrg ;; Predicated integer add reduction. The result is always 64-bits.
1660 1.1 mrg (define_insn "*reduc_plus_scal_<mode>"
1661 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
1662 1.1 mrg (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
1663 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w")]
1664 1.1 mrg UNSPEC_ADDV))]
1665 1.1 mrg "TARGET_SVE"
1666 1.1 mrg "uaddv\t%d0, %1, %2.<Vetype>"
1667 1.1 mrg )
1668 1.1 mrg
1669 1.1 mrg ;; Unpredicated floating-point add reduction.
1670 1.1 mrg (define_expand "reduc_plus_scal_<mode>"
1671 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand")
1672 1.1 mrg (unspec:<VEL> [(match_dup 2)
1673 1.1 mrg (match_operand:SVE_F 1 "register_operand")]
1674 1.1 mrg UNSPEC_FADDV))]
1675 1.1 mrg "TARGET_SVE"
1676 1.1 mrg {
1677 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1678 1.1 mrg }
1679 1.1 mrg )
1680 1.1 mrg
1681 1.1 mrg ;; Predicated floating-point add reduction.
1682 1.1 mrg (define_insn "*reduc_plus_scal_<mode>"
1683 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
1684 1.1 mrg (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
1685 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w")]
1686 1.1 mrg UNSPEC_FADDV))]
1687 1.1 mrg "TARGET_SVE"
1688 1.1 mrg "faddv\t%<Vetype>0, %1, %2.<Vetype>"
1689 1.1 mrg )
1690 1.1 mrg
1691 1.1 mrg ;; Unpredicated integer MIN/MAX reduction.
1692 1.1 mrg (define_expand "reduc_<maxmin_uns>_scal_<mode>"
1693 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand")
1694 1.1 mrg (unspec:<VEL> [(match_dup 2)
1695 1.1 mrg (match_operand:SVE_I 1 "register_operand")]
1696 1.1 mrg MAXMINV))]
1697 1.1 mrg "TARGET_SVE"
1698 1.1 mrg {
1699 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1700 1.1 mrg }
1701 1.1 mrg )
1702 1.1 mrg
1703 1.1 mrg ;; Predicated integer MIN/MAX reduction.
1704 1.1 mrg (define_insn "*reduc_<maxmin_uns>_scal_<mode>"
1705 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
1706 1.1 mrg (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
1707 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w")]
1708 1.1 mrg MAXMINV))]
1709 1.1 mrg "TARGET_SVE"
1710 1.1 mrg "<maxmin_uns_op>v\t%<Vetype>0, %1, %2.<Vetype>"
1711 1.1 mrg )
1712 1.1 mrg
1713 1.1 mrg ;; Unpredicated floating-point MIN/MAX reduction.
1714 1.1 mrg (define_expand "reduc_<maxmin_uns>_scal_<mode>"
1715 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand")
1716 1.1 mrg (unspec:<VEL> [(match_dup 2)
1717 1.1 mrg (match_operand:SVE_F 1 "register_operand")]
1718 1.1 mrg FMAXMINV))]
1719 1.1 mrg "TARGET_SVE"
1720 1.1 mrg {
1721 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1722 1.1 mrg }
1723 1.1 mrg )
1724 1.1 mrg
1725 1.1 mrg ;; Predicated floating-point MIN/MAX reduction.
1726 1.1 mrg (define_insn "*reduc_<maxmin_uns>_scal_<mode>"
1727 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
1728 1.1 mrg (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
1729 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w")]
1730 1.1 mrg FMAXMINV))]
1731 1.1 mrg "TARGET_SVE"
1732 1.1 mrg "<maxmin_uns_op>v\t%<Vetype>0, %1, %2.<Vetype>"
1733 1.1 mrg )
1734 1.1 mrg
1735 1.1 mrg (define_expand "reduc_<optab>_scal_<mode>"
1736 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand")
1737 1.1 mrg (unspec:<VEL> [(match_dup 2)
1738 1.1 mrg (match_operand:SVE_I 1 "register_operand")]
1739 1.1 mrg BITWISEV))]
1740 1.1 mrg "TARGET_SVE"
1741 1.1 mrg {
1742 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1743 1.1 mrg }
1744 1.1 mrg )
1745 1.1 mrg
1746 1.1 mrg (define_insn "*reduc_<optab>_scal_<mode>"
1747 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
1748 1.1 mrg (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
1749 1.1 mrg (match_operand:SVE_I 2 "register_operand" "w")]
1750 1.1 mrg BITWISEV))]
1751 1.1 mrg "TARGET_SVE"
1752 1.1 mrg "<bit_reduc_op>\t%<Vetype>0, %1, %2.<Vetype>"
1753 1.1 mrg )
1754 1.1 mrg
1755 1.1 mrg ;; Unpredicated in-order FP reductions.
1756 1.1 mrg (define_expand "fold_left_plus_<mode>"
1757 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand")
1758 1.1 mrg (unspec:<VEL> [(match_dup 3)
1759 1.1 mrg (match_operand:<VEL> 1 "register_operand")
1760 1.1 mrg (match_operand:SVE_F 2 "register_operand")]
1761 1.1 mrg UNSPEC_FADDA))]
1762 1.1 mrg "TARGET_SVE"
1763 1.1 mrg {
1764 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1765 1.1 mrg }
1766 1.1 mrg )
1767 1.1 mrg
1768 1.1 mrg ;; In-order FP reductions predicated with PTRUE.
1769 1.1 mrg (define_insn "*fold_left_plus_<mode>"
1770 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
1771 1.1 mrg (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
1772 1.1 mrg (match_operand:<VEL> 2 "register_operand" "0")
1773 1.1 mrg (match_operand:SVE_F 3 "register_operand" "w")]
1774 1.1 mrg UNSPEC_FADDA))]
1775 1.1 mrg "TARGET_SVE"
1776 1.1 mrg "fadda\t%<Vetype>0, %1, %<Vetype>0, %3.<Vetype>"
1777 1.1 mrg )
1778 1.1 mrg
1779 1.1 mrg ;; Predicated form of the above in-order reduction.
1780 1.1 mrg (define_insn "*pred_fold_left_plus_<mode>"
1781 1.1 mrg [(set (match_operand:<VEL> 0 "register_operand" "=w")
1782 1.1 mrg (unspec:<VEL>
1783 1.1 mrg [(match_operand:<VEL> 1 "register_operand" "0")
1784 1.1 mrg (unspec:SVE_F
1785 1.1 mrg [(match_operand:<VPRED> 2 "register_operand" "Upl")
1786 1.1 mrg (match_operand:SVE_F 3 "register_operand" "w")
1787 1.1 mrg (match_operand:SVE_F 4 "aarch64_simd_imm_zero")]
1788 1.1 mrg UNSPEC_SEL)]
1789 1.1 mrg UNSPEC_FADDA))]
1790 1.1 mrg "TARGET_SVE"
1791 1.1 mrg "fadda\t%<Vetype>0, %2, %<Vetype>0, %3.<Vetype>"
1792 1.1 mrg )
1793 1.1 mrg
1794 1.1 mrg ;; Unpredicated floating-point addition.
1795 1.1 mrg (define_expand "add<mode>3"
1796 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1797 1.1 mrg (unspec:SVE_F
1798 1.1 mrg [(match_dup 3)
1799 1.1 mrg (plus:SVE_F
1800 1.1 mrg (match_operand:SVE_F 1 "register_operand")
1801 1.1 mrg (match_operand:SVE_F 2 "aarch64_sve_float_arith_with_sub_operand"))]
1802 1.1 mrg UNSPEC_MERGE_PTRUE))]
1803 1.1 mrg "TARGET_SVE"
1804 1.1 mrg {
1805 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1806 1.1 mrg }
1807 1.1 mrg )
1808 1.1 mrg
1809 1.1 mrg ;; Floating-point addition predicated with a PTRUE.
1810 1.1 mrg (define_insn "*add<mode>3"
1811 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w")
1812 1.1 mrg (unspec:SVE_F
1813 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
1814 1.1 mrg (plus:SVE_F
1815 1.1 mrg (match_operand:SVE_F 2 "register_operand" "%0, 0, w")
1816 1.1 mrg (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand" "vsA, vsN, w"))]
1817 1.1 mrg UNSPEC_MERGE_PTRUE))]
1818 1.1 mrg "TARGET_SVE"
1819 1.1 mrg "@
1820 1.1 mrg fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
1821 1.1 mrg fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
1822 1.1 mrg fadd\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>"
1823 1.1 mrg )
1824 1.1 mrg
1825 1.1 mrg ;; Unpredicated floating-point subtraction.
1826 1.1 mrg (define_expand "sub<mode>3"
1827 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1828 1.1 mrg (unspec:SVE_F
1829 1.1 mrg [(match_dup 3)
1830 1.1 mrg (minus:SVE_F
1831 1.1 mrg (match_operand:SVE_F 1 "aarch64_sve_float_arith_operand")
1832 1.1 mrg (match_operand:SVE_F 2 "register_operand"))]
1833 1.1 mrg UNSPEC_MERGE_PTRUE))]
1834 1.1 mrg "TARGET_SVE"
1835 1.1 mrg {
1836 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1837 1.1 mrg }
1838 1.1 mrg )
1839 1.1 mrg
1840 1.1 mrg ;; Floating-point subtraction predicated with a PTRUE.
1841 1.1 mrg (define_insn "*sub<mode>3"
1842 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, w")
1843 1.1 mrg (unspec:SVE_F
1844 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
1845 1.1 mrg (minus:SVE_F
1846 1.1 mrg (match_operand:SVE_F 2 "aarch64_sve_float_arith_operand" "0, 0, vsA, w")
1847 1.1 mrg (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand" "vsA, vsN, 0, w"))]
1848 1.1 mrg UNSPEC_MERGE_PTRUE))]
1849 1.1 mrg "TARGET_SVE
1850 1.1 mrg && (register_operand (operands[2], <MODE>mode)
1851 1.1 mrg || register_operand (operands[3], <MODE>mode))"
1852 1.1 mrg "@
1853 1.1 mrg fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
1854 1.1 mrg fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
1855 1.1 mrg fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
1856 1.1 mrg fsub\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>"
1857 1.1 mrg )
1858 1.1 mrg
1859 1.1 mrg ;; Unpredicated floating-point multiplication.
1860 1.1 mrg (define_expand "mul<mode>3"
1861 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1862 1.1 mrg (unspec:SVE_F
1863 1.1 mrg [(match_dup 3)
1864 1.1 mrg (mult:SVE_F
1865 1.1 mrg (match_operand:SVE_F 1 "register_operand")
1866 1.1 mrg (match_operand:SVE_F 2 "aarch64_sve_float_mul_operand"))]
1867 1.1 mrg UNSPEC_MERGE_PTRUE))]
1868 1.1 mrg "TARGET_SVE"
1869 1.1 mrg {
1870 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1871 1.1 mrg }
1872 1.1 mrg )
1873 1.1 mrg
1874 1.1 mrg ;; Floating-point multiplication predicated with a PTRUE.
1875 1.1 mrg (define_insn "*mul<mode>3"
1876 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w, w")
1877 1.1 mrg (unspec:SVE_F
1878 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1879 1.1 mrg (mult:SVE_F
1880 1.1 mrg (match_operand:SVE_F 2 "register_operand" "%0, w")
1881 1.1 mrg (match_operand:SVE_F 3 "aarch64_sve_float_mul_operand" "vsM, w"))]
1882 1.1 mrg UNSPEC_MERGE_PTRUE))]
1883 1.1 mrg "TARGET_SVE"
1884 1.1 mrg "@
1885 1.1 mrg fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
1886 1.1 mrg fmul\t%0.<Vetype>, %2.<Vetype>, %3.<Vetype>"
1887 1.1 mrg )
1888 1.1 mrg
1889 1.1 mrg ;; Unpredicated fma (%0 = (%1 * %2) + %3).
1890 1.1 mrg (define_expand "fma<mode>4"
1891 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1892 1.1 mrg (unspec:SVE_F
1893 1.1 mrg [(match_dup 4)
1894 1.1 mrg (fma:SVE_F (match_operand:SVE_F 1 "register_operand")
1895 1.1 mrg (match_operand:SVE_F 2 "register_operand")
1896 1.1 mrg (match_operand:SVE_F 3 "register_operand"))]
1897 1.1 mrg UNSPEC_MERGE_PTRUE))]
1898 1.1 mrg "TARGET_SVE"
1899 1.1 mrg {
1900 1.1 mrg operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1901 1.1 mrg }
1902 1.1 mrg )
1903 1.1 mrg
1904 1.1 mrg ;; fma predicated with a PTRUE.
1905 1.1 mrg (define_insn "*fma<mode>4"
1906 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w, w")
1907 1.1 mrg (unspec:SVE_F
1908 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1909 1.1 mrg (fma:SVE_F (match_operand:SVE_F 3 "register_operand" "%0, w")
1910 1.1 mrg (match_operand:SVE_F 4 "register_operand" "w, w")
1911 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w, 0"))]
1912 1.1 mrg UNSPEC_MERGE_PTRUE))]
1913 1.1 mrg "TARGET_SVE"
1914 1.1 mrg "@
1915 1.1 mrg fmad\t%0.<Vetype>, %1/m, %4.<Vetype>, %2.<Vetype>
1916 1.1 mrg fmla\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
1917 1.1 mrg )
1918 1.1 mrg
1919 1.1 mrg ;; Unpredicated fnma (%0 = (-%1 * %2) + %3).
1920 1.1 mrg (define_expand "fnma<mode>4"
1921 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1922 1.1 mrg (unspec:SVE_F
1923 1.1 mrg [(match_dup 4)
1924 1.1 mrg (fma:SVE_F (neg:SVE_F
1925 1.1 mrg (match_operand:SVE_F 1 "register_operand"))
1926 1.1 mrg (match_operand:SVE_F 2 "register_operand")
1927 1.1 mrg (match_operand:SVE_F 3 "register_operand"))]
1928 1.1 mrg UNSPEC_MERGE_PTRUE))]
1929 1.1 mrg "TARGET_SVE"
1930 1.1 mrg {
1931 1.1 mrg operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1932 1.1 mrg }
1933 1.1 mrg )
1934 1.1 mrg
1935 1.1 mrg ;; fnma predicated with a PTRUE.
1936 1.1 mrg (define_insn "*fnma<mode>4"
1937 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w, w")
1938 1.1 mrg (unspec:SVE_F
1939 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1940 1.1 mrg (fma:SVE_F (neg:SVE_F
1941 1.1 mrg (match_operand:SVE_F 3 "register_operand" "%0, w"))
1942 1.1 mrg (match_operand:SVE_F 4 "register_operand" "w, w")
1943 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w, 0"))]
1944 1.1 mrg UNSPEC_MERGE_PTRUE))]
1945 1.1 mrg "TARGET_SVE"
1946 1.1 mrg "@
1947 1.1 mrg fmsb\t%0.<Vetype>, %1/m, %4.<Vetype>, %2.<Vetype>
1948 1.1 mrg fmls\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
1949 1.1 mrg )
1950 1.1 mrg
1951 1.1 mrg ;; Unpredicated fms (%0 = (%1 * %2) - %3).
1952 1.1 mrg (define_expand "fms<mode>4"
1953 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1954 1.1 mrg (unspec:SVE_F
1955 1.1 mrg [(match_dup 4)
1956 1.1 mrg (fma:SVE_F (match_operand:SVE_F 1 "register_operand")
1957 1.1 mrg (match_operand:SVE_F 2 "register_operand")
1958 1.1 mrg (neg:SVE_F
1959 1.1 mrg (match_operand:SVE_F 3 "register_operand")))]
1960 1.1 mrg UNSPEC_MERGE_PTRUE))]
1961 1.1 mrg "TARGET_SVE"
1962 1.1 mrg {
1963 1.1 mrg operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1964 1.1 mrg }
1965 1.1 mrg )
1966 1.1 mrg
1967 1.1 mrg ;; fms predicated with a PTRUE.
1968 1.1 mrg (define_insn "*fms<mode>4"
1969 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w, w")
1970 1.1 mrg (unspec:SVE_F
1971 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
1972 1.1 mrg (fma:SVE_F (match_operand:SVE_F 3 "register_operand" "%0, w")
1973 1.1 mrg (match_operand:SVE_F 4 "register_operand" "w, w")
1974 1.1 mrg (neg:SVE_F
1975 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w, 0")))]
1976 1.1 mrg UNSPEC_MERGE_PTRUE))]
1977 1.1 mrg "TARGET_SVE"
1978 1.1 mrg "@
1979 1.1 mrg fnmsb\t%0.<Vetype>, %1/m, %4.<Vetype>, %2.<Vetype>
1980 1.1 mrg fnmls\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
1981 1.1 mrg )
1982 1.1 mrg
1983 1.1 mrg ;; Unpredicated fnms (%0 = (-%1 * %2) - %3).
1984 1.1 mrg (define_expand "fnms<mode>4"
1985 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
1986 1.1 mrg (unspec:SVE_F
1987 1.1 mrg [(match_dup 4)
1988 1.1 mrg (fma:SVE_F (neg:SVE_F
1989 1.1 mrg (match_operand:SVE_F 1 "register_operand"))
1990 1.1 mrg (match_operand:SVE_F 2 "register_operand")
1991 1.1 mrg (neg:SVE_F
1992 1.1 mrg (match_operand:SVE_F 3 "register_operand")))]
1993 1.1 mrg UNSPEC_MERGE_PTRUE))]
1994 1.1 mrg "TARGET_SVE"
1995 1.1 mrg {
1996 1.1 mrg operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
1997 1.1 mrg }
1998 1.1 mrg )
1999 1.1 mrg
2000 1.1 mrg ;; fnms predicated with a PTRUE.
2001 1.1 mrg (define_insn "*fnms<mode>4"
2002 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w, w")
2003 1.1 mrg (unspec:SVE_F
2004 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
2005 1.1 mrg (fma:SVE_F (neg:SVE_F
2006 1.1 mrg (match_operand:SVE_F 3 "register_operand" "%0, w"))
2007 1.1 mrg (match_operand:SVE_F 4 "register_operand" "w, w")
2008 1.1 mrg (neg:SVE_F
2009 1.1 mrg (match_operand:SVE_F 2 "register_operand" "w, 0")))]
2010 1.1 mrg UNSPEC_MERGE_PTRUE))]
2011 1.1 mrg "TARGET_SVE"
2012 1.1 mrg "@
2013 1.1 mrg fnmad\t%0.<Vetype>, %1/m, %4.<Vetype>, %2.<Vetype>
2014 1.1 mrg fnmla\t%0.<Vetype>, %1/m, %3.<Vetype>, %4.<Vetype>"
2015 1.1 mrg )
2016 1.1 mrg
2017 1.1 mrg ;; Unpredicated floating-point division.
2018 1.1 mrg (define_expand "div<mode>3"
2019 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
2020 1.1 mrg (unspec:SVE_F
2021 1.1 mrg [(match_dup 3)
2022 1.1 mrg (div:SVE_F (match_operand:SVE_F 1 "register_operand")
2023 1.1 mrg (match_operand:SVE_F 2 "register_operand"))]
2024 1.1 mrg UNSPEC_MERGE_PTRUE))]
2025 1.1 mrg "TARGET_SVE"
2026 1.1 mrg {
2027 1.1 mrg operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
2028 1.1 mrg }
2029 1.1 mrg )
2030 1.1 mrg
2031 1.1 mrg ;; Floating-point division predicated with a PTRUE.
2032 1.1 mrg (define_insn "*div<mode>3"
2033 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w, w")
2034 1.1 mrg (unspec:SVE_F
2035 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
2036 1.1 mrg (div:SVE_F (match_operand:SVE_F 2 "register_operand" "0, w")
2037 1.1 mrg (match_operand:SVE_F 3 "register_operand" "w, 0"))]
2038 1.1 mrg UNSPEC_MERGE_PTRUE))]
2039 1.1 mrg "TARGET_SVE"
2040 1.1 mrg "@
2041 1.1 mrg fdiv\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
2042 1.1 mrg fdivr\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>"
2043 1.1 mrg )
2044 1.1 mrg
2045 1.1 mrg ;; Unpredicated FNEG, FABS and FSQRT.
2046 1.1 mrg (define_expand "<optab><mode>2"
2047 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
2048 1.1 mrg (unspec:SVE_F
2049 1.1 mrg [(match_dup 2)
2050 1.1 mrg (SVE_FP_UNARY:SVE_F (match_operand:SVE_F 1 "register_operand"))]
2051 1.1 mrg UNSPEC_MERGE_PTRUE))]
2052 1.1 mrg "TARGET_SVE"
2053 1.1 mrg {
2054 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
2055 1.1 mrg }
2056 1.1 mrg )
2057 1.1 mrg
2058 1.1 mrg ;; FNEG, FABS and FSQRT predicated with a PTRUE.
2059 1.1 mrg (define_insn "*<optab><mode>2"
2060 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w")
2061 1.1 mrg (unspec:SVE_F
2062 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
2063 1.1 mrg (SVE_FP_UNARY:SVE_F (match_operand:SVE_F 2 "register_operand" "w"))]
2064 1.1 mrg UNSPEC_MERGE_PTRUE))]
2065 1.1 mrg "TARGET_SVE"
2066 1.1 mrg "<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
2067 1.1 mrg )
2068 1.1 mrg
2069 1.1 mrg ;; Unpredicated FRINTy.
2070 1.1 mrg (define_expand "<frint_pattern><mode>2"
2071 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
2072 1.1 mrg (unspec:SVE_F
2073 1.1 mrg [(match_dup 2)
2074 1.1 mrg (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand")]
2075 1.1 mrg FRINT)]
2076 1.1 mrg UNSPEC_MERGE_PTRUE))]
2077 1.1 mrg "TARGET_SVE"
2078 1.1 mrg {
2079 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
2080 1.1 mrg }
2081 1.1 mrg )
2082 1.1 mrg
2083 1.1 mrg ;; FRINTy predicated with a PTRUE.
2084 1.1 mrg (define_insn "*<frint_pattern><mode>2"
2085 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w")
2086 1.1 mrg (unspec:SVE_F
2087 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
2088 1.1 mrg (unspec:SVE_F [(match_operand:SVE_F 2 "register_operand" "w")]
2089 1.1 mrg FRINT)]
2090 1.1 mrg UNSPEC_MERGE_PTRUE))]
2091 1.1 mrg "TARGET_SVE"
2092 1.1 mrg "frint<frint_suffix>\t%0.<Vetype>, %1/m, %2.<Vetype>"
2093 1.1 mrg )
2094 1.1 mrg
2095 1.1 mrg ;; Unpredicated conversion of floats to integers of the same size (HF to HI,
2096 1.1 mrg ;; SF to SI or DF to DI).
2097 1.1 mrg (define_expand "<fix_trunc_optab><mode><v_int_equiv>2"
2098 1.1 mrg [(set (match_operand:<V_INT_EQUIV> 0 "register_operand")
2099 1.1 mrg (unspec:<V_INT_EQUIV>
2100 1.1 mrg [(match_dup 2)
2101 1.1 mrg (FIXUORS:<V_INT_EQUIV>
2102 1.1 mrg (match_operand:SVE_F 1 "register_operand"))]
2103 1.1 mrg UNSPEC_MERGE_PTRUE))]
2104 1.1 mrg "TARGET_SVE"
2105 1.1 mrg {
2106 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
2107 1.1 mrg }
2108 1.1 mrg )
2109 1.1 mrg
2110 1.1 mrg ;; Conversion of SF to DI, SI or HI, predicated with a PTRUE.
2111 1.1 mrg (define_insn "*<fix_trunc_optab>v16hsf<mode>2"
2112 1.1 mrg [(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
2113 1.1 mrg (unspec:SVE_HSDI
2114 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
2115 1.1 mrg (FIXUORS:SVE_HSDI
2116 1.1 mrg (match_operand:VNx8HF 2 "register_operand" "w"))]
2117 1.1 mrg UNSPEC_MERGE_PTRUE))]
2118 1.1 mrg "TARGET_SVE"
2119 1.1 mrg "fcvtz<su>\t%0.<Vetype>, %1/m, %2.h"
2120 1.1 mrg )
2121 1.1 mrg
2122 1.1 mrg ;; Conversion of SF to DI or SI, predicated with a PTRUE.
2123 1.1 mrg (define_insn "*<fix_trunc_optab>vnx4sf<mode>2"
2124 1.1 mrg [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
2125 1.1 mrg (unspec:SVE_SDI
2126 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
2127 1.1 mrg (FIXUORS:SVE_SDI
2128 1.1 mrg (match_operand:VNx4SF 2 "register_operand" "w"))]
2129 1.1 mrg UNSPEC_MERGE_PTRUE))]
2130 1.1 mrg "TARGET_SVE"
2131 1.1 mrg "fcvtz<su>\t%0.<Vetype>, %1/m, %2.s"
2132 1.1 mrg )
2133 1.1 mrg
2134 1.1 mrg ;; Conversion of DF to DI or SI, predicated with a PTRUE.
2135 1.1 mrg (define_insn "*<fix_trunc_optab>vnx2df<mode>2"
2136 1.1 mrg [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
2137 1.1 mrg (unspec:SVE_SDI
2138 1.1 mrg [(match_operand:VNx2BI 1 "register_operand" "Upl")
2139 1.1 mrg (FIXUORS:SVE_SDI
2140 1.1 mrg (match_operand:VNx2DF 2 "register_operand" "w"))]
2141 1.1 mrg UNSPEC_MERGE_PTRUE))]
2142 1.1 mrg "TARGET_SVE"
2143 1.1 mrg "fcvtz<su>\t%0.<Vetype>, %1/m, %2.d"
2144 1.1 mrg )
2145 1.1 mrg
2146 1.1 mrg ;; Unpredicated conversion of integers to floats of the same size
2147 1.1 mrg ;; (HI to HF, SI to SF or DI to DF).
2148 1.1 mrg (define_expand "<optab><v_int_equiv><mode>2"
2149 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand")
2150 1.1 mrg (unspec:SVE_F
2151 1.1 mrg [(match_dup 2)
2152 1.1 mrg (FLOATUORS:SVE_F
2153 1.1 mrg (match_operand:<V_INT_EQUIV> 1 "register_operand"))]
2154 1.1 mrg UNSPEC_MERGE_PTRUE))]
2155 1.1 mrg "TARGET_SVE"
2156 1.1 mrg {
2157 1.1 mrg operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
2158 1.1 mrg }
2159 1.1 mrg )
2160 1.1 mrg
2161 1.1 mrg ;; Conversion of DI, SI or HI to the same number of HFs, predicated
2162 1.1 mrg ;; with a PTRUE.
2163 1.1 mrg (define_insn "*<optab><mode>vnx8hf2"
2164 1.1 mrg [(set (match_operand:VNx8HF 0 "register_operand" "=w")
2165 1.1 mrg (unspec:VNx8HF
2166 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
2167 1.1 mrg (FLOATUORS:VNx8HF
2168 1.1 mrg (match_operand:SVE_HSDI 2 "register_operand" "w"))]
2169 1.1 mrg UNSPEC_MERGE_PTRUE))]
2170 1.1 mrg "TARGET_SVE"
2171 1.1 mrg "<su_optab>cvtf\t%0.h, %1/m, %2.<Vetype>"
2172 1.1 mrg )
2173 1.1 mrg
2174 1.1 mrg ;; Conversion of DI or SI to the same number of SFs, predicated with a PTRUE.
2175 1.1 mrg (define_insn "*<optab><mode>vnx4sf2"
2176 1.1 mrg [(set (match_operand:VNx4SF 0 "register_operand" "=w")
2177 1.1 mrg (unspec:VNx4SF
2178 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
2179 1.1 mrg (FLOATUORS:VNx4SF
2180 1.1 mrg (match_operand:SVE_SDI 2 "register_operand" "w"))]
2181 1.1 mrg UNSPEC_MERGE_PTRUE))]
2182 1.1 mrg "TARGET_SVE"
2183 1.1 mrg "<su_optab>cvtf\t%0.s, %1/m, %2.<Vetype>"
2184 1.1 mrg )
2185 1.1 mrg
2186 1.1 mrg ;; Conversion of DI or SI to DF, predicated with a PTRUE.
2187 1.1 mrg (define_insn "aarch64_sve_<optab><mode>vnx2df2"
2188 1.1 mrg [(set (match_operand:VNx2DF 0 "register_operand" "=w")
2189 1.1 mrg (unspec:VNx2DF
2190 1.1 mrg [(match_operand:VNx2BI 1 "register_operand" "Upl")
2191 1.1 mrg (FLOATUORS:VNx2DF
2192 1.1 mrg (match_operand:SVE_SDI 2 "register_operand" "w"))]
2193 1.1 mrg UNSPEC_MERGE_PTRUE))]
2194 1.1 mrg "TARGET_SVE"
2195 1.1 mrg "<su_optab>cvtf\t%0.d, %1/m, %2.<Vetype>"
2196 1.1 mrg )
2197 1.1 mrg
2198 1.1 mrg ;; Conversion of DFs to the same number of SFs, or SFs to the same number
2199 1.1 mrg ;; of HFs.
2200 1.1 mrg (define_insn "*trunc<Vwide><mode>2"
2201 1.1 mrg [(set (match_operand:SVE_HSF 0 "register_operand" "=w")
2202 1.1 mrg (unspec:SVE_HSF
2203 1.1 mrg [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
2204 1.1 mrg (unspec:SVE_HSF
2205 1.1 mrg [(match_operand:<VWIDE> 2 "register_operand" "w")]
2206 1.1 mrg UNSPEC_FLOAT_CONVERT)]
2207 1.1 mrg UNSPEC_MERGE_PTRUE))]
2208 1.1 mrg "TARGET_SVE"
2209 1.1 mrg "fcvt\t%0.<Vetype>, %1/m, %2.<Vewtype>"
2210 1.1 mrg )
2211 1.1 mrg
2212 1.1 mrg ;; Conversion of SFs to the same number of DFs, or HFs to the same number
2213 1.1 mrg ;; of SFs.
2214 1.1 mrg (define_insn "aarch64_sve_extend<mode><Vwide>2"
2215 1.1 mrg [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2216 1.1 mrg (unspec:<VWIDE>
2217 1.1 mrg [(match_operand:<VWIDE_PRED> 1 "register_operand" "Upl")
2218 1.1 mrg (unspec:<VWIDE>
2219 1.1 mrg [(match_operand:SVE_HSF 2 "register_operand" "w")]
2220 1.1 mrg UNSPEC_FLOAT_CONVERT)]
2221 1.1 mrg UNSPEC_MERGE_PTRUE))]
2222 1.1 mrg "TARGET_SVE"
2223 1.1 mrg "fcvt\t%0.<Vewtype>, %1/m, %2.<Vetype>"
2224 1.1 mrg )
2225 1.1 mrg
2226 1.1 mrg ;; Unpack the low or high half of a predicate, where "high" refers to
2227 1.1 mrg ;; the low-numbered lanes for big-endian and the high-numbered lanes
2228 1.1 mrg ;; for little-endian.
2229 1.1 mrg (define_expand "vec_unpack<su>_<perm_hilo>_<mode>"
2230 1.1 mrg [(match_operand:<VWIDE> 0 "register_operand")
2231 1.1 mrg (unspec:<VWIDE> [(match_operand:PRED_BHS 1 "register_operand")]
2232 1.1 mrg UNPACK)]
2233 1.1 mrg "TARGET_SVE"
2234 1.1 mrg {
2235 1.1 mrg emit_insn ((<hi_lanes_optab>
2236 1.1 mrg ? gen_aarch64_sve_punpkhi_<PRED_BHS:mode>
2237 1.1 mrg : gen_aarch64_sve_punpklo_<PRED_BHS:mode>)
2238 1.1 mrg (operands[0], operands[1]));
2239 1.1 mrg DONE;
2240 1.1 mrg }
2241 1.1 mrg )
2242 1.1 mrg
2243 1.1 mrg ;; PUNPKHI and PUNPKLO.
2244 1.1 mrg (define_insn "aarch64_sve_punpk<perm_hilo>_<mode>"
2245 1.1 mrg [(set (match_operand:<VWIDE> 0 "register_operand" "=Upa")
2246 1.1 mrg (unspec:<VWIDE> [(match_operand:PRED_BHS 1 "register_operand" "Upa")]
2247 1.1 mrg UNPACK_UNSIGNED))]
2248 1.1 mrg "TARGET_SVE"
2249 1.1 mrg "punpk<perm_hilo>\t%0.h, %1.b"
2250 1.1 mrg )
2251 1.1 mrg
2252 1.1 mrg ;; Unpack the low or high half of a vector, where "high" refers to
2253 1.1 mrg ;; the low-numbered lanes for big-endian and the high-numbered lanes
2254 1.1 mrg ;; for little-endian.
2255 1.1 mrg (define_expand "vec_unpack<su>_<perm_hilo>_<SVE_BHSI:mode>"
2256 1.1 mrg [(match_operand:<VWIDE> 0 "register_operand")
2257 1.1 mrg (unspec:<VWIDE> [(match_operand:SVE_BHSI 1 "register_operand")] UNPACK)]
2258 1.1 mrg "TARGET_SVE"
2259 1.1 mrg {
2260 1.1 mrg emit_insn ((<hi_lanes_optab>
2261 1.1 mrg ? gen_aarch64_sve_<su>unpkhi_<SVE_BHSI:mode>
2262 1.1 mrg : gen_aarch64_sve_<su>unpklo_<SVE_BHSI:mode>)
2263 1.1 mrg (operands[0], operands[1]));
2264 1.1 mrg DONE;
2265 1.1 mrg }
2266 1.1 mrg )
2267 1.1 mrg
2268 1.1 mrg ;; SUNPKHI, UUNPKHI, SUNPKLO and UUNPKLO.
2269 1.1 mrg (define_insn "aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>"
2270 1.1 mrg [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
2271 1.1 mrg (unspec:<VWIDE> [(match_operand:SVE_BHSI 1 "register_operand" "w")]
2272 1.1 mrg UNPACK))]
2273 1.1 mrg "TARGET_SVE"
2274 1.1 mrg "<su>unpk<perm_hilo>\t%0.<Vewtype>, %1.<Vetype>"
2275 1.1 mrg )
2276 1.1 mrg
2277 1.1 mrg ;; Unpack one half of a VNx4SF to VNx2DF, or one half of a VNx8HF to VNx4SF.
2278 1.1 mrg ;; First unpack the source without conversion, then float-convert the
2279 1.1 mrg ;; unpacked source.
2280 1.1 mrg (define_expand "vec_unpacks_<perm_hilo>_<mode>"
2281 1.1 mrg [(match_operand:<VWIDE> 0 "register_operand")
2282 1.1 mrg (unspec:SVE_HSF [(match_operand:SVE_HSF 1 "register_operand")]
2283 1.1 mrg UNPACK_UNSIGNED)]
2284 1.1 mrg "TARGET_SVE"
2285 1.1 mrg {
2286 1.1 mrg /* Use ZIP to do the unpack, since we don't care about the upper halves
2287 1.1 mrg and since it has the nice property of not needing any subregs.
2288 1.1 mrg If using UUNPK* turns out to be preferable, we could model it as
2289 1.1 mrg a ZIP whose first operand is zero. */
2290 1.1 mrg rtx temp = gen_reg_rtx (<MODE>mode);
2291 1.1 mrg emit_insn ((<hi_lanes_optab>
2292 1.1 mrg ? gen_aarch64_sve_zip2<mode>
2293 1.1 mrg : gen_aarch64_sve_zip1<mode>)
2294 1.1 mrg (temp, operands[1], operands[1]));
2295 1.1 mrg rtx ptrue = force_reg (<VWIDE_PRED>mode, CONSTM1_RTX (<VWIDE_PRED>mode));
2296 1.1 mrg emit_insn (gen_aarch64_sve_extend<mode><Vwide>2 (operands[0],
2297 1.1 mrg ptrue, temp));
2298 1.1 mrg DONE;
2299 1.1 mrg }
2300 1.1 mrg )
2301 1.1 mrg
2302 1.1 mrg ;; Unpack one half of a VNx4SI to VNx2DF. First unpack from VNx4SI
2303 1.1 mrg ;; to VNx2DI, reinterpret the VNx2DI as a VNx4SI, then convert the
2304 1.1 mrg ;; unpacked VNx4SI to VNx2DF.
2305 1.1 mrg (define_expand "vec_unpack<su_optab>_float_<perm_hilo>_vnx4si"
2306 1.1 mrg [(match_operand:VNx2DF 0 "register_operand")
2307 1.1 mrg (FLOATUORS:VNx2DF
2308 1.1 mrg (unspec:VNx2DI [(match_operand:VNx4SI 1 "register_operand")]
2309 1.1 mrg UNPACK_UNSIGNED))]
2310 1.1 mrg "TARGET_SVE"
2311 1.1 mrg {
2312 1.1 mrg /* Use ZIP to do the unpack, since we don't care about the upper halves
2313 1.1 mrg and since it has the nice property of not needing any subregs.
2314 1.1 mrg If using UUNPK* turns out to be preferable, we could model it as
2315 1.1 mrg a ZIP whose first operand is zero. */
2316 1.1 mrg rtx temp = gen_reg_rtx (VNx4SImode);
2317 1.1 mrg emit_insn ((<hi_lanes_optab>
2318 1.1 mrg ? gen_aarch64_sve_zip2vnx4si
2319 1.1 mrg : gen_aarch64_sve_zip1vnx4si)
2320 1.1 mrg (temp, operands[1], operands[1]));
2321 1.1 mrg rtx ptrue = force_reg (VNx2BImode, CONSTM1_RTX (VNx2BImode));
2322 1.1 mrg emit_insn (gen_aarch64_sve_<FLOATUORS:optab>vnx4sivnx2df2 (operands[0],
2323 1.1 mrg ptrue, temp));
2324 1.1 mrg DONE;
2325 1.1 mrg }
2326 1.1 mrg )
2327 1.1 mrg
2328 1.1 mrg ;; Predicate pack. Use UZP1 on the narrower type, which discards
2329 1.1 mrg ;; the high part of each wide element.
2330 1.1 mrg (define_insn "vec_pack_trunc_<Vwide>"
2331 1.1 mrg [(set (match_operand:PRED_BHS 0 "register_operand" "=Upa")
2332 1.1 mrg (unspec:PRED_BHS
2333 1.1 mrg [(match_operand:<VWIDE> 1 "register_operand" "Upa")
2334 1.1 mrg (match_operand:<VWIDE> 2 "register_operand" "Upa")]
2335 1.1 mrg UNSPEC_PACK))]
2336 1.1 mrg "TARGET_SVE"
2337 1.1 mrg "uzp1\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
2338 1.1 mrg )
2339 1.1 mrg
2340 1.1 mrg ;; Integer pack. Use UZP1 on the narrower type, which discards
2341 1.1 mrg ;; the high part of each wide element.
2342 1.1 mrg (define_insn "vec_pack_trunc_<Vwide>"
2343 1.1 mrg [(set (match_operand:SVE_BHSI 0 "register_operand" "=w")
2344 1.1 mrg (unspec:SVE_BHSI
2345 1.1 mrg [(match_operand:<VWIDE> 1 "register_operand" "w")
2346 1.1 mrg (match_operand:<VWIDE> 2 "register_operand" "w")]
2347 1.1 mrg UNSPEC_PACK))]
2348 1.1 mrg "TARGET_SVE"
2349 1.1 mrg "uzp1\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
2350 1.1 mrg )
2351 1.1 mrg
2352 1.1 mrg ;; Convert two vectors of DF to SF, or two vectors of SF to HF, and pack
2353 1.1 mrg ;; the results into a single vector.
2354 1.1 mrg (define_expand "vec_pack_trunc_<Vwide>"
2355 1.1 mrg [(set (match_dup 4)
2356 1.1 mrg (unspec:SVE_HSF
2357 1.1 mrg [(match_dup 3)
2358 1.1 mrg (unspec:SVE_HSF [(match_operand:<VWIDE> 1 "register_operand")]
2359 1.1 mrg UNSPEC_FLOAT_CONVERT)]
2360 1.1 mrg UNSPEC_MERGE_PTRUE))
2361 1.1 mrg (set (match_dup 5)
2362 1.1 mrg (unspec:SVE_HSF
2363 1.1 mrg [(match_dup 3)
2364 1.1 mrg (unspec:SVE_HSF [(match_operand:<VWIDE> 2 "register_operand")]
2365 1.1 mrg UNSPEC_FLOAT_CONVERT)]
2366 1.1 mrg UNSPEC_MERGE_PTRUE))
2367 1.1 mrg (set (match_operand:SVE_HSF 0 "register_operand")
2368 1.1 mrg (unspec:SVE_HSF [(match_dup 4) (match_dup 5)] UNSPEC_UZP1))]
2369 1.1 mrg "TARGET_SVE"
2370 1.1 mrg {
2371 1.1 mrg operands[3] = force_reg (<VWIDE_PRED>mode, CONSTM1_RTX (<VWIDE_PRED>mode));
2372 1.1 mrg operands[4] = gen_reg_rtx (<MODE>mode);
2373 1.1 mrg operands[5] = gen_reg_rtx (<MODE>mode);
2374 1.1 mrg }
2375 1.1 mrg )
2376 1.1 mrg
2377 1.1 mrg ;; Convert two vectors of DF to SI and pack the results into a single vector.
2378 1.1 mrg (define_expand "vec_pack_<su>fix_trunc_vnx2df"
2379 1.1 mrg [(set (match_dup 4)
2380 1.1 mrg (unspec:VNx4SI
2381 1.1 mrg [(match_dup 3)
2382 1.1 mrg (FIXUORS:VNx4SI (match_operand:VNx2DF 1 "register_operand"))]
2383 1.1 mrg UNSPEC_MERGE_PTRUE))
2384 1.1 mrg (set (match_dup 5)
2385 1.1 mrg (unspec:VNx4SI
2386 1.1 mrg [(match_dup 3)
2387 1.1 mrg (FIXUORS:VNx4SI (match_operand:VNx2DF 2 "register_operand"))]
2388 1.1 mrg UNSPEC_MERGE_PTRUE))
2389 1.1 mrg (set (match_operand:VNx4SI 0 "register_operand")
2390 1.1 mrg (unspec:VNx4SI [(match_dup 4) (match_dup 5)] UNSPEC_UZP1))]
2391 1.1 mrg "TARGET_SVE"
2392 1.1 mrg {
2393 1.1 mrg operands[3] = force_reg (VNx2BImode, CONSTM1_RTX (VNx2BImode));
2394 1.1 mrg operands[4] = gen_reg_rtx (VNx4SImode);
2395 1.1 mrg operands[5] = gen_reg_rtx (VNx4SImode);
2396 1.1 mrg }
2397 1.1 mrg )
2398 1.1 mrg
2399 1.1 mrg ;; Predicated floating-point operations.
2400 1.1 mrg (define_insn "cond_<optab><mode>"
2401 1.1 mrg [(set (match_operand:SVE_F 0 "register_operand" "=w")
2402 1.1 mrg (unspec:SVE_F
2403 1.1 mrg [(match_operand:<VPRED> 1 "register_operand" "Upl")
2404 1.1 mrg (match_operand:SVE_F 2 "register_operand" "0")
2405 1.1 mrg (match_operand:SVE_F 3 "register_operand" "w")]
2406 1.1 mrg SVE_COND_FP_OP))]
2407 1.1 mrg "TARGET_SVE"
2408 1.1 mrg "<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
2409 1.1 mrg )
2410 1.1 mrg
2411 1.1 mrg ;; Shift an SVE vector left and insert a scalar into element 0.
2412 1.1 mrg (define_insn "vec_shl_insert_<mode>"
2413 1.1 mrg [(set (match_operand:SVE_ALL 0 "register_operand" "=w, w")
2414 1.1 mrg (unspec:SVE_ALL
2415 1.1 mrg [(match_operand:SVE_ALL 1 "register_operand" "0, 0")
2416 1.1 mrg (match_operand:<VEL> 2 "register_operand" "rZ, w")]
2417 1.1 mrg UNSPEC_INSR))]
2418 1.1 mrg "TARGET_SVE"
2419 1.1 mrg "@
2420 1.1 mrg insr\t%0.<Vetype>, %<vwcore>2
2421 1.1 mrg insr\t%0.<Vetype>, %<Vetype>2"
2422 1.1 mrg )
2423