rs6000: Fix wrong RTL patterns for vector merge high/low word on LE
[official-gcc.git] / gcc / config / aarch64 / aarch64.md
blob9de6235b1398f1ed77686f7a914960c662a88dc8
1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; Register numbers
22 (define_constants
23   [
24     (R0_REGNUM          0)
25     (R1_REGNUM          1)
26     (R2_REGNUM          2)
27     (R3_REGNUM          3)
28     (R4_REGNUM          4)
29     (R5_REGNUM          5)
30     (R6_REGNUM          6)
31     (R7_REGNUM          7)
32     (R8_REGNUM          8)
33     (R9_REGNUM          9)
34     (R10_REGNUM         10)
35     (R11_REGNUM         11)
36     (R12_REGNUM         12)
37     (R13_REGNUM         13)
38     (R14_REGNUM         14)
39     (R15_REGNUM         15)
40     (R16_REGNUM         16)
41     (R17_REGNUM         17)
42     (R18_REGNUM         18)
43     (R19_REGNUM         19)
44     (R20_REGNUM         20)
45     (R21_REGNUM         21)
46     (R22_REGNUM         22)
47     (R23_REGNUM         23)
48     (R24_REGNUM         24)
49     (R25_REGNUM         25)
50     (R26_REGNUM         26)
51     (R27_REGNUM         27)
52     (R28_REGNUM         28)
53     (R29_REGNUM         29)
54     (R30_REGNUM         30)
55     (SP_REGNUM          31)
56     (V0_REGNUM          32)
57     (V1_REGNUM          33)
58     (V2_REGNUM          34)
59     (V3_REGNUM          35)
60     (V4_REGNUM          36)
61     (V5_REGNUM          37)
62     (V6_REGNUM          38)
63     (V7_REGNUM          39)
64     (V8_REGNUM          40)
65     (V9_REGNUM          41)
66     (V10_REGNUM         42)
67     (V11_REGNUM         43)
68     (V12_REGNUM         44)
69     (V13_REGNUM         45)
70     (V14_REGNUM         46)
71     (V15_REGNUM         47)
72     (V16_REGNUM         48)
73     (V17_REGNUM         49)
74     (V18_REGNUM         50)
75     (V19_REGNUM         51)
76     (V20_REGNUM         52)
77     (V21_REGNUM         53)
78     (V22_REGNUM         54)
79     (V23_REGNUM         55)
80     (V24_REGNUM         56)
81     (V25_REGNUM         57)
82     (V26_REGNUM         58)
83     (V27_REGNUM         59)
84     (V28_REGNUM         60)
85     (V29_REGNUM         61)
86     (V30_REGNUM         62)
87     (V31_REGNUM         63)
88     (SFP_REGNUM         64)
89     (AP_REGNUM          65)
90     (CC_REGNUM          66)
91     ;; Defined only to make the DWARF description simpler.
92     (VG_REGNUM          67)
93     (P0_REGNUM          68)
94     (P1_REGNUM          69)
95     (P2_REGNUM          70)
96     (P3_REGNUM          71)
97     (P4_REGNUM          72)
98     (P5_REGNUM          73)
99     (P6_REGNUM          74)
100     (P7_REGNUM          75)
101     (P8_REGNUM          76)
102     (P9_REGNUM          77)
103     (P10_REGNUM         78)
104     (P11_REGNUM         79)
105     (P12_REGNUM         80)
106     (P13_REGNUM         81)
107     (P14_REGNUM         82)
108     (P15_REGNUM         83)
109     (LAST_SAVED_REGNUM  83)
110     (FFR_REGNUM         84)
111     ;; "FFR token": a fake register used for representing the scheduling
112     ;; restrictions on FFR-related operations.
113     (FFRT_REGNUM        85)
115     ;; ----------------------------------------------------------------
116     ;; Fake registers
117     ;; ----------------------------------------------------------------
118     ;; These registers represent abstract things, rather than real
119     ;; architected registers.
121     ;; Sometimes we use placeholder instructions to mark where later
122     ;; ABI-related lowering is needed.  These placeholders read and
123     ;; write this register.  Instructions that depend on the lowering
124     ;; read the register.
125     (LOWERING_REGNUM 86)
127     ;; Represents the contents of the current function's TPIDR2 block,
128     ;; in abstract form.
129     (TPIDR2_BLOCK_REGNUM 87)
131     ;; Holds the value that the current function wants PSTATE.ZA to be.
132     ;; The actual value can sometimes vary, because it does not track
133     ;; changes to PSTATE.ZA that happen during a lazy save and restore.
134     ;; Those effects are instead tracked by ZA_SAVED_REGNUM.
135     (SME_STATE_REGNUM 88)
137     ;; Instructions write to this register if they set TPIDR2_EL0 to a
138     ;; well-defined value.  Instructions read from the register if they
139     ;; depend on the result of such writes.
140     ;;
141     ;; The register does not model the architected TPIDR2_ELO, just the
142     ;; current function's management of it.
143     (TPIDR2_SETUP_REGNUM 89)
145     ;; Represents the property "has an incoming lazy save been committed?".
146     (ZA_FREE_REGNUM 90)
148     ;; Represents the property "are the current function's ZA contents
149     ;; stored in the lazy save buffer, rather than in ZA itself?".
150     (ZA_SAVED_REGNUM 91)
152     ;; Represents the contents of the current function's ZA state in
153     ;; abstract form.  At various times in the function, these contents
154     ;; might be stored in ZA itself, or in the function's lazy save buffer.
155     ;;
156     ;; The contents persist even when the architected ZA is off.  Private-ZA
157     ;; functions have no effect on its contents.
158     (ZA_REGNUM 92)
160     ;; Similarly represents the contents of the current function's ZT0 state.
161     (ZT0_REGNUM 93)
163     (FIRST_FAKE_REGNUM  LOWERING_REGNUM)
164     (LAST_FAKE_REGNUM   ZT0_REGNUM)
165     ;; ----------------------------------------------------------------
167     ;; The pair of scratch registers used for stack probing with -fstack-check.
168     ;; Leave R9 alone as a possible choice for the static chain.
169     ;; Note that the use of these registers is mutually exclusive with the use
170     ;; of STACK_CLASH_SVE_CFA_REGNUM, which is for -fstack-clash-protection
171     ;; rather than -fstack-check.
172     (PROBE_STACK_FIRST_REGNUM  10)
173     (PROBE_STACK_SECOND_REGNUM 11)
174     ;; Scratch register used by stack clash protection to calculate
175     ;; SVE CFA offsets during probing.
176     (STACK_CLASH_SVE_CFA_REGNUM 11)
177     ;; Scratch registers for prologue/epilogue use.
178     (EP0_REGNUM         12)
179     (EP1_REGNUM         13)
180     ;; A couple of call-clobbered registers that we need to reserve when
181     ;; tracking speculation this is not ABI, so is subject to change.
182     (SPECULATION_SCRATCH_REGNUM 14)
183     (SPECULATION_TRACKER_REGNUM 15)
184     ;; Scratch registers used in frame layout.
185     (IP0_REGNUM         16)
186     (IP1_REGNUM         17)
187     (FP_REGNUM          29)
188     (LR_REGNUM          30)
189   ]
192 (define_c_enum "unspec" [
193     UNSPEC_AUTIA1716
194     UNSPEC_AUTIB1716
195     UNSPEC_AUTIASP
196     UNSPEC_AUTIBSP
197     UNSPEC_CALLEE_ABI
198     UNSPEC_CASESI
199     UNSPEC_CPYMEM
200     UNSPEC_CRC32B
201     UNSPEC_CRC32CB
202     UNSPEC_CRC32CH
203     UNSPEC_CRC32CW
204     UNSPEC_CRC32CX
205     UNSPEC_CRC32H
206     UNSPEC_CRC32W
207     UNSPEC_CRC32X
208     UNSPEC_FCVTZS
209     UNSPEC_FCVTZU
210     UNSPEC_FJCVTZS
211     UNSPEC_FRINT32Z
212     UNSPEC_FRINT32X
213     UNSPEC_FRINT64Z
214     UNSPEC_FRINT64X
215     UNSPEC_URECPE
216     UNSPEC_FRECPE
217     UNSPEC_FRECPS
218     UNSPEC_FRECPX
219     UNSPEC_FRINTA
220     UNSPEC_FRINTI
221     UNSPEC_FRINTM
222     UNSPEC_FRINTN
223     UNSPEC_FRINTP
224     UNSPEC_FRINTX
225     UNSPEC_FRINTZ
226     UNSPEC_GOTSMALLPIC
227     UNSPEC_GOTSMALLPIC28K
228     UNSPEC_GOTSMALLTLS
229     UNSPEC_GOTTINYPIC
230     UNSPEC_GOTTINYTLS
231     UNSPEC_STP
232     UNSPEC_LDP_FST
233     UNSPEC_LDP_SND
234     UNSPEC_LD1
235     UNSPEC_LD2
236     UNSPEC_LD2_DREG
237     UNSPEC_LD2_DUP
238     UNSPEC_LD3
239     UNSPEC_LD3_DREG
240     UNSPEC_LD3_DUP
241     UNSPEC_LD4
242     UNSPEC_LD4_DREG
243     UNSPEC_LD4_DUP
244     UNSPEC_LD2_LANE
245     UNSPEC_LD3_LANE
246     UNSPEC_LD4_LANE
247     UNSPEC_LD64B
248     UNSPEC_ST64B
249     UNSPEC_ST64BV
250     UNSPEC_ST64BV_RET
251     UNSPEC_ST64BV0
252     UNSPEC_ST64BV0_RET
253     UNSPEC_MB
254     UNSPEC_MOVMEM
255     UNSPEC_NOP
256     UNSPEC_PACIA1716
257     UNSPEC_PACIB1716
258     UNSPEC_PACIASP
259     UNSPEC_PACIBSP
260     UNSPEC_PRLG_STK
261     UNSPEC_REV
262     UNSPEC_SADALP
263     UNSPEC_SCVTF
264     UNSPEC_SETMEM
265     UNSPEC_SISD_NEG
266     UNSPEC_SISD_SSHL
267     UNSPEC_SISD_USHL
268     UNSPEC_SSHL_2S
269     UNSPEC_ST1
270     UNSPEC_ST2
271     UNSPEC_ST3
272     UNSPEC_ST4
273     UNSPEC_ST2_LANE
274     UNSPEC_ST3_LANE
275     UNSPEC_ST4_LANE
276     UNSPEC_TLS
277     UNSPEC_TLSDESC
278     UNSPEC_TLSLE12
279     UNSPEC_TLSLE24
280     UNSPEC_TLSLE32
281     UNSPEC_TLSLE48
282     UNSPEC_UADALP
283     UNSPEC_UCVTF
284     UNSPEC_USHL_2S
285     UNSPEC_VSTRUCTDUMMY
286     UNSPEC_SSP_SYSREG
287     UNSPEC_SP_SET
288     UNSPEC_SP_TEST
289     UNSPEC_RSQRT
290     UNSPEC_RSQRTE
291     UNSPEC_RSQRTS
292     UNSPEC_NZCV
293     UNSPEC_XPACLRI
294     UNSPEC_LD1_SVE
295     UNSPEC_ST1_SVE
296     UNSPEC_LDNT1_SVE
297     UNSPEC_STNT1_SVE
298     UNSPEC_LD1RQ
299     UNSPEC_LD1_GATHER
300     UNSPEC_LDFF1_GATHER
301     UNSPEC_LDNT1_GATHER
302     UNSPEC_ST1_SCATTER
303     UNSPEC_STNT1_SCATTER
304     UNSPEC_PRED_X
305     UNSPEC_PRED_Z
306     UNSPEC_PTEST
307     UNSPEC_PTRUE
308     UNSPEC_UNPACKSHI
309     UNSPEC_UNPACKUHI
310     UNSPEC_UNPACKSLO
311     UNSPEC_UNPACKULO
312     UNSPEC_PACK
313     UNSPEC_WHILEGE
314     UNSPEC_WHILEGT
315     UNSPEC_WHILEHI
316     UNSPEC_WHILEHS
317     UNSPEC_WHILELE
318     UNSPEC_WHILELO
319     UNSPEC_WHILELS
320     UNSPEC_WHILELT
321     UNSPEC_WHILERW
322     UNSPEC_WHILEWR
323     UNSPEC_LDN
324     UNSPEC_STN
325     UNSPEC_INSR
326     UNSPEC_CLASTA
327     UNSPEC_CLASTB
328     UNSPEC_FADDA
329     UNSPEC_REV_SUBREG
330     UNSPEC_REINTERPRET
331     UNSPEC_SPECULATION_TRACKER
332     UNSPEC_SPECULATION_TRACKER_REV
333     UNSPEC_COPYSIGN
334     UNSPEC_TTEST                ; Represent transaction test.
335     UNSPEC_UPDATE_FFR
336     UNSPEC_UPDATE_FFRT
337     UNSPEC_RDFFR
338     UNSPEC_WRFFR
339     UNSPEC_SYSREG_RDI
340     UNSPEC_SYSREG_RTI
341     UNSPEC_SYSREG_WDI
342     UNSPEC_SYSREG_WTI
343     UNSPEC_PLDX
344     ;; Represents an SVE-style lane index, in which the indexing applies
345     ;; within the containing 128-bit block.
346     UNSPEC_SVE_LANE_SELECT
347     UNSPEC_SVE_CNT_PAT
348     UNSPEC_SVE_PREFETCH
349     UNSPEC_SVE_PREFETCH_GATHER
350     UNSPEC_SVE_COMPACT
351     UNSPEC_SVE_SPLICE
352     UNSPEC_GEN_TAG              ; Generate a 4-bit MTE tag.
353     UNSPEC_GEN_TAG_RND          ; Generate a random 4-bit MTE tag.
354     UNSPEC_TAG_SPACE            ; Translate address to MTE tag address space.
355     UNSPEC_LD1RO
356     UNSPEC_SALT_ADDR
357     UNSPEC_SAVE_NZCV
358     UNSPEC_RESTORE_NZCV
359     UNSPECV_PATCHABLE_AREA
360     UNSPEC_LDAP1_LANE
361     UNSPEC_STL1_LANE
362     ;; Wraps a constant integer that should be multiplied by the number
363     ;; of quadwords in an SME vector.
364     UNSPEC_SME_VQ
367 (define_c_enum "unspecv" [
368     UNSPECV_EH_RETURN           ; Represent EH_RETURN
369     UNSPECV_GET_FPCR            ; Represent fetch of FPCR content.
370     UNSPECV_SET_FPCR            ; Represent assign of FPCR content.
371     UNSPECV_GET_FPSR            ; Represent fetch of FPSR content.
372     UNSPECV_SET_FPSR            ; Represent assign of FPSR content.
373     UNSPECV_BLOCKAGE            ; Represent a blockage
374     UNSPECV_PROBE_STACK_RANGE   ; Represent stack range probing.
375     UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
376     UNSPECV_BTI_NOARG           ; Represent BTI.
377     UNSPECV_BTI_C               ; Represent BTI c.
378     UNSPECV_BTI_J               ; Represent BTI j.
379     UNSPECV_BTI_JC              ; Represent BTI jc.
380     UNSPECV_TSTART              ; Represent transaction start.
381     UNSPECV_TCOMMIT             ; Represent transaction commit.
382     UNSPECV_TCANCEL             ; Represent transaction cancel.
383     UNSPEC_RNDR                 ; Represent RNDR
384     UNSPEC_RNDRRS               ; Represent RNDRRS
385   ]
388 ;; These constants are used as a const_int in various SVE unspecs
389 ;; to indicate whether the governing predicate is known to be a PTRUE.
390 (define_constants
391   [; Indicates that the predicate might not be a PTRUE.
392    (SVE_MAYBE_NOT_PTRUE 0)
394    ; Indicates that the predicate is known to be a PTRUE.
395    (SVE_KNOWN_PTRUE 1)])
397 ;; These constants are used as a const_int in predicated SVE FP arithmetic
398 ;; to indicate whether the operation is allowed to make additional lanes
399 ;; active without worrying about the effect on faulting behavior.
400 (define_constants
401   [; Indicates either that all lanes are active or that the instruction may
402    ; operate on inactive inputs even if doing so could induce a fault.
403    (SVE_RELAXED_GP 0)
405    ; Indicates that some lanes might be inactive and that the instruction
406    ; must not operate on inactive inputs if doing so could induce a fault.
407    (SVE_STRICT_GP 1)])
409 (include "constraints.md")
410 (include "predicates.md")
411 (include "iterators.md")
413 ;; -------------------------------------------------------------------
414 ;; Instruction types and attributes
415 ;; -------------------------------------------------------------------
417 ; The "type" attribute is included here from AArch32 backend to be able
418 ; to share pipeline descriptions.
419 (include "../arm/types.md")
421 ;; It is important to set the fp or simd attributes to yes when a pattern
422 ;; alternative uses the FP or SIMD register files, usually signified by use of
423 ;; the 'w' constraint.  This will ensure that the alternative will be
424 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
425 ;; architecture extensions.  If all the alternatives in a pattern use the
426 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
427 ;; or TARGET_SIMD.
429 ;; Attributes of the architecture required to support the instruction (or
430 ;; alternative). This attribute is used to compute attribute "enabled", use type
431 ;; "any" to enable an alternative in all cases.
433 ;; As a convenience, "fp_q" means "fp" + the ability to move between
434 ;; Q registers and is equivalent to "simd".
436 (define_enum "arches" [any rcpc8_4 fp fp_q base_simd nobase_simd
437                        simd nosimd sve fp16 sme])
439 (define_enum_attr "arch" "arches" (const_string "any"))
441 ;; Whether a normal INSN in fact contains a call.  Sometimes we represent
442 ;; calls to functions that use an ad-hoc ABI as normal insns, both for
443 ;; optimization reasons and to avoid the need to describe the ABI to
444 ;; target-independent code.
445 (define_attr "is_call" "no,yes" (const_string "no"))
447 ;; Indicates whether we want to enable the pattern with an optional early
448 ;; clobber for SVE predicates.
449 (define_attr "pred_clobber" "any,no,yes" (const_string "any"))
451 ;; [For compatibility with Arm in pipeline models]
452 ;; Attribute that specifies whether or not the instruction touches fp
453 ;; registers.
454 ;; Note that this attribute is not used anywhere in either the arm or aarch64
455 ;; backends except in the scheduling description for xgene1.  In that
456 ;; scheduling description this attribute is used to subclass the load_4 and
457 ;; load_8 types.
458 (define_attr "fp" "no,yes"
459   (if_then_else
460     (eq_attr "arch" "fp")
461     (const_string "yes")
462     (const_string "no")))
464 (define_attr "arch_enabled" "no,yes"
465   (if_then_else
466     (and
467       (ior
468         (and
469           (eq_attr "pred_clobber" "no")
470           (match_test "!TARGET_SVE_PRED_CLOBBER"))
471         (and
472           (eq_attr "pred_clobber" "yes")
473           (match_test "TARGET_SVE_PRED_CLOBBER"))
474         (eq_attr "pred_clobber" "any"))
476       (ior
477         (eq_attr "arch" "any")
479         (and (eq_attr "arch" "rcpc8_4")
480              (match_test "AARCH64_ISA_RCPC8_4"))
482         (and (eq_attr "arch" "fp")
483              (match_test "TARGET_FLOAT"))
485         (and (eq_attr "arch" "base_simd")
486              (match_test "TARGET_BASE_SIMD"))
488         (and (eq_attr "arch" "nobase_simd")
489              (match_test "!TARGET_BASE_SIMD"))
491         (and (eq_attr "arch" "fp_q, simd")
492              (match_test "TARGET_SIMD"))
494         (and (eq_attr "arch" "nosimd")
495              (match_test "!TARGET_SIMD"))
497         (and (eq_attr "arch" "fp16")
498              (match_test "TARGET_FP_F16INST"))
500         (and (eq_attr "arch" "sve")
501              (match_test "TARGET_SVE"))
503         (and (eq_attr "arch" "sme")
504              (match_test "TARGET_SME"))))
505     (const_string "yes")
506     (const_string "no")))
508 ;; Attribute that controls whether an alternative is enabled or not.
509 ;; Currently it is only used to disable alternatives which touch fp or simd
510 ;; registers when -mgeneral-regs-only is specified or to require a special
511 ;; architecture support.
512 (define_attr "enabled" "no,yes" (attr "arch_enabled"))
514 ;; Attribute that specifies whether we are dealing with a branch to a
515 ;; label that is far away, i.e. further away than the maximum/minimum
516 ;; representable in a signed 21-bits number.
517 ;; 0 :=: no
518 ;; 1 :=: yes
519 (define_attr "far_branch" "" (const_int 0))
521 ;; Attribute that specifies whether the alternative uses MOVPRFX.
522 (define_attr "movprfx" "no,yes" (const_string "no"))
524 ;; Attribute to specify that an alternative has the length of a single
525 ;; instruction plus a speculation barrier.
526 (define_attr "sls_length" "none,retbr,casesi" (const_string "none"))
528 (define_attr "length" ""
529   (cond [(eq_attr "movprfx" "yes")
530            (const_int 8)
532          (eq_attr "sls_length" "retbr")
533            (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 4)
534                   (match_test "TARGET_SB") (const_int 8)]
535                  (const_int 12))
537          (eq_attr "sls_length" "casesi")
538            (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 16)
539                   (match_test "TARGET_SB") (const_int 20)]
540                  (const_int 24))
541         ]
542           (const_int 4)))
544 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
545 ;; no predicated insns.
546 (define_attr "predicated" "yes,no" (const_string "no"))
548 ;; Set to true on an insn that requires the speculation tracking state to be
549 ;; in the tracking register before the insn issues.  Otherwise the compiler
550 ;; may chose to hold the tracking state encoded in SP.
551 (define_attr "speculation_barrier" "true,false" (const_string "false"))
553 ;; This attribute is attached to multi-register instructions that have
554 ;; two forms: one in which the registers are consecutive and one in
555 ;; which they are strided.  The consecutive and strided forms have
556 ;; different define_insns, with different operands.  The mapping between
557 ;; the RTL of the consecutive form and the RTL of the strided form varies
558 ;; from one type of instruction to another.
560 ;; The attribute gives two pieces of information:
561 ;; - does the current instruction have consecutive or strided registers?
562 ;; - what kind of RTL rewrite is needed to move between forms?
564 ;; For example, all consecutive LD*1 instructions have the same basic
565 ;; RTL structure.  The same applies to all strided LD*1 instructions.
566 ;; The RTL mapping therefore applies at LD1 granularity, rather than
567 ;; being broken down into individual types of load.
568 (define_attr "stride_type"
569   "none,ld1_consecutive,ld1_strided,st1_consecutive,st1_strided"
570   (const_string "none"))
572 ;; Attribute used to identify load pair and store pair instructions.
573 ;; Currently the attribute is only applied to the non-writeback ldp/stp
574 ;; patterns.
575 (define_attr "ldpstp" "ldp,stp,none" (const_string "none"))
577 ;; -------------------------------------------------------------------
578 ;; Pipeline descriptions and scheduling
579 ;; -------------------------------------------------------------------
581 ;; Processor types.
582 (include "aarch64-tune.md")
584 ;; Scheduling
585 (include "../arm/cortex-a53.md")
586 (include "../arm/cortex-a57.md")
587 (include "../arm/exynos-m1.md")
588 (include "falkor.md")
589 (include "saphira.md")
590 (include "thunderx.md")
591 (include "../arm/xgene1.md")
592 (include "thunderx2t99.md")
593 (include "tsv110.md")
594 (include "thunderx3t110.md")
596 ;; -------------------------------------------------------------------
597 ;; Jumps and other miscellaneous insns
598 ;; -------------------------------------------------------------------
600 (define_insn "aarch64_read_sysregdi"
601   [(set (match_operand:DI 0 "register_operand" "=r")
602         (unspec_volatile:DI [(match_operand 1 "aarch64_sysreg_string" "")]
603                             UNSPEC_SYSREG_RDI))]
604   ""
605   "mrs\t%x0, %1"
608 (define_insn "aarch64_read_sysregti"
609   [(set (match_operand:TI 0 "register_operand" "=r")
610     (unspec_volatile:TI [(match_operand 1 "aarch64_sysreg_string" "")]
611                         UNSPEC_SYSREG_RTI))]
612  "TARGET_D128"
613  "mrrs\t%x0, %H0, %x1"
616 (define_insn "aarch64_write_sysregdi"
617   [(unspec_volatile:DI [(match_operand 0 "aarch64_sysreg_string" "")
618                         (match_operand:DI 1 "register_operand" "rZ")]
619                        UNSPEC_SYSREG_WDI)]
620   ""
621   "msr\t%0, %x1"
624 (define_insn "aarch64_write_sysregti"
625  [(unspec_volatile:TI [(match_operand 0 "aarch64_sysreg_string" "")
626                        (match_operand:TI 1 "register_operand" "r")]
627                       UNSPEC_SYSREG_WTI)]
628  "TARGET_D128"
629  "msrr\t%x0, %x1, %H1"
632 (define_insn "indirect_jump"
633   [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
634   ""
635   {
636     output_asm_insn ("br\\t%0", operands);
637     return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
638   }
639   [(set_attr "type" "branch")
640    (set_attr "sls_length" "retbr")]
643 (define_insn "jump"
644   [(set (pc) (label_ref (match_operand 0 "" "")))]
645   ""
646   "b\\t%l0"
647   [(set_attr "type" "branch")]
650 (define_expand "cbranch<mode>4"
651   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
652                             [(match_operand:GPI 1 "register_operand")
653                              (match_operand:GPI 2 "aarch64_plus_operand")])
654                            (label_ref (match_operand 3 "" ""))
655                            (pc)))]
656   ""
657   "
658   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
659                                          operands[2]);
660   operands[2] = const0_rtx;
661   "
664 (define_expand "cbranch<mode>4"
665   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
666                             [(match_operand:GPF 1 "register_operand")
667                              (match_operand:GPF 2 "aarch64_fp_compare_operand")])
668                            (label_ref (match_operand 3 "" ""))
669                            (pc)))]
670   ""
671   "
672   operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
673                                          operands[2]);
674   operands[2] = const0_rtx;
675   "
678 (define_expand "cbranchcc4"
679   [(set (pc) (if_then_else
680               (match_operator 0 "aarch64_comparison_operator"
681                [(match_operand 1 "cc_register")
682                 (match_operand 2 "const0_operand")])
683               (label_ref (match_operand 3 "" ""))
684               (pc)))]
685   ""
686   "")
688 (define_insn "@ccmp<CC_ONLY:mode><GPI:mode>"
689   [(set (match_operand:CC_ONLY 1 "cc_register")
690         (if_then_else:CC_ONLY
691           (match_operator 4 "aarch64_comparison_operator"
692            [(match_operand 0 "cc_register")
693             (const_int 0)])
694           (compare:CC_ONLY
695             (match_operand:GPI 2 "register_operand")
696             (match_operand:GPI 3 "aarch64_ccmp_operand"))
697           (unspec:CC_ONLY
698             [(match_operand 5 "immediate_operand")]
699             UNSPEC_NZCV)))]
700   ""
701   {@ [ cons: 2 , 3   ; attrs: type ]
702      [ r       , r   ; alus_sreg   ] ccmp\t%<w>2, %<w>3, %k5, %m4
703      [ r       , Uss ; alus_imm    ] ccmp\t%<w>2, %3, %k5, %m4
704      [ r       , Usn ; alus_imm    ] ccmn\t%<w>2, #%n3, %k5, %m4
705   }
708 (define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>"
709   [(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
710         (if_then_else:CCFP_CCFPE
711           (match_operator 4 "aarch64_comparison_operator"
712            [(match_operand 0 "cc_register" "")
713             (const_int 0)])
714           (compare:CCFP_CCFPE
715             (match_operand:GPF 2 "register_operand" "w")
716             (match_operand:GPF 3 "register_operand" "w"))
717           (unspec:CCFP_CCFPE
718             [(match_operand 5 "immediate_operand")]
719             UNSPEC_NZCV)))]
720   "TARGET_FLOAT"
721   "fccmp<e>\\t%<s>2, %<s>3, %k5, %m4"
722   [(set_attr "type" "fccmp<s>")]
725 (define_insn "@ccmp<CC_ONLY:mode><GPI:mode>_rev"
726   [(set (match_operand:CC_ONLY 1 "cc_register")
727         (if_then_else:CC_ONLY
728           (match_operator 4 "aarch64_comparison_operator"
729            [(match_operand 0 "cc_register")
730             (const_int 0)])
731           (unspec:CC_ONLY
732             [(match_operand 5 "immediate_operand")]
733             UNSPEC_NZCV)
734           (compare:CC_ONLY
735             (match_operand:GPI 2 "register_operand")
736             (match_operand:GPI 3 "aarch64_ccmp_operand"))))]
737   ""
738   {@ [ cons: 2 , 3   ; attrs: type ]
739      [ r       , r   ; alus_sreg   ] ccmp\t%<w>2, %<w>3, %k5, %M4
740      [ r       , Uss ; alus_imm    ] ccmp\t%<w>2, %3, %k5, %M4
741      [ r       , Usn ; alus_imm    ] ccmn\t%<w>2, #%n3, %k5, %M4
742   }
745 (define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>_rev"
746   [(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
747         (if_then_else:CCFP_CCFPE
748           (match_operator 4 "aarch64_comparison_operator"
749            [(match_operand 0 "cc_register" "")
750             (const_int 0)])
751           (unspec:CCFP_CCFPE
752             [(match_operand 5 "immediate_operand")]
753             UNSPEC_NZCV)
754           (compare:CCFP_CCFPE
755             (match_operand:GPF 2 "register_operand" "w")
756             (match_operand:GPF 3 "register_operand" "w"))))]
757   "TARGET_FLOAT"
758   "fccmp<e>\\t%<s>2, %<s>3, %k5, %M4"
759   [(set_attr "type" "fccmp<s>")]
762 ;; Expansion of signed mod by a power of 2 using CSNEG.
763 ;; For x0 % n where n is a power of 2 produce:
764 ;; negs   x1, x0
765 ;; and    x0, x0, #(n - 1)
766 ;; and    x1, x1, #(n - 1)
767 ;; csneg  x0, x0, x1, mi
769 (define_expand "mod<mode>3"
770   [(match_operand:GPI 0 "register_operand")
771    (match_operand:GPI 1 "register_operand")
772    (match_operand:GPI 2 "const_int_operand")]
773   ""
774   {
775     HOST_WIDE_INT val = INTVAL (operands[2]);
777     if (val <= 0
778        || exact_log2 (val) <= 0
779        || !aarch64_bitmask_imm (val - 1, <MODE>mode))
780       FAIL;
782     rtx mask = GEN_INT (val - 1);
784     /* In the special case of x0 % 2 we can do the even shorter:
785         cmp    x0, xzr
786         and    x0, x0, 1
787         cneg   x0, x0, lt.  */
788     if (val == 2)
789       {
790         rtx masked = gen_reg_rtx (<MODE>mode);
791         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
792         emit_insn (gen_and<mode>3 (masked, operands[1], mask));
793         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
794         emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
795         DONE;
796       }
798     rtx neg_op = gen_reg_rtx (<MODE>mode);
799     rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
801     /* Extract the condition register and mode.  */
802     rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
803     rtx cc_reg = SET_DEST (cmp);
804     rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
806     rtx masked_pos = gen_reg_rtx (<MODE>mode);
807     emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
809     rtx masked_neg = gen_reg_rtx (<MODE>mode);
810     emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
812     emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
813                                        masked_neg, masked_pos));
814     DONE;
815   }
818 (define_insn "condjump"
819   [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
820                             [(match_operand 1 "cc_register" "") (const_int 0)])
821                            (label_ref (match_operand 2 "" ""))
822                            (pc)))]
823   ""
824   {
825     /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
826        but the "." is required for SVE conditions.  */
827     bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
828     if (get_attr_length (insn) == 8)
829       return aarch64_gen_far_branch (operands, 2, "Lbcond",
830                                      use_dot_p ? "b.%M0\\t" : "b%M0\\t");
831     else
832       return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
833   }
834   [(set_attr "type" "branch")
835    (set (attr "length")
836         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
837                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
838                       (const_int 4)
839                       (const_int 8)))
840    (set (attr "far_branch")
841         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
842                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
843                       (const_int 0)
844                       (const_int 1)))]
847 ;; For a 24-bit immediate CST we can optimize the compare for equality
848 ;; and branch sequence from:
849 ;;      mov     x0, #imm1
850 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
851 ;;      cmp     x1, x0
852 ;;      b<ne,eq> .Label
853 ;; into the shorter:
854 ;;      sub     x0, x1, #(CST & 0xfff000)
855 ;;      subs    x0, x0, #(CST & 0x000fff)
856 ;;      b<ne,eq> .Label
857 (define_insn_and_split "*compare_condjump<GPI:mode>"
858   [(set (pc) (if_then_else (EQL
859                               (match_operand:GPI 0 "register_operand" "r")
860                               (match_operand:GPI 1 "aarch64_imm24" "n"))
861                            (label_ref:P (match_operand 2 "" ""))
862                            (pc)))]
863   "!aarch64_move_imm (INTVAL (operands[1]), <GPI:MODE>mode)
864    && !aarch64_plus_operand (operands[1], <GPI:MODE>mode)
865    && !reload_completed"
866   "#"
867   "&& true"
868   [(const_int 0)]
869   {
870     HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
871     HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
872     rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
873     emit_insn (gen_add<GPI:mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
874     emit_insn (gen_add<GPI:mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
875     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
876     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
877                                   cc_reg, const0_rtx);
878     emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
879     DONE;
880   }
883 (define_expand "casesi"
884   [(match_operand:SI 0 "register_operand")      ; Index
885    (match_operand:SI 1 "const_int_operand")     ; Lower bound
886    (match_operand:SI 2 "const_int_operand")     ; Total range
887    (match_operand:DI 3 "" "")                   ; Table label
888    (match_operand:DI 4 "" "")]                  ; Out of range label
889   ""
890   {
891     if (operands[1] != const0_rtx)
892       {
893         rtx reg = gen_reg_rtx (SImode);
895         /* Canonical RTL says that if you have:
897            (minus (X) (CONST))
899            then this should be emitted as:
901            (plus (X) (-CONST))
903            The use of trunc_int_for_mode ensures that the resulting
904            constant can be represented in SImode, this is important
905            for the corner case where operand[1] is INT_MIN.  */
907         operands[1]
908           = GEN_INT (trunc_int_for_mode (-UINTVAL (operands[1]), SImode));
910         if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
911               (operands[1], SImode))
912           operands[1] = force_reg (SImode, operands[1]);
913         emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
914         operands[0] = reg;
915       }
917     if (!aarch64_plus_operand (operands[2], SImode))
918       operands[2] = force_reg (SImode, operands[2]);
919     emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
920                                                  const0_rtx),
921                                     operands[0], operands[2], operands[4]));
923     operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3]));
924     operands[2]
925       = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], operands[0]),
926                         UNSPEC_CASESI);
927     operands[2] = gen_rtx_MEM (DImode, operands[2]);
928     MEM_READONLY_P (operands[2]) = 1;
929     MEM_NOTRAP_P (operands[2]) = 1;
930     emit_jump_insn (gen_casesi_dispatch (operands[2], operands[3]));
931     DONE;
932   }
935 (define_expand "casesi_dispatch"
936   [(parallel
937     [(set (pc) (match_operand:DI 0 ""))
938      (clobber (reg:CC CC_REGNUM))
939      (clobber (match_scratch:DI 2))
940      (clobber (match_scratch:DI 3))
941      (use (label_ref:DI (match_operand 1 "")))])]
942   "")
944 (define_insn "*casesi_dispatch"
945   [(parallel
946     [(set (pc)
947           (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
948                            (match_operand:SI 1 "register_operand" "r")]
949                         UNSPEC_CASESI)))
950      (clobber (reg:CC CC_REGNUM))
951      (clobber (match_scratch:DI 3 "=r"))
952      (clobber (match_scratch:DI 4 "=r"))
953      (use (label_ref:DI (match_operand 2 "" "")))])]
954   ""
955   "*
956   return aarch64_output_casesi (operands);
957   "
958   [(set_attr "sls_length" "casesi")
959    (set_attr "type" "branch")]
962 (define_insn "nop"
963   [(unspec[(const_int 0)] UNSPEC_NOP)]
964   ""
965   "nop"
966   [(set_attr "type" "no_insn")]
969 (define_insn "prefetch"
970   [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
971             (match_operand:QI 1 "const_int_operand" "")
972             (match_operand:QI 2 "const_int_operand" ""))]
973   ""
974   {
975     const char * pftype[2][4] =
976     {
977       {"prfm\\tPLDL1STRM, %0",
978        "prfm\\tPLDL3KEEP, %0",
979        "prfm\\tPLDL2KEEP, %0",
980        "prfm\\tPLDL1KEEP, %0"},
981       {"prfm\\tPSTL1STRM, %0",
982        "prfm\\tPSTL3KEEP, %0",
983        "prfm\\tPSTL2KEEP, %0",
984        "prfm\\tPSTL1KEEP, %0"},
985     };
987     int locality = INTVAL (operands[2]);
989     gcc_assert (IN_RANGE (locality, 0, 3));
991     /* PRFM accepts the same addresses as a 64-bit LDR so wrap
992        the address into a DImode MEM so that aarch64_print_operand knows
993        how to print it.  */
994     operands[0] = gen_rtx_MEM (DImode, operands[0]);
995     return pftype[INTVAL(operands[1])][locality];
996   }
997   [(set_attr "type" "load_4")]
1000 (define_insn "aarch64_pldx"
1001   [(unspec [(match_operand 0 "" "")
1002             (match_operand:DI 1 "aarch64_prefetch_operand" "Dp")] UNSPEC_PLDX)]
1003   ""
1004   {
1005     operands[1] = gen_rtx_MEM (DImode, operands[1]);
1006     return "prfm\\t%0, %1";
1007   }
1008   [(set_attr "type" "load_4")]
1011 (define_insn "trap"
1012   [(trap_if (const_int 1) (const_int 8))]
1013   ""
1014   "brk #1000"
1015   [(set_attr "type" "trap")])
1017 (define_expand "prologue"
1018   [(clobber (const_int 0))]
1019   ""
1020   "
1021   aarch64_expand_prologue ();
1022   DONE;
1023   "
1026 (define_expand "epilogue"
1027   [(clobber (const_int 0))]
1028   ""
1029   "
1030   aarch64_expand_epilogue (nullptr);
1031   DONE;
1032   "
1035 (define_insn "*do_return"
1036   [(return)]
1037   ""
1038   {
1039     const char *ret = NULL;
1040     if (aarch64_return_address_signing_enabled ()
1041         && (TARGET_PAUTH))
1042       {
1043         if (aarch64_ra_sign_key == AARCH64_KEY_B)
1044           ret = "retab";
1045         else
1046           ret = "retaa";
1047       }
1048     else
1049       ret = "ret";
1050     output_asm_insn (ret, operands);
1051     return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1052   }
1053   [(set_attr "type" "branch")
1054    (set_attr "sls_length" "retbr")]
1057 (define_expand "return"
1058   [(simple_return)]
1059   "aarch64_use_return_insn_p ()"
1060   ""
1063 (define_insn "simple_return"
1064   [(simple_return)]
1065   ""
1066   {
1067     output_asm_insn ("ret", operands);
1068     return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1069   }
1070   [(set_attr "type" "branch")
1071    (set_attr "sls_length" "retbr")]
1074 (define_insn "aarch64_cb<optab><mode>1"
1075   [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
1076                                 (const_int 0))
1077                            (label_ref (match_operand 1 "" ""))
1078                            (pc)))]
1079   "!aarch64_track_speculation"
1080   {
1081     if (get_attr_length (insn) == 8)
1082       return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
1083     else
1084       return "<cbz>\\t%<w>0, %l1";
1085   }
1086   [(set_attr "type" "branch")
1087    (set (attr "length")
1088         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
1089                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
1090                       (const_int 4)
1091                       (const_int 8)))
1092    (set (attr "far_branch")
1093         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
1094                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
1095                       (const_int 0)
1096                       (const_int 1)))]
1099 (define_expand "tbranch_<code><mode>3"
1100   [(set (pc) (if_then_else
1101               (EQL (match_operand:SHORT 0 "register_operand")
1102                    (match_operand 1 "const0_operand"))
1103               (label_ref (match_operand 2 ""))
1104               (pc)))]
1105   ""
1107   rtx bitvalue = gen_reg_rtx (<ZEROM>mode);
1108   rtx reg = gen_lowpart (<ZEROM>mode, operands[0]);
1109   rtx val = gen_int_mode (HOST_WIDE_INT_1U << UINTVAL (operands[1]), <MODE>mode);
1110   emit_insn (gen_and<zerom>3 (bitvalue, reg, val));
1111   operands[1] = const0_rtx;
1112   operands[0] = aarch64_gen_compare_reg (<CODE>, bitvalue,
1113                                          operands[1]);
1116 (define_insn "@aarch64_tb<optab><ALLI:mode><GPI:mode>"
1117   [(set (pc) (if_then_else
1118               (EQL (zero_extract:GPI (match_operand:ALLI 0 "register_operand" "r")
1119                                      (const_int 1)
1120                                      (match_operand 1
1121                                        "aarch64_simd_shift_imm_<ALLI:mode>" "n"))
1122                    (const_int 0))
1123              (label_ref (match_operand 2 "" ""))
1124              (pc)))
1125    (clobber (reg:CC CC_REGNUM))]
1126   "!aarch64_track_speculation"
1127   {
1128     if (get_attr_length (insn) == 8)
1129       {
1130         if (get_attr_far_branch (insn) == 1)
1131           return aarch64_gen_far_branch (operands, 2, "Ltb",
1132                                          "<inv_tb>\\t%<ALLI:w>0, %1, ");
1133         else
1134           {
1135             operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
1136             return "tst\t%<ALLI:w>0, %1\;<bcond>\t%l2";
1137           }
1138       }
1139     else
1140       return "<tbz>\t%<ALLI:w>0, %1, %l2";
1141   }
1142   [(set_attr "type" "branch")
1143    (set (attr "length")
1144         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
1145                            (lt (minus (match_dup 2) (pc)) (const_int 32764)))
1146                       (const_int 4)
1147                       (const_int 8)))
1148    (set (attr "far_branch")
1149         (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
1150                            (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
1151                       (const_int 0)
1152                       (const_int 1)))]
1156 (define_insn "*cb<optab><mode>1"
1157   [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
1158                                  (const_int 0))
1159                            (label_ref (match_operand 1 "" ""))
1160                            (pc)))
1161    (clobber (reg:CC CC_REGNUM))]
1162   "!aarch64_track_speculation"
1163   {
1164     if (get_attr_length (insn) == 8)
1165       {
1166         if (get_attr_far_branch (insn) == 1)
1167           return aarch64_gen_far_branch (operands, 1, "Ltb",
1168                                          "<inv_tb>\\t%<w>0, <sizem1>, ");
1169         else
1170           {
1171             char buf[64];
1172             uint64_t val = ((uint64_t) 1)
1173                 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
1174             sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
1175             output_asm_insn (buf, operands);
1176             return "<bcond>\t%l1";
1177           }
1178       }
1179     else
1180       return "<tbz>\t%<w>0, <sizem1>, %l1";
1181   }
1182   [(set_attr "type" "branch")
1183    (set (attr "length")
1184         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
1185                            (lt (minus (match_dup 1) (pc)) (const_int 32764)))
1186                       (const_int 4)
1187                       (const_int 8)))
1188    (set (attr "far_branch")
1189         (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
1190                            (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
1191                       (const_int 0)
1192                       (const_int 1)))]
1195 ;; -------------------------------------------------------------------
1196 ;; Subroutine calls and sibcalls
1197 ;; -------------------------------------------------------------------
1199 (define_expand "call"
1200   [(parallel
1201      [(call (match_operand 0 "memory_operand")
1202             (match_operand 1 "general_operand"))
1203       (unspec:DI [(match_operand 2)] UNSPEC_CALLEE_ABI)
1204       (clobber (reg:DI LR_REGNUM))])]
1205   ""
1206   "
1207   {
1208     aarch64_expand_call (NULL_RTX, operands[0], operands[2], false);
1209     DONE;
1210   }"
1213 (define_insn "*call_insn"
1214   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand"))
1215          (match_operand 1 "" ""))
1216    (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1217    (clobber (reg:DI LR_REGNUM))]
1218   ""
1219   {@ [ cons: 0 ; attrs: type ]
1220      [ Ucr     ; call        ] << aarch64_indirect_call_asm (operands[0]);
1221      [ Usf     ; call        ] bl\t%c0
1222   }
1225 (define_expand "call_value"
1226   [(parallel
1227      [(set (match_operand 0 "")
1228            (call (match_operand 1 "memory_operand")
1229                  (match_operand 2 "general_operand")))
1230      (unspec:DI [(match_operand 3)] UNSPEC_CALLEE_ABI)
1231      (clobber (reg:DI LR_REGNUM))])]
1232   ""
1233   "
1234   {
1235     aarch64_expand_call (operands[0], operands[1], operands[3], false);
1236     DONE;
1237   }"
1240 (define_insn "*call_value_insn"
1241   [(set (match_operand 0 "" "")
1242         (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand"))
1243                       (match_operand 2 "" "")))
1244    (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1245    (clobber (reg:DI LR_REGNUM))]
1246   ""
1247   {@ [ cons: 1 ; attrs: type ]
1248      [ Ucr     ; call        ] << aarch64_indirect_call_asm (operands[1]);
1249      [ Usf     ; call        ] bl\t%c1
1250   }
1253 (define_expand "sibcall"
1254   [(parallel
1255      [(call (match_operand 0 "memory_operand")
1256             (match_operand 1 "general_operand"))
1257       (unspec:DI [(match_operand 2)] UNSPEC_CALLEE_ABI)
1258       (return)])]
1259   ""
1260   {
1261     aarch64_expand_call (NULL_RTX, operands[0], operands[2], true);
1262     DONE;
1263   }
1266 (define_expand "sibcall_value"
1267   [(parallel
1268      [(set (match_operand 0 "")
1269            (call (match_operand 1 "memory_operand")
1270                  (match_operand 2 "general_operand")))
1271       (unspec:DI [(match_operand 3)] UNSPEC_CALLEE_ABI)
1272       (return)])]
1273   ""
1274   {
1275     aarch64_expand_call (operands[0], operands[1], operands[3], true);
1276     DONE;
1277   }
1280 (define_insn "*sibcall_insn"
1281   [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
1282          (match_operand 1 ""))
1283    (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1284    (return)]
1285   "SIBLING_CALL_P (insn)"
1286   {
1287     if (which_alternative == 0)
1288       {
1289         output_asm_insn ("br\\t%0", operands);
1290         return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1291       }
1292     return "b\\t%c0";
1293   }
1294   [(set_attr "type" "branch, branch")
1295    (set_attr "sls_length" "retbr,none")]
1298 (define_insn "*sibcall_value_insn"
1299   [(set (match_operand 0 "")
1300         (call (mem:DI
1301                 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
1302               (match_operand 2 "")))
1303    (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1304    (return)]
1305   "SIBLING_CALL_P (insn)"
1306   {
1307     if (which_alternative == 0)
1308       {
1309         output_asm_insn ("br\\t%1", operands);
1310         return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1311       }
1312     return "b\\t%c1";
1313   }
1314   [(set_attr "type" "branch, branch")
1315    (set_attr "sls_length" "retbr,none")]
1318 ;; Call subroutine returning any type.
1320 (define_expand "untyped_call"
1321   [(parallel [(call (match_operand 0 "")
1322                     (const_int 0))
1323               (match_operand 1 "")
1324               (match_operand 2 "")])]
1325   ""
1327   int i;
1329   /* Generate a PARALLEL that contains all of the register results.
1330      The offsets are somewhat arbitrary, since we don't know the
1331      actual return type.  The main thing we need to avoid is having
1332      overlapping byte ranges, since those might give the impression
1333      that two registers are known to have data in common.  */
1334   rtvec rets = rtvec_alloc (XVECLEN (operands[2], 0));
1335   poly_int64 offset = 0;
1336   for (i = 0; i < XVECLEN (operands[2], 0); i++)
1337     {
1338       rtx reg = SET_SRC (XVECEXP (operands[2], 0, i));
1339       gcc_assert (REG_P (reg));
1340       rtx offset_rtx = gen_int_mode (offset, Pmode);
1341       rtx piece = gen_rtx_EXPR_LIST (VOIDmode, reg, offset_rtx);
1342       RTVEC_ELT (rets, i) = piece;
1343       offset += GET_MODE_SIZE (GET_MODE (reg));
1344     }
1345   rtx ret = gen_rtx_PARALLEL (VOIDmode, rets);
1347   /* Untyped calls always use the default ABI.  It's only possible to use
1348      ABI variants if we know the type of the target function.  */
1349   emit_call_insn (gen_call_value (ret, operands[0], const0_rtx, const0_rtx));
1351   for (i = 0; i < XVECLEN (operands[2], 0); i++)
1352     {
1353       rtx set = XVECEXP (operands[2], 0, i);
1354       emit_move_insn (SET_DEST (set), SET_SRC (set));
1355     }
1357   /* The optimizer does not know that the call sets the function value
1358      registers we stored in the result block.  We avoid problems by
1359      claiming that all hard registers are used and clobbered at this
1360      point.  */
1361   emit_insn (gen_blockage ());
1362   DONE;
1365 ;; -------------------------------------------------------------------
1366 ;; Moves
1367 ;; -------------------------------------------------------------------
1369 (define_expand "mov<mode>"
1370   [(set (match_operand:SHORT 0 "nonimmediate_operand")
1371         (match_operand:SHORT 1 "general_operand"))]
1372   ""
1373   "
1374     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1375       operands[1] = force_reg (<MODE>mode, operands[1]);
1377     if (GET_CODE (operands[1]) == CONST_POLY_INT)
1378       {
1379         aarch64_expand_mov_immediate (operands[0], operands[1]);
1380         DONE;
1381       }
1382   "
1385 (define_insn "*mov<mode>_aarch64"
1386   [(set (match_operand:SHORT 0 "nonimmediate_operand")
1387         (match_operand:SHORT 1 "aarch64_mov_operand"))]
1388   "(register_operand (operands[0], <MODE>mode)
1389     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
1390   {@ [cons: =0, 1; attrs: type, arch]
1391      [w, Z    ; neon_move      , simd       ] movi\t%0.<Vbtype>, #0
1392      [r, r    ; mov_reg        , *          ] mov\t%w0, %w1
1393      [r, M    ; mov_imm        , *          ] mov\t%w0, %1
1394      [w, D<hq>; neon_move      , simd       ] << aarch64_output_scalar_simd_mov_immediate (operands[1], <MODE>mode);
1395      /* The "mov_imm" type for CNT is just a placeholder.  */
1396      [r, Usv  ; mov_imm        , sve        ] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
1397      [r, Usr  ; mov_imm        , sve        ] << aarch64_output_sve_rdvl (operands[1]);
1398      [r, m    ; load_4         , *          ] ldr<size>\t%w0, %1
1399      [w, m    ; load_4         , *          ] ldr\t%<size>0, %1
1400      [m, r Z  ; store_4        , *          ] str<size>\\t%w1, %0
1401      [m, w    ; store_4        , *          ] str\t%<size>1, %0
1402      [r, w    ; neon_to_gp<q>  , base_simd  ] umov\t%w0, %1.<v>[0]
1403      [r, w    ; neon_to_gp<q>  , nobase_simd] fmov\t%w0, %s1
1404      [w, r Z  ; neon_from_gp<q>, simd       ] dup\t%0.<Vallxd>, %w1
1405      [w, r Z  ; neon_from_gp<q>, nosimd     ] fmov\t%s0, %w1
1406      [w, w    ; neon_dup       , simd       ] dup\t%<Vetype>0, %1.<v>[0]
1407      [w, w    ; neon_dup       , nosimd     ] fmov\t%s0, %s1
1408   }
1411 (define_expand "mov<mode>"
1412   [(set (match_operand:GPI 0 "nonimmediate_operand")
1413         (match_operand:GPI 1 "general_operand"))]
1414   ""
1415   "
1416     if (MEM_P (operands[0]) && !MEM_VOLATILE_P (operands[0])
1417         && CONST_INT_P (operands[1]) && <MODE>mode == DImode
1418         && aarch64_split_dimode_const_store (operands[0], operands[1]))
1419       DONE;
1421     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1422       operands[1] = force_reg (<MODE>mode, operands[1]);
1424     /* Lower moves of symbolic constants into individual instructions.
1425        Doing this now is sometimes necessary for correctness, since some
1426        sequences require temporary pseudo registers.  Lowering now is also
1427        often better for optimization, since more RTL passes get the
1428        chance to optimize the individual instructions.
1430        When called after RA, also split multi-instruction moves into
1431        smaller pieces now, since we can't be sure that sure that there
1432        will be a following split pass.  */
1433     if (CONST_INT_P (operands[1])
1434         ? (reload_completed
1435            && !aarch64_mov_imm_operand (operands[1], <MODE>mode))
1436         : CONSTANT_P (operands[1]))
1437      {
1438        aarch64_expand_mov_immediate (operands[0], operands[1]);
1439        DONE;
1440      }
1441   "
1444 (define_insn_and_split "*movsi_aarch64"
1445   [(set (match_operand:SI 0 "nonimmediate_operand")
1446         (match_operand:SI 1 "aarch64_mov_operand"))]
1447   "(register_operand (operands[0], SImode)
1448     || aarch64_reg_or_zero (operands[1], SImode))"
1449   {@ [cons: =0, 1; attrs: type, arch, length]
1450      [w  , Z  ; neon_move, simd, 4] movi\t%0.2d, #0
1451      [r k, r  ; mov_reg  , *   , 4] mov\t%w0, %w1
1452      [r  , k  ; mov_reg  , *   , 4] ^
1453      [r  , M  ; mov_imm  , *   , 4] mov\t%w0, %1
1454      [r  , n  ; mov_imm  , *   ,16] #
1455      /* The "mov_imm" type for CNT is just a placeholder.  */
1456      [r  , Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
1457      [r  , Usr; mov_imm  , sve,  4] << aarch64_output_sve_rdvl (operands[1]);
1458      [r  , UsR; mov_imm  , sme,  4] << aarch64_output_rdsvl (operands[1]);
1459      [r  , m  ; load_4   , *   , 4] ldr\t%w0, %1
1460      [w  , m  ; load_4   , fp  , 4] ldr\t%s0, %1
1461      [m  , r Z; store_4  , *   , 4] str\t%w1, %0
1462      [m  , w  ; store_4  , fp  , 4] str\t%s1, %0
1463      [r  , Usw; load_4   , *   , 8] adrp\t%x0, %A1\;ldr\t%w0, [%x0, %L1]
1464      [r  , Usa; adr      , *   , 4] adr\t%x0, %c1
1465      [r  , Ush; adr      , *   , 4] adrp\t%x0, %A1
1466      [w  , r Z; f_mcr    , fp  , 4] fmov\t%s0, %w1
1467      [r  , w  ; f_mrc    , fp  , 4] fmov\t%w0, %s1
1468      [w  , w  ; fmov     , fp  , 4] fmov\t%s0, %s1
1469      [w  , Ds ; neon_move, simd, 4] << aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1470   }
1471   "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1472     && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1473   [(const_int 0)]
1474   {
1475     aarch64_expand_mov_immediate (operands[0], operands[1]);
1476     DONE;
1477   }
1480 (define_insn_and_split "*movdi_aarch64"
1481   [(set (match_operand:DI 0 "nonimmediate_operand")
1482         (match_operand:DI 1 "aarch64_mov_operand"))]
1483   "(register_operand (operands[0], DImode)
1484     || aarch64_reg_or_zero (operands[1], DImode))"
1485   {@ [cons: =0, 1; attrs: type, arch, length]
1486      [w, Z  ; neon_move, simd, 4] movi\t%0.2d, #0
1487      [r, r  ; mov_reg  , *   , 4] mov\t%x0, %x1
1488      [k, r  ; mov_reg  , *   , 4] mov\t%0, %x1
1489      [r, k  ; mov_reg  , *   , 4] mov\t%x0, %1
1490      [r, O  ; mov_imm  , *   , 4] << aarch64_is_mov_xn_imm (INTVAL (operands[1])) ? "mov\t%x0, %1" : "mov\t%w0, %1";
1491      [r, n  ; mov_imm  , *   ,16] #
1492      /* The "mov_imm" type for CNT is just a placeholder.  */
1493      [r, Usv; mov_imm  , sve , 4] << aarch64_output_sve_cnt_immediate ("cnt", "%x0", operands[1]);
1494      [r, Usr; mov_imm  , sve,  4] << aarch64_output_sve_rdvl (operands[1]);
1495      [r, UsR; mov_imm  , sme,  4] << aarch64_output_rdsvl (operands[1]);
1496      [r, m  ; load_8   , *   , 4] ldr\t%x0, %1
1497      [w, m  ; load_8   , fp  , 4] ldr\t%d0, %1
1498      [m, r Z; store_8  , *   , 4] str\t%x1, %0
1499      [m, w  ; store_8  , fp  , 4] str\t%d1, %0
1500      [r, Usw; load_8   , *   , 8] << TARGET_ILP32 ? "adrp\t%0, %A1\;ldr\t%w0, [%0, %L1]" : "adrp\t%0, %A1\;ldr\t%0, [%0, %L1]";
1501      [r, Usa; adr      , *   , 4] adr\t%x0, %c1
1502      [r, Ush; adr      , *   , 4] adrp\t%x0, %A1
1503      [w, r Z; f_mcr    , fp  , 4] fmov\t%d0, %x1
1504      [r, w  ; f_mrc    , fp  , 4] fmov\t%x0, %d1
1505      [w, w  ; fmov     , fp  , 4] fmov\t%d0, %d1
1506      [w, Dd ; neon_move, simd, 4] << aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1507      [w, Dx ; neon_move, simd, 8] #
1508   }
1509   "CONST_INT_P (operands[1])
1510    && REG_P (operands[0])
1511    && ((!aarch64_move_imm (INTVAL (operands[1]), DImode)
1512         && GP_REGNUM_P (REGNO (operands[0])))
1513        || (aarch64_simd_special_constant_p (operands[1], DImode)
1514            && FP_REGNUM_P (REGNO (operands[0]))))"
1515   [(const_int 0)]
1516   {
1517     if (GP_REGNUM_P (REGNO (operands[0])))
1518       aarch64_expand_mov_immediate (operands[0], operands[1]);
1519     else
1520       aarch64_maybe_generate_simd_constant (operands[0], operands[1], DImode);
1521     DONE;
1522   }
1525 (define_insn "insv_imm<mode>"
1526   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1527                           (const_int 16)
1528                           (match_operand:GPI 1 "const_int_operand" "n"))
1529         (match_operand:GPI 2 "const_int_operand" "n"))]
1530   "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1531    && UINTVAL (operands[1]) % 16 == 0"
1532   "movk\\t%<w>0, %X2, lsl %1"
1533   [(set_attr "type" "mov_imm")]
1536 ;; Match MOVK as a normal AND and IOR operation.
1537 (define_insn "aarch64_movk<mode>"
1538   [(set (match_operand:GPI 0 "register_operand" "=r")
1539         (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
1540                           (match_operand:GPI 2 "const_int_operand"))
1541                  (match_operand:GPI 3 "const_int_operand")))]
1542   "aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
1543                        rtx_mode_t (operands[3], <MODE>mode)) >= 0"
1544   {
1545     int shift = aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
1546                                     rtx_mode_t (operands[3], <MODE>mode));
1547     operands[2] = gen_int_mode (UINTVAL (operands[3]) >> shift, SImode);
1548     operands[3] = gen_int_mode (shift, SImode);
1549     return "movk\\t%<w>0, #%X2, lsl %3";
1550   }
1551   [(set_attr "type" "mov_imm")]
1554 (define_expand "movti"
1555   [(set (match_operand:TI 0 "nonimmediate_operand")
1556         (match_operand:TI 1 "general_operand"))]
1557   ""
1558   "
1559     if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1560       operands[1] = force_reg (TImode, operands[1]);
1562     if (GET_CODE (operands[1]) == CONST_POLY_INT)
1563       {
1564         emit_move_insn (gen_lowpart (DImode, operands[0]),
1565                         gen_lowpart (DImode, operands[1]));
1566         emit_move_insn (gen_highpart (DImode, operands[0]), const0_rtx);
1567         DONE;
1568       }
1569   "
1572 (define_insn "*movti_aarch64"
1573   [(set (match_operand:TI 0
1574          "nonimmediate_operand"  "=   r,w,w,w, r,w,w,r,m,m,w,m")
1575         (match_operand:TI 1
1576          "aarch64_movti_operand" " rUti,Z,Z,r, w,w,w,m,r,Z,m,w"))]
1577   "(register_operand (operands[0], TImode)
1578     || aarch64_reg_or_zero (operands[1], TImode))"
1579   "@
1580    #
1581    movi\\t%0.2d, #0
1582    fmov\t%d0, xzr
1583    #
1584    #
1585    mov\\t%0.16b, %1.16b
1586    mov\\t%Z0.d, %Z1.d
1587    ldp\\t%0, %H0, %1
1588    stp\\t%1, %H1, %0
1589    stp\\txzr, xzr, %0
1590    ldr\\t%q0, %1
1591    str\\t%q1, %0"
1592   [(set_attr "type" "multiple,neon_move,f_mcr,f_mcr,f_mrc,neon_logic_q,*,\
1593                              load_16,store_16,store_16,\
1594                              load_16,store_16")
1595    (set_attr "length" "8,4,4,8,8,4,4,4,4,4,4,4")
1596    (set_attr "arch" "*,simd,*,*,*,simd,sve,*,*,*,fp,fp")]
1599 ;; Split a TImode register-register or register-immediate move into
1600 ;; its component DImode pieces, taking care to handle overlapping
1601 ;; source and dest registers.
1602 (define_split
1603    [(set (match_operand:TI 0 "register_operand" "")
1604          (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1605   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1606   [(const_int 0)]
1608   aarch64_split_128bit_move (operands[0], operands[1]);
1609   DONE;
1612 (define_expand "mov<mode>"
1613   [(set (match_operand:GPF_TF_F16_MOV 0 "nonimmediate_operand")
1614         (match_operand:GPF_TF_F16_MOV 1 "general_operand"))]
1615   ""
1616   {
1617     if (!TARGET_FLOAT)
1618       {
1619         aarch64_err_no_fpadvsimd (<MODE>mode);
1620         machine_mode intmode
1621           = int_mode_for_size (GET_MODE_BITSIZE (<MODE>mode), 0).require ();
1622         emit_move_insn (gen_lowpart (intmode, operands[0]),
1623                         gen_lowpart (intmode, operands[1]));
1624         DONE;
1625       }
1627     if (GET_CODE (operands[0]) == MEM
1628         && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1629               && aarch64_float_const_zero_rtx_p (operands[1])))
1630       operands[1] = force_reg (<MODE>mode, operands[1]);
1631   }
1634 (define_insn "*mov<mode>_aarch64"
1635   [(set (match_operand:HFBF 0 "nonimmediate_operand")
1636         (match_operand:HFBF 1 "general_operand"))]
1637   "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
1638     || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
1639   {@ [ cons: =0 , 1   ; attrs: type , arch  ]
1640      [ w        , Y   ; neon_move   , simd  ] movi\t%0.4h, #0
1641      [ w        , ?rY ; f_mcr       , fp16  ] fmov\t%h0, %w1
1642      [ w        , ?r  ; neon_move   , simd  ] dup\t%w0.4h, %w1
1643      [ w        , ?rY ; f_mcr       , *     ] fmov\t%s0, %w1
1644      [ ?r       , w   ; neon_to_gp  , simd  ] umov\t%w0, %1.h[0]
1645      [ ?r       , w   ; f_mrc       , *     ] fmov\t%w0, %s1
1646      [ w        , w   ; neon_move   , simd  ] mov\t%0.h[0], %1.h[0]
1647      [ w        , w   ; fmov        , *     ] fmov\t%s0, %s1
1648      [ w        , Ufc ; fconsts     , fp16  ] fmov\t%h0, %1
1649      [ w        , Uvi ; neon_move   , simd  ] << aarch64_output_scalar_simd_mov_immediate (operands[1], HImode);
1650      [ w        , m   ; f_loads     , *     ] ldr\t%h0, %1
1651      [ m        , w   ; f_stores    , *     ] str\t%h1, %0
1652      [ r        , m   ; load_4      , *     ] ldrh\t%w0, %1
1653      [ m        , rY  ; store_4     , *     ] strh\t%w1, %0
1654      [ r        , r   ; mov_reg     , *     ] mov\t%w0, %w1
1655   }
1658 (define_insn "*mov<mode>_aarch64"
1659   [(set (match_operand:SFD 0 "nonimmediate_operand")
1660         (match_operand:SFD 1 "general_operand"))]
1661   "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
1662     || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
1663   {@ [ cons: =0 , 1   ; attrs: type , arch  ]
1664      [ w        , Y   ; neon_move   , simd  ] movi\t%0.2s, #0
1665      [ w        , ?rY ; f_mcr       , *     ] fmov\t%s0, %w1
1666      [ ?r       , w   ; f_mrc       , *     ] fmov\t%w0, %s1
1667      [ w        , w   ; fmov        , *     ] fmov\t%s0, %s1
1668      [ w        , Ufc ; fconsts     , *     ] fmov\t%s0, %1
1669      [ w        , Uvi ; neon_move   , simd  ] << aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1670      [ w        , m   ; f_loads     , *     ] ldr\t%s0, %1
1671      [ m        , w   ; f_stores    , *     ] str\t%s1, %0
1672      [ r        , m   ; load_4      , *     ] ldr\t%w0, %1
1673      [ m        , rY  ; store_4     , *     ] str\t%w1, %0
1674      [ r        , r   ; mov_reg     , *     ] mov\t%w0, %w1
1675      [ r        , M   ; fconsts     , *     ] mov\t%w0, %1
1676   }
1679 (define_insn "*mov<mode>_aarch64"
1680   [(set (match_operand:DFD 0 "nonimmediate_operand")
1681         (match_operand:DFD 1 "general_operand"))]
1682   "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
1683     || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
1684   {@ [ cons: =0 , 1   ; attrs: type , arch  ]
1685      [ w        , Y   ; neon_move   , simd  ] movi\t%d0, #0
1686      [ w        , ?rY ; f_mcr       , *     ] fmov\t%d0, %x1
1687      [ ?r       , w   ; f_mrc       , *     ] fmov\t%x0, %d1
1688      [ w        , w   ; fmov        , *     ] fmov\t%d0, %d1
1689      [ w        , Ufc ; fconstd     , *     ] fmov\t%d0, %1
1690      [ w        , Uvi ; neon_move   , simd  ] << aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1691      [ w        , m   ; f_loadd     , *     ] ldr\t%d0, %1
1692      [ m        , w   ; f_stored    , *     ] str\t%d1, %0
1693      [ r        , m   ; load_8      , *     ] ldr\t%x0, %1
1694      [ m        , rY  ; store_8     , *     ] str\t%x1, %0
1695      [ r        , r   ; mov_reg     , *     ] mov\t%x0, %x1
1696      [ r        , O   ; fconstd     , *     ] << aarch64_is_mov_xn_imm (INTVAL (operands[1])) ? "mov\t%x0, %1" : "mov\t%w0, %1";
1697   }
1700 (define_split
1701   [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
1702         (match_operand:GPF_HF 1 "const_double_operand"))]
1703   "can_create_pseudo_p ()
1704    && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
1705    && !aarch64_float_const_representable_p (operands[1])
1706    && !aarch64_float_const_zero_rtx_p (operands[1])
1707    &&  aarch64_float_const_rtx_p (operands[1])"
1708   [(const_int 0)]
1709   {
1710     unsigned HOST_WIDE_INT ival;
1711     if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
1712       FAIL;
1714     rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1715     emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1716     emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
1717     DONE;
1718   }
1721 (define_insn "*mov<mode>_aarch64"
1722   [(set (match_operand:TFD 0
1723          "nonimmediate_operand" "=w,w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
1724         (match_operand:TFD 1
1725          "general_operand"      " w,w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1726   "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
1727     || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
1728   "@
1729    mov\\t%0.16b, %1.16b
1730    mov\\t%Z0.d, %Z1.d
1731    #
1732    #
1733    #
1734    movi\\t%0.2d, #0
1735    fmov\\t%s0, wzr
1736    ldr\\t%q0, %1
1737    str\\t%q1, %0
1738    ldp\\t%0, %H0, %1
1739    stp\\t%1, %H1, %0
1740    stp\\txzr, xzr, %0"
1741   [(set_attr "type" "logic_reg,*,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1742                      f_loadd,f_stored,load_16,store_16,store_16")
1743    (set_attr "length" "4,4,8,8,8,4,4,4,4,4,4,4")
1744    (set_attr "arch" "simd,sve,*,*,*,simd,*,*,*,*,*,*")]
1747 (define_split
1748    [(set (match_operand:TFD 0 "register_operand" "")
1749          (match_operand:TFD 1 "nonmemory_operand" ""))]
1750   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1751   [(const_int 0)]
1752   {
1753     aarch64_split_128bit_move (operands[0], operands[1]);
1754     DONE;
1755   }
1758 (define_expand "aarch64_cpymemdi"
1759   [(parallel
1760      [(set (match_operand 2) (const_int 0))
1761       (clobber (match_dup 3))
1762       (clobber (match_dup 4))
1763       (clobber (reg:CC CC_REGNUM))
1764       (set (match_operand 0)
1765            (unspec:BLK [(match_operand 1) (match_dup 2)] UNSPEC_CPYMEM))])]
1766   "TARGET_MOPS"
1767   {
1768     operands[3] = XEXP (operands[0], 0);
1769     operands[4] = XEXP (operands[1], 0);
1770   }
1773 (define_insn "*aarch64_cpymemdi"
1774   [(set (match_operand:DI 2 "register_operand" "+&r") (const_int 0))
1775    (clobber (match_operand:DI 0 "register_operand" "+&r"))
1776    (clobber (match_operand:DI 1 "register_operand" "+&r"))
1777    (clobber (reg:CC CC_REGNUM))
1778    (set (mem:BLK (match_dup 0))
1779         (unspec:BLK [(mem:BLK (match_dup 1)) (match_dup 2)] UNSPEC_CPYMEM))]
1780   "TARGET_MOPS"
1781   "cpyfp\t[%x0]!, [%x1]!, %x2!\;cpyfm\t[%x0]!, [%x1]!, %x2!\;cpyfe\t[%x0]!, [%x1]!, %x2!"
1782   [(set_attr "length" "12")]
1785 ;; 0 is dst
1786 ;; 1 is src
1787 ;; 2 is size of copy in bytes
1788 ;; 3 is alignment
1790 (define_expand "cpymemdi"
1791   [(match_operand:BLK 0 "memory_operand")
1792    (match_operand:BLK 1 "memory_operand")
1793    (match_operand:DI 2 "general_operand")
1794    (match_operand:DI 3 "immediate_operand")]
1795    ""
1797   if (aarch64_expand_cpymem (operands, false))
1798     DONE;
1799   FAIL;
1803 (define_expand "aarch64_movmemdi"
1804   [(parallel
1805      [(set (match_operand 2) (const_int 0))
1806       (clobber (match_dup 3))
1807       (clobber (match_dup 4))
1808       (clobber (reg:CC CC_REGNUM))
1809       (set (match_operand 0)
1810            (unspec:BLK [(match_operand 1) (match_dup 2)] UNSPEC_MOVMEM))])]
1811   "TARGET_MOPS"
1812   {
1813     operands[3] = XEXP (operands[0], 0);
1814     operands[4] = XEXP (operands[1], 0);
1815   }
1818 (define_insn "*aarch64_movmemdi"
1819   [(parallel [
1820    (set (match_operand:DI 2 "register_operand" "+&r") (const_int 0))
1821    (clobber (match_operand:DI 0 "register_operand" "+&r"))
1822    (clobber (match_operand:DI 1 "register_operand" "+&r"))
1823    (clobber (reg:CC CC_REGNUM))
1824    (set (mem:BLK (match_dup 0))
1825         (unspec:BLK [(mem:BLK (match_dup 1)) (match_dup 2)] UNSPEC_MOVMEM))])]
1826  "TARGET_MOPS"
1827  "cpyp\t[%x0]!, [%x1]!, %x2!\;cpym\t[%x0]!, [%x1]!, %x2!\;cpye\t[%x0]!, [%x1]!, %x2!"
1828  [(set_attr "length" "12")]
1831 ;; 0 is dst
1832 ;; 1 is src
1833 ;; 2 is size of copy in bytes
1834 ;; 3 is alignment
1836 (define_expand "movmemdi"
1837   [(match_operand:BLK 0 "memory_operand")
1838    (match_operand:BLK 1 "memory_operand")
1839    (match_operand:DI 2 "general_operand")
1840    (match_operand:DI 3 "immediate_operand")]
1841    ""
1843   if (aarch64_expand_cpymem (operands, true))
1844     DONE;
1845   FAIL;
1849 (define_expand "aarch64_setmemdi"
1850   [(parallel
1851      [(set (match_operand 2) (const_int 0))
1852       (clobber (match_dup 3))
1853       (clobber (reg:CC CC_REGNUM))
1854       (set (match_operand 0)
1855            (unspec:BLK [(match_operand 1)
1856                         (match_dup 2)] UNSPEC_SETMEM))])]
1857   "TARGET_MOPS"
1858   {
1859     operands[3] = XEXP (operands[0], 0);
1860   }
1863 (define_insn "*aarch64_setmemdi"
1864   [(set (match_operand:DI 2 "register_operand" "+&r") (const_int 0))
1865    (clobber (match_operand:DI 0 "register_operand" "+&r"))
1866    (clobber (reg:CC CC_REGNUM))
1867    (set (mem:BLK (match_dup 0))
1868         (unspec:BLK [(match_operand:QI 1 "aarch64_reg_or_zero" "rZ")
1869                      (match_dup 2)] UNSPEC_SETMEM))]
1870   "TARGET_MOPS"
1871   "setp\t[%x0]!, %x2!, %x1\;setm\t[%x0]!, %x2!, %x1\;sete\t[%x0]!, %x2!, %x1"
1872   [(set_attr "length" "12")]
1875 ;; 0 is dst
1876 ;; 1 is val
1877 ;; 2 is size of copy in bytes
1878 ;; 3 is alignment
1879 (define_expand "setmemdi"
1880   [(set (match_operand:BLK 0 "memory_operand")     ;; Dest
1881         (match_operand:QI  2 "nonmemory_operand")) ;; Value
1882    (use (match_operand:DI  1 "general_operand")) ;; Length
1883    (match_operand          3 "immediate_operand")] ;; Align
1884  ""
1886   if (aarch64_expand_setmem (operands))
1887     DONE;
1889   FAIL;
1892 (define_insn "*load_pair_<ldst_sz>"
1893   [(set (match_operand:GPI 0 "aarch64_ldp_reg_operand")
1894         (unspec [
1895           (match_operand:<VPAIR> 1 "aarch64_mem_pair_lanes_operand")
1896         ] UNSPEC_LDP_FST))
1897    (set (match_operand:GPI 2 "aarch64_ldp_reg_operand")
1898         (unspec [
1899           (match_dup 1)
1900         ] UNSPEC_LDP_SND))]
1901   ""
1902   {@ [cons: =0, 1,   =2; attrs: type,      arch]
1903      [       r, Umn,  r; load_<ldpstp_sz>, *   ] ldp\t%<w>0, %<w>2, %y1
1904      [       w, Umn,  w; neon_load1_2reg,  fp  ] ldp\t%<v>0, %<v>2, %y1
1905   }
1906   [(set_attr "ldpstp" "ldp")]
1909 (define_insn "*load_pair_16"
1910   [(set (match_operand:TI 0 "aarch64_ldp_reg_operand" "=w")
1911         (unspec [
1912           (match_operand:V2x16QI 1 "aarch64_mem_pair_lanes_operand" "Umn")
1913         ] UNSPEC_LDP_FST))
1914    (set (match_operand:TI 2 "aarch64_ldp_reg_operand" "=w")
1915         (unspec [
1916           (match_dup 1)
1917         ] UNSPEC_LDP_SND))]
1918   "TARGET_FLOAT"
1919   "ldp\\t%q0, %q2, %y1"
1920   [(set_attr "type" "neon_ldp_q")
1921    (set_attr "fp" "yes")
1922    (set_attr "ldpstp" "ldp")]
1925 (define_insn "*store_pair_<ldst_sz>"
1926   [(set (match_operand:<VPAIR> 0 "aarch64_mem_pair_lanes_operand")
1927         (unspec:<VPAIR>
1928           [(match_operand:GPI 1 "aarch64_stp_reg_operand")
1929            (match_operand:GPI 2 "aarch64_stp_reg_operand")] UNSPEC_STP))]
1930   ""
1931   {@ [cons:  =0,   1,   2; attrs: type      , arch]
1932      [      Umn, rYZ, rYZ; store_<ldpstp_sz>, *   ] stp\t%<w>1, %<w>2, %y0
1933      [      Umn,   w,   w; neon_store1_2reg , fp  ] stp\t%<v>1, %<v>2, %y0
1934   }
1935   [(set_attr "ldpstp" "stp")]
1938 (define_insn "*store_pair_16"
1939   [(set (match_operand:V2x16QI 0 "aarch64_mem_pair_lanes_operand" "=Umn")
1940         (unspec:V2x16QI
1941           [(match_operand:TI 1 "aarch64_ldp_reg_operand" "w")
1942            (match_operand:TI 2 "aarch64_ldp_reg_operand" "w")] UNSPEC_STP))]
1943   "TARGET_FLOAT"
1944   "stp\t%q1, %q2, %y0"
1945   [(set_attr "type" "neon_stp_q")
1946    (set_attr "fp" "yes")
1947    (set_attr "ldpstp" "stp")]
1950 ;; Writeback load/store pair patterns.
1952 ;; Note that modes in the patterns [SI DI TI] are used only as a proxy for their
1953 ;; size; aarch64_ldp_reg_operand and aarch64_mem_pair_operator are special
1954 ;; predicates which accept a wide range of operand modes, with the requirement
1955 ;; that the contextual (pattern) mode is of the same size as the operand mode.
1957 ;; Load pair with post-index writeback.  This is primarily used in function
1958 ;; epilogues.
1959 (define_insn "*loadwb_post_pair_<ldst_sz>"
1960   [(set (match_operand 0 "pmode_register_operand")
1961         (match_operator 7 "pmode_plus_operator" [
1962           (match_operand 1 "pmode_register_operand")
1963           (match_operand 4 "const_int_operand")]))
1964    (set (match_operand:GPI 2 "aarch64_ldp_reg_operand")
1965         (match_operator 5 "memory_operand" [(match_dup 1)]))
1966    (set (match_operand:GPI 3 "aarch64_ldp_reg_operand")
1967         (match_operator 6 "memory_operand" [
1968           (match_operator 8 "pmode_plus_operator" [
1969             (match_dup 1)
1970             (const_int <ldst_sz>)])]))]
1971   "aarch64_mem_pair_offset (operands[4], <MODE>mode)"
1972   {@ [cons: =0, 1, =2, =3; attrs: type]
1973      [      rk, 0,  r,  r; load_<ldpstp_sz>] ldp\t%<w>2, %<w>3, [%1], %4
1974      [      rk, 0,  w,  w; neon_load1_2reg ] ldp\t%<v>2, %<v>3, [%1], %4
1975   }
1978 ;; q-register variant of the above
1979 (define_insn "*loadwb_post_pair_16"
1980   [(set (match_operand 0 "pmode_register_operand" "=rk")
1981         (match_operator 7 "pmode_plus_operator" [
1982           (match_operand 1 "pmode_register_operand" "0")
1983           (match_operand 4 "const_int_operand")]))
1984    (set (match_operand:TI 2 "aarch64_ldp_reg_operand" "=w")
1985         (match_operator 5 "memory_operand" [(match_dup 1)]))
1986    (set (match_operand:TI 3 "aarch64_ldp_reg_operand" "=w")
1987         (match_operator 6 "memory_operand"
1988           [(match_operator 8 "pmode_plus_operator" [
1989              (match_dup 1)
1990              (const_int 16)])]))]
1991   "TARGET_FLOAT
1992    && aarch64_mem_pair_offset (operands[4], TImode)"
1993   "ldp\t%q2, %q3, [%1], %4"
1994   [(set_attr "type" "neon_ldp_q")]
1997 ;; Load pair with pre-index writeback.
1998 (define_insn "*loadwb_pre_pair_<ldst_sz>"
1999   [(set (match_operand 0 "pmode_register_operand")
2000         (match_operator 8 "pmode_plus_operator" [
2001           (match_operand 1 "pmode_register_operand")
2002           (match_operand 4 "const_int_operand")]))
2003    (set (match_operand:GPI 2 "aarch64_ldp_reg_operand")
2004         (match_operator 6 "memory_operand" [
2005           (match_operator 9 "pmode_plus_operator" [
2006             (match_dup 1)
2007             (match_dup 4)
2008           ])]))
2009    (set (match_operand:GPI 3 "aarch64_ldp_reg_operand")
2010         (match_operator 7 "memory_operand" [
2011           (match_operator 10 "pmode_plus_operator" [
2012              (match_dup 1)
2013              (match_operand 5 "const_int_operand")
2014           ])]))]
2015   "aarch64_mem_pair_offset (operands[4], <MODE>mode)
2016    && known_eq (INTVAL (operands[5]),
2017                 INTVAL (operands[4]) + GET_MODE_SIZE (<MODE>mode))"
2018   {@ [cons: =&0, 1, =2, =3; attrs: type     ]
2019      [       rk, 0,  r,  r; load_<ldpstp_sz>] ldp\t%<w>2, %<w>3, [%0, %4]!
2020      [       rk, 0,  w,  w; neon_load1_2reg ] ldp\t%<v>2, %<v>3, [%0, %4]!
2021   }
2024 ;; q-register variant of the above
2025 (define_insn "*loadwb_pre_pair_16"
2026   [(set (match_operand 0 "pmode_register_operand" "=&rk")
2027         (match_operator 8 "pmode_plus_operator" [
2028           (match_operand 1 "pmode_register_operand" "0")
2029           (match_operand 4 "const_int_operand")]))
2030    (set (match_operand:TI 2 "aarch64_ldp_reg_operand" "=w")
2031         (match_operator 6 "memory_operand" [
2032           (match_operator 9 "pmode_plus_operator" [
2033             (match_dup 1)
2034             (match_dup 4)
2035           ])]))
2036    (set (match_operand:TI 3 "aarch64_ldp_reg_operand" "=w")
2037         (match_operator 7 "memory_operand" [
2038           (match_operator 10 "pmode_plus_operator" [
2039              (match_dup 1)
2040              (match_operand 5 "const_int_operand")
2041           ])]))]
2042   "TARGET_FLOAT
2043    && aarch64_mem_pair_offset (operands[4], TImode)
2044    && known_eq (INTVAL (operands[5]), INTVAL (operands[4]) + 16)"
2045   "ldp\t%q2, %q3, [%0, %4]!"
2046   [(set_attr "type" "neon_ldp_q")]
2049 ;; Store pair with pre-index writeback.  This is primarily used in function
2050 ;; prologues.
2051 (define_insn "*storewb_pre_pair_<ldst_sz>"
2052   [(set (match_operand 0 "pmode_register_operand")
2053         (match_operator 6 "pmode_plus_operator" [
2054           (match_operand 1 "pmode_register_operand")
2055           (match_operand 4 "const_int_operand")
2056         ]))
2057    (set (match_operator:GPI 7 "aarch64_mem_pair_operator" [
2058           (match_operator 8 "pmode_plus_operator" [
2059             (match_dup 0)
2060             (match_dup 4)
2061           ])])
2062         (match_operand:GPI 2 "aarch64_stp_reg_operand"))
2063    (set (match_operator:GPI 9 "aarch64_mem_pair_operator" [
2064           (match_operator 10 "pmode_plus_operator" [
2065             (match_dup 0)
2066             (match_operand 5 "const_int_operand")
2067           ])])
2068         (match_operand:GPI 3 "aarch64_stp_reg_operand"))]
2069   "aarch64_mem_pair_offset (operands[4], <MODE>mode)
2070    && known_eq (INTVAL (operands[5]),
2071                 INTVAL (operands[4]) + GET_MODE_SIZE (<MODE>mode))
2072    && !reg_overlap_mentioned_p (operands[0], operands[2])
2073    && !reg_overlap_mentioned_p (operands[0], operands[3])"
2074   {@ [cons: =&0, 1,   2,   3; attrs: type      ]
2075      [       rk, 0, rYZ, rYZ; store_<ldpstp_sz>] stp\t%<w>2, %<w>3, [%0, %4]!
2076      [       rk, 0,   w,   w; neon_store1_2reg ] stp\t%<v>2, %<v>3, [%0, %4]!
2077   }
2080 ;; q-register variant of the above.
2081 (define_insn "*storewb_pre_pair_16"
2082   [(set (match_operand 0 "pmode_register_operand" "=&rk")
2083         (match_operator 6 "pmode_plus_operator" [
2084           (match_operand 1 "pmode_register_operand" "0")
2085           (match_operand 4 "const_int_operand")
2086         ]))
2087    (set (match_operator:TI 7 "aarch64_mem_pair_operator" [
2088           (match_operator 8 "pmode_plus_operator" [
2089             (match_dup 0)
2090             (match_dup 4)
2091           ])])
2092         (match_operand:TI 2 "aarch64_ldp_reg_operand" "w"))
2093    (set (match_operator:TI 9 "aarch64_mem_pair_operator" [
2094           (match_operator 10 "pmode_plus_operator" [
2095             (match_dup 0)
2096             (match_operand 5 "const_int_operand")
2097           ])])
2098         (match_operand:TI 3 "aarch64_ldp_reg_operand" "w"))]
2099   "TARGET_FLOAT
2100    && aarch64_mem_pair_offset (operands[4], TImode)
2101    && known_eq (INTVAL (operands[5]), INTVAL (operands[4]) + 16)
2102    && !reg_overlap_mentioned_p (operands[0], operands[2])
2103    && !reg_overlap_mentioned_p (operands[0], operands[3])"
2104   "stp\\t%q2, %q3, [%0, %4]!"
2105   [(set_attr "type" "neon_stp_q")]
2108 ;; Store pair with post-index writeback.
2109 (define_insn "*storewb_post_pair_<ldst_sz>"
2110   [(set (match_operand 0 "pmode_register_operand")
2111         (match_operator 5 "pmode_plus_operator" [
2112           (match_operand 1 "pmode_register_operand")
2113           (match_operand 4 "const_int_operand")
2114         ]))
2115    (set (match_operator:GPI 6 "aarch64_mem_pair_operator" [(match_dup 1)])
2116         (match_operand 2 "aarch64_stp_reg_operand"))
2117    (set (match_operator:GPI 7 "aarch64_mem_pair_operator" [
2118           (match_operator 8 "pmode_plus_operator" [
2119             (match_dup 0)
2120             (const_int <ldst_sz>)
2121           ])])
2122         (match_operand 3 "aarch64_stp_reg_operand"))]
2123   "aarch64_mem_pair_offset (operands[4], <MODE>mode)
2124    && !reg_overlap_mentioned_p (operands[0], operands[2])
2125    && !reg_overlap_mentioned_p (operands[0], operands[3])"
2126   {@ [cons: =0, 1,   2,   3; attrs: type      ]
2127      [      rk, 0, rYZ, rYZ; store_<ldpstp_sz>] stp\t%<w>2, %<w>3, [%0], %4
2128      [      rk, 0,   w,   w; neon_store1_2reg ] stp\t%<v>2, %<v>3, [%0], %4
2129   }
2132 ;; Store pair with post-index writeback.
2133 (define_insn "*storewb_post_pair_16"
2134   [(set (match_operand 0 "pmode_register_operand" "=rk")
2135         (match_operator 5 "pmode_plus_operator" [
2136           (match_operand 1 "pmode_register_operand" "0")
2137           (match_operand 4 "const_int_operand")
2138         ]))
2139    (set (match_operator:TI 6 "aarch64_mem_pair_operator" [(match_dup 1)])
2140         (match_operand:TI 2 "aarch64_ldp_reg_operand" "w"))
2141    (set (match_operator:TI 7 "aarch64_mem_pair_operator" [
2142           (match_operator 8 "pmode_plus_operator" [
2143             (match_dup 0)
2144             (const_int 16)
2145           ])])
2146         (match_operand:TI 3 "aarch64_ldp_reg_operand" "w"))]
2147   "TARGET_FLOAT
2148    && aarch64_mem_pair_offset (operands[4], TImode)
2149    && !reg_overlap_mentioned_p (operands[0], operands[2])
2150    && !reg_overlap_mentioned_p (operands[0], operands[3])"
2151   "stp\t%q2, %q3, [%0], %4"
2152   [(set_attr "type" "neon_stp_q")]
2155 ;; -------------------------------------------------------------------
2156 ;; Sign/Zero extension
2157 ;; -------------------------------------------------------------------
2159 (define_expand "<optab>sidi2"
2160   [(set (match_operand:DI 0 "register_operand")
2161         (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
2162   ""
2165 (define_insn "*extendsidi2_aarch64"
2166   [(set (match_operand:DI 0 "register_operand")
2167         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
2168   ""
2169   {@ [ cons: =0 , 1 ; attrs: type ]
2170      [ r        , r ; extend      ] sxtw\t%0, %w1
2171      [ r        , m ; load_4      ] ldrsw\t%0, %1
2172   }
2175 (define_insn "*load_pair_extendsidi2_aarch64"
2176   [(set (match_operand:DI 0 "register_operand" "=r")
2177         (sign_extend:DI (unspec:SI [
2178           (match_operand:V2x4QI 1 "aarch64_mem_pair_lanes_operand" "Umn")
2179         ] UNSPEC_LDP_FST)))
2180    (set (match_operand:DI 2 "register_operand" "=r")
2181         (sign_extend:DI (unspec:SI [
2182           (match_dup 1)
2183         ] UNSPEC_LDP_SND)))]
2184   ""
2185   "ldpsw\\t%0, %2, %y1"
2186   [(set_attr "type" "load_8")]
2189 (define_insn "*zero_extendsidi2_aarch64"
2190   [(set (match_operand:DI 0 "register_operand")
2191         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
2192   ""
2193   {@ [ cons: =0 , 1 ; attrs: type , arch ]
2194      [ r        , r ; mov_reg     , *    ] uxtw\t%0, %w1
2195      [ r        , m ; load_4      , *    ] ldr\t%w0, %1
2196      [ w        , r ; f_mcr       , fp   ] fmov\t%s0, %w1
2197      [ w        , m ; f_loads     , fp   ] ldr\t%s0, %1
2198      [ r        , w ; f_mrc       , fp   ] fmov\t%w0, %s1
2199      [ w        , w ; fmov        , fp   ] fmov\t%s0, %s1
2200   }
2203 (define_insn "*load_pair_zero_extendsidi2_aarch64"
2204   [(set (match_operand:DI 0 "register_operand")
2205         (zero_extend:DI (unspec:SI [
2206           (match_operand:V2x4QI 1 "aarch64_mem_pair_lanes_operand")
2207         ] UNSPEC_LDP_FST)))
2208    (set (match_operand:DI 2 "register_operand")
2209         (zero_extend:DI (unspec:SI [
2210           (match_dup 1)
2211         ] UNSPEC_LDP_SND)))]
2212   ""
2213   {@ [ cons: =0 , 1   , =2; attrs: type    , arch]
2214      [ r        , Umn , r ; load_8         , *   ] ldp\t%w0, %w2, %y1
2215      [ w        , Umn , w ; neon_load1_2reg, fp  ] ldp\t%s0, %s2, %y1
2216   }
2219 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
2220   [(set (match_operand:GPI 0 "register_operand")
2221         (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
2222   ""
2225 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
2226   [(set (match_operand:GPI 0 "register_operand")
2227         (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
2228   ""
2229   {@ [ cons: =0 , 1 ; attrs: type , arch ]
2230      [ r        , r ; extend      , *    ] sxt<SHORT:size>\t%<GPI:w>0, %w1
2231      [ r        , m ; load_4      , *    ] ldrs<SHORT:size>\t%<GPI:w>0, %1
2232      [ r        , w ; neon_to_gp  , fp   ] smov\t%<GPI:w>0, %1.<SHORT:size>[0]
2233   }
2236 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
2237   [(set (match_operand:GPI 0 "register_operand")
2238         (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
2239   ""
2240   {@ [ cons: =0 , 1 ; attrs: type , arch ]
2241      [ r        , r ; logic_imm   , *    ] and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
2242      [ r        , m ; load_4      , *    ] ldr<SHORT:size>\t%w0, %1
2243      [ w        , m ; f_loads     , fp   ] ldr\t%<SHORT:size>0, %1
2244      [ r        , w ; neon_to_gp  , fp   ] umov\t%w0, %1.<SHORT:size>[0]
2245   }
2248 (define_expand "<optab>qihi2"
2249   [(set (match_operand:HI 0 "register_operand")
2250         (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
2251   ""
2254 (define_insn "*extendqihi2_aarch64"
2255   [(set (match_operand:HI 0 "register_operand")
2256         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand")))]
2257   ""
2258   {@ [ cons: =0 , 1 ; attrs: type ]
2259      [ r        , r ; extend      ] sxtb\t%w0, %w1
2260      [ r        , m ; load_4      ] ldrsb\t%w0, %1
2261   }
2264 (define_insn "*zero_extendqihi2_aarch64"
2265   [(set (match_operand:HI 0 "register_operand")
2266         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand")))]
2267   ""
2268   {@ [ cons: =0 , 1 ; attrs: type ]
2269      [ r        , r ; logic_imm   ] and\t%w0, %w1, 255
2270      [ r        , m ; load_4      ] ldrb\t%w0, %1
2271   }
2274 ;; -------------------------------------------------------------------
2275 ;; Simple arithmetic
2276 ;; -------------------------------------------------------------------
2278 (define_expand "add<mode>3"
2279   [(set
2280     (match_operand:GPI 0 "register_operand")
2281     (plus:GPI (match_operand:GPI 1 "register_operand")
2282               (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand")))]
2283   ""
2285   /* If operands[1] is a subreg extract the inner RTX.  */
2286   rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
2288   /* If the constant is too large for a single instruction and isn't frame
2289      based, split off the immediate so it is available for CSE.  */
2290   if (!aarch64_plus_immediate (operands[2], <MODE>mode)
2291       && !(TARGET_SVE && aarch64_sve_plus_immediate (operands[2], <MODE>mode))
2292       && can_create_pseudo_p ()
2293       && (!REG_P (op1)
2294          || !REGNO_PTR_FRAME_P (REGNO (op1))))
2295     operands[2] = force_reg (<MODE>mode, operands[2]);
2296   /* Some tunings prefer to avoid VL-based operations.
2297      Split off the poly immediate here.  The rtx costs hook will reject attempts
2298      to combine them back.  */
2299   else if (GET_CODE (operands[2]) == CONST_POLY_INT
2300            && can_create_pseudo_p ()
2301            && (aarch64_tune_params.extra_tuning_flags
2302                & AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS))
2303     operands[2] = force_reg (<MODE>mode, operands[2]);
2304   /* Expand polynomial additions now if the destination is the stack
2305      pointer, since we don't want to use that as a temporary.  */
2306   else if (operands[0] == stack_pointer_rtx
2307            && aarch64_split_add_offset_immediate (operands[2], <MODE>mode))
2308     {
2309       aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
2310                                 operands[2], NULL_RTX, NULL_RTX);
2311       DONE;
2312     }
2315 (define_insn "*add<mode>3_aarch64"
2316   [(set
2317     (match_operand:GPI 0 "register_operand")
2318     (plus:GPI
2319      (match_operand:GPI 1 "register_operand")
2320      (match_operand:GPI 2 "aarch64_pluslong_operand")))]
2321   ""
2322   {@ [ cons: =0 , 1   , 2   ; attrs: type , arch  ]
2323      [ rk       , %rk , I   ; alu_imm     , *     ] add\t%<w>0, %<w>1, %2
2324      [ rk       , rk  , r   ; alu_sreg    , *     ] add\t%<w>0, %<w>1, %<w>2
2325      [ w        , w   , w   ; neon_add    , simd  ] add\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
2326      [ rk       , rk  , J   ; alu_imm     , *     ] sub\t%<w>0, %<w>1, #%n2
2327      [ r        , rk  , Uaa ; multiple    , *     ] #
2328      [ r        , 0   , Uai ; alu_imm     , sve   ] << aarch64_output_sve_scalar_inc_dec (operands[2]);
2329      [ rk       , rk  , Uav ; alu_imm     , sve   ] << aarch64_output_sve_addvl_addpl (operands[2]);
2330      [ rk       , rk  , UaV ; alu_imm     , sme   ] << aarch64_output_addsvl_addspl (operands[2]);
2331   }
2332   ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
2335 ;; zero_extend version of above
2336 (define_insn "*addsi3_aarch64_uxtw"
2337   [(set
2338     (match_operand:DI 0 "register_operand")
2339     (zero_extend:DI
2340      (plus:SI (match_operand:SI 1 "register_operand")
2341               (match_operand:SI 2 "aarch64_pluslong_operand"))))]
2342   ""
2343   {@ [ cons: =0 , 1   , 2   ; attrs: type ]
2344      [ rk       , %rk , I   ; alu_imm     ] add\t%w0, %w1, %2
2345      [ rk       , rk  , r   ; alu_sreg    ] add\t%w0, %w1, %w2
2346      [ rk       , rk  , J   ; alu_imm     ] sub\t%w0, %w1, #%n2
2347      [ r        , rk  , Uaa ; multiple    ] #
2348   }
2351 ;; If there's a free register, and we can load the constant with a
2352 ;; single instruction, do so.  This has a chance to improve scheduling.
2353 (define_peephole2
2354   [(match_scratch:GPI 3 "r")
2355    (set (match_operand:GPI 0 "register_operand")
2356         (plus:GPI
2357           (match_operand:GPI 1 "register_operand")
2358           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
2359   "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
2360   [(set (match_dup 3) (match_dup 2))
2361    (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
2364 (define_peephole2
2365   [(match_scratch:SI 3 "r")
2366    (set (match_operand:DI 0 "register_operand")
2367         (zero_extend:DI
2368           (plus:SI
2369             (match_operand:SI 1 "register_operand")
2370             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
2371   "aarch64_move_imm (INTVAL (operands[2]), SImode)"
2372   [(set (match_dup 3) (match_dup 2))
2373    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
2376 ;; After peephole2 has had a chance to run, split any remaining long
2377 ;; additions into two add immediates.
2378 (define_split
2379   [(set (match_operand:GPI 0 "register_operand")
2380         (plus:GPI
2381           (match_operand:GPI 1 "register_operand")
2382           (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
2383   "epilogue_completed"
2384   [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
2385    (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
2386   {
2387     HOST_WIDE_INT i = INTVAL (operands[2]);
2388     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
2389     operands[3] = GEN_INT (i - s);
2390     operands[4] = GEN_INT (s);
2391   }
2394 ;; Match addition of polynomial offsets that require one temporary, for which
2395 ;; we can use the early-clobbered destination register.  This is a separate
2396 ;; pattern so that the early clobber doesn't affect register allocation
2397 ;; for other forms of addition.  However, we still need to provide an
2398 ;; all-register alternative, in case the offset goes out of range after
2399 ;; elimination.  For completeness we might as well provide all GPR-based
2400 ;; alternatives from the main pattern.
2402 ;; We don't have a pattern for additions requiring two temporaries since at
2403 ;; present LRA doesn't allow new scratches to be added during elimination.
2404 ;; Such offsets should be rare anyway.
2406 ;; ??? But if we added LRA support for new scratches, much of the ugliness
2407 ;; here would go away.  We could just handle all polynomial constants in
2408 ;; this pattern.
2409 (define_insn_and_split "*add<mode>3_poly_1"
2410   [(set
2411     (match_operand:GPI 0 "register_operand")
2412     (plus:GPI
2413      (match_operand:GPI 1 "register_operand")
2414      (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand")))]
2415   "TARGET_SVE && operands[0] != stack_pointer_rtx"
2416   {@ [ cons: =0 , 1   , 2   ; attrs: type ]
2417      [ r        , %rk , I   ; alu_imm     ] add\t%<w>0, %<w>1, %2
2418      [ r        , rk  , r   ; alu_sreg    ] add\t%<w>0, %<w>1, %<w>2
2419      [ r        , rk  , J   ; alu_imm     ] sub\t%<w>0, %<w>1, #%n2
2420      [ r        , rk  , Uaa ; multiple    ] #
2421      [ r        , 0   , Uai ; alu_imm     ] << aarch64_output_sve_scalar_inc_dec (operands[2]);
2422      [ r        , rk  , Uav ; alu_imm     ] << aarch64_output_sve_addvl_addpl (operands[2]);
2423      [ &r       , rk  , Uat ; multiple    ] #
2424   }
2425   "&& epilogue_completed
2426    && !reg_overlap_mentioned_p (operands[0], operands[1])
2427    && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)"
2428   [(const_int 0)]
2429   {
2430     aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
2431                               operands[2], operands[0], NULL_RTX);
2432     DONE;
2433   }
2434   ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
2437 (define_split
2438   [(set (match_operand:DI 0 "register_operand")
2439         (zero_extend:DI
2440           (plus:SI
2441             (match_operand:SI 1 "register_operand")
2442             (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
2443   "epilogue_completed"
2444   [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
2445    (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
2446   {
2447     HOST_WIDE_INT i = INTVAL (operands[2]);
2448     HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
2449     operands[3] = GEN_INT (i - s);
2450     operands[4] = GEN_INT (s);
2451     operands[5] = gen_lowpart (SImode, operands[0]);
2452   }
2455 (define_expand "addv<mode>4"
2456   [(match_operand:GPI 0 "register_operand")
2457    (match_operand:GPI 1 "register_operand")
2458    (match_operand:GPI 2 "aarch64_plus_operand")
2459    (label_ref (match_operand 3 "" ""))]
2460   ""
2462   if (CONST_INT_P (operands[2]))
2463     emit_insn (gen_add<mode>3_compareV_imm (operands[0], operands[1],
2464                                             operands[2]));
2465   else
2466     emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
2467   aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2469   DONE;
2472 (define_expand "uaddv<mode>4"
2473   [(match_operand:GPI 0 "register_operand")
2474    (match_operand:GPI 1 "register_operand")
2475    (match_operand:GPI 2 "register_operand")
2476    (label_ref (match_operand 3 "" ""))]
2477   ""
2479   emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
2480   aarch64_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
2482   DONE;
2485 (define_expand "addti3"
2486   [(set (match_operand:TI 0 "register_operand")
2487         (plus:TI (match_operand:TI 1 "register_operand")
2488                  (match_operand:TI 2 "aarch64_reg_or_imm")))]
2489   ""
2491   rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2493   aarch64_addti_scratch_regs (operands[1], operands[2],
2494                               &low_dest, &op1_low, &op2_low,
2495                               &high_dest, &op1_high, &op2_high);
2497   if (op2_low == const0_rtx)
2498     {
2499       low_dest = op1_low;
2500       if (!aarch64_pluslong_operand (op2_high, DImode))
2501         op2_high = force_reg (DImode, op2_high);
2502       emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
2503     }
2504   else
2505     {
2506       emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2507                                       force_reg (DImode, op2_low)));
2508       emit_insn (gen_adddi3_carryin (high_dest, op1_high,
2509                                      force_reg (DImode, op2_high)));
2510     }
2512   emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2513   emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2515   DONE;
2518 (define_expand "addvti4"
2519   [(match_operand:TI 0 "register_operand")
2520    (match_operand:TI 1 "register_operand")
2521    (match_operand:TI 2 "aarch64_reg_or_imm")
2522    (label_ref (match_operand 3 "" ""))]
2523   ""
2525   rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2527   aarch64_addti_scratch_regs (operands[1], operands[2],
2528                               &low_dest, &op1_low, &op2_low,
2529                               &high_dest, &op1_high, &op2_high);
2531   if (op2_low == const0_rtx)
2532     {
2533       low_dest = op1_low;
2534       emit_insn (gen_adddi3_compareV (high_dest, op1_high,
2535                                       force_reg (DImode, op2_high)));
2536     }
2537   else
2538     {
2539       emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2540                                       force_reg (DImode, op2_low)));
2541       emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
2542                                       force_reg (DImode, op2_high)));
2543     }
2545   emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2546   emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2548   aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2549   DONE;
2552 (define_expand "uaddvti4"
2553   [(match_operand:TI 0 "register_operand")
2554    (match_operand:TI 1 "register_operand")
2555    (match_operand:TI 2 "aarch64_reg_or_imm")
2556    (label_ref (match_operand 3 "" ""))]
2557   ""
2559   rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2561   aarch64_addti_scratch_regs (operands[1], operands[2],
2562                               &low_dest, &op1_low, &op2_low,
2563                               &high_dest, &op1_high, &op2_high);
2565   if (op2_low == const0_rtx)
2566     {
2567       low_dest = op1_low;
2568       emit_insn (gen_adddi3_compareC (high_dest, op1_high,
2569                                       force_reg (DImode, op2_high)));
2570     }
2571   else
2572     {
2573       emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2574                                       force_reg (DImode, op2_low)));
2575       emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
2576                                       force_reg (DImode, op2_high)));
2577     }
2579   emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2580   emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2582   aarch64_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[3]);
2583   DONE;
2584  })
2586 (define_insn "add<mode>3_compare0"
2587   [(set (reg:CC_NZ CC_REGNUM)
2588         (compare:CC_NZ
2589          (plus:GPI (match_operand:GPI 1 "register_operand")
2590                    (match_operand:GPI 2 "aarch64_plus_operand"))
2591          (const_int 0)))
2592    (set (match_operand:GPI 0 "register_operand")
2593         (plus:GPI (match_dup 1) (match_dup 2)))]
2594   ""
2595   {@ [ cons: =0 , 1   , 2 ; attrs: type ]
2596      [ r        , %rk , r ; alus_sreg   ] adds\t%<w>0, %<w>1, %<w>2
2597      [ r        , rk  , I ; alus_imm    ] adds\t%<w>0, %<w>1, %2
2598      [ r        , rk  , J ; alus_imm    ] subs\t%<w>0, %<w>1, #%n2
2599   }
2602 ;; zero_extend version of above
2603 (define_insn "*addsi3_compare0_uxtw"
2604   [(set (reg:CC_NZ CC_REGNUM)
2605         (compare:CC_NZ
2606          (plus:SI (match_operand:SI 1 "register_operand")
2607                   (match_operand:SI 2 "aarch64_plus_operand"))
2608          (const_int 0)))
2609    (set (match_operand:DI 0 "register_operand")
2610         (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
2611   ""
2612   {@ [ cons: =0 , 1   , 2 ; attrs: type ]
2613      [ r        , %rk , r ; alus_sreg   ] adds\t%w0, %w1, %w2
2614      [ r        , rk  , I ; alus_imm    ] adds\t%w0, %w1, %2
2615      [ r        , rk  , J ; alus_imm    ] subs\t%w0, %w1, #%n2
2616   }
2619 (define_insn "*add<mode>3_compareC_cconly"
2620   [(set (reg:CC_C CC_REGNUM)
2621         (compare:CC_C
2622           (plus:GPI
2623             (match_operand:GPI 0 "register_operand")
2624             (match_operand:GPI 1 "aarch64_plus_operand"))
2625           (match_dup 0)))]
2626   ""
2627   {@ [ cons: 0 , 1 ; attrs: type ]
2628      [ r       , r ; alus_sreg   ] cmn\t%<w>0, %<w>1
2629      [ r       , I ; alus_imm    ] cmn\t%<w>0, %1
2630      [ r       , J ; alus_imm    ] cmp\t%<w>0, #%n1
2631   }
2634 (define_insn "add<mode>3_compareC"
2635   [(set (reg:CC_C CC_REGNUM)
2636         (compare:CC_C
2637           (plus:GPI
2638             (match_operand:GPI 1 "register_operand")
2639             (match_operand:GPI 2 "aarch64_plus_operand"))
2640           (match_dup 1)))
2641    (set (match_operand:GPI 0 "register_operand")
2642         (plus:GPI (match_dup 1) (match_dup 2)))]
2643   ""
2644   {@ [ cons: =0 , 1  , 2 ; attrs: type ]
2645      [ r        , rk , r ; alus_sreg   ] adds\t%<w>0, %<w>1, %<w>2
2646      [ r        , rk , I ; alus_imm    ] adds\t%<w>0, %<w>1, %2
2647      [ r        , rk , J ; alus_imm    ] subs\t%<w>0, %<w>1, #%n2
2648   }
2651 (define_insn "*add<mode>3_compareV_cconly_imm"
2652   [(set (reg:CC_V CC_REGNUM)
2653         (compare:CC_V
2654           (plus:<DWI>
2655             (sign_extend:<DWI> (match_operand:GPI 0 "register_operand"))
2656             (match_operand:<DWI> 1 "const_scalar_int_operand"))
2657           (sign_extend:<DWI>
2658            (plus:GPI
2659             (match_dup 0)
2660             (match_operand:GPI 2 "aarch64_plus_immediate")))))]
2661   "INTVAL (operands[1]) == INTVAL (operands[2])"
2662   {@ [ cons: 0 , 2  ]
2663      [ r       , I  ] cmn\t%<w>0, %<w>1
2664      [ r       , J  ] cmp\t%<w>0, #%n1
2665   }
2666   [(set_attr "type" "alus_imm")]
2669 (define_insn "*add<mode>3_compareV_cconly"
2670   [(set (reg:CC_V CC_REGNUM)
2671         (compare:CC_V
2672           (plus:<DWI>
2673             (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
2674             (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2675           (sign_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
2676   ""
2677   "cmn\\t%<w>0, %<w>1"
2678   [(set_attr "type" "alus_sreg")]
2681 (define_insn "add<mode>3_compareV_imm"
2682   [(set (reg:CC_V CC_REGNUM)
2683         (compare:CC_V
2684           (plus:<DWI>
2685             (sign_extend:<DWI>
2686               (match_operand:GPI 1 "register_operand"))
2687             (match_operand:GPI 2 "aarch64_plus_immediate"))
2688           (sign_extend:<DWI>
2689             (plus:GPI (match_dup 1) (match_dup 2)))))
2690    (set (match_operand:GPI 0 "register_operand")
2691         (plus:GPI (match_dup 1) (match_dup 2)))]
2692    ""
2693    {@ [ cons: =0 , 1  , 2 ; attrs: type ]
2694       [ r        , rk , I ; alus_imm    ] adds\t%<w>0, %<w>1, %<w>2
2695       [ r        , rk , J ; alus_imm    ] subs\t%<w>0, %<w>1, #%n2
2696   }
2699 (define_insn "add<mode>3_compareV"
2700   [(set (reg:CC_V CC_REGNUM)
2701         (compare:CC_V
2702           (plus:<DWI>
2703             (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "rk"))
2704             (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2705           (sign_extend:<DWI> (plus:GPI (match_dup 1) (match_dup 2)))))
2706    (set (match_operand:GPI 0 "register_operand" "=r")
2707         (plus:GPI (match_dup 1) (match_dup 2)))]
2708   ""
2709   "adds\\t%<w>0, %<w>1, %<w>2"
2710   [(set_attr "type" "alus_sreg")]
2713 (define_insn "*adds_shift_imm_<mode>"
2714   [(set (reg:CC_NZ CC_REGNUM)
2715         (compare:CC_NZ
2716          (plus:GPI (ASHIFT:GPI
2717                     (match_operand:GPI 1 "register_operand" "r")
2718                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2719                    (match_operand:GPI 3 "register_operand" "r"))
2720          (const_int 0)))
2721    (set (match_operand:GPI 0 "register_operand" "=r")
2722         (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
2723                   (match_dup 3)))]
2724   ""
2725   "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2726   [(set_attr "type" "alus_shift_imm")]
2729 (define_insn "*subs_shift_imm_<mode>"
2730   [(set (reg:CC_NZ CC_REGNUM)
2731         (compare:CC_NZ
2732          (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2733                     (ASHIFT:GPI
2734                      (match_operand:GPI 2 "register_operand" "r")
2735                      (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
2736          (const_int 0)))
2737    (set (match_operand:GPI 0 "register_operand" "=r")
2738         (minus:GPI (match_dup 1)
2739                    (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
2740   ""
2741   "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
2742   [(set_attr "type" "alus_shift_imm")]
2745 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2746   [(set (reg:CC_NZ CC_REGNUM)
2747         (compare:CC_NZ
2748          (plus:GPI
2749           (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2750           (match_operand:GPI 2 "register_operand" "rk"))
2751         (const_int 0)))
2752    (set (match_operand:GPI 0 "register_operand" "=r")
2753         (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
2754   ""
2755   "adds\\t%<GPI:w>0, %<GPI:w>2, %w1, <su>xt<ALLX:size>"
2756   [(set_attr "type" "alus_ext")]
2759 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2760   [(set (reg:CC_NZ CC_REGNUM)
2761         (compare:CC_NZ
2762          (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2763                     (ANY_EXTEND:GPI
2764                      (match_operand:ALLX 2 "register_operand" "r")))
2765         (const_int 0)))
2766    (set (match_operand:GPI 0 "register_operand" "=r")
2767         (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
2768   ""
2769   "subs\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size>"
2770   [(set_attr "type" "alus_ext")]
2773 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2774   [(set (reg:CC_NZ CC_REGNUM)
2775         (compare:CC_NZ
2776          (plus:GPI (ashift:GPI 
2777                     (ANY_EXTEND:GPI 
2778                      (match_operand:ALLX 1 "register_operand" "r"))
2779                     (match_operand 2 "aarch64_imm3" "Ui3"))
2780                    (match_operand:GPI 3 "register_operand" "rk"))
2781          (const_int 0)))
2782    (set (match_operand:GPI 0 "register_operand" "=rk")
2783         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
2784                               (match_dup 2))
2785                   (match_dup 3)))]
2786   ""
2787   "adds\\t%<GPI:w>0, %<GPI:w>3, %w1, <su>xt<ALLX:size> %2"
2788   [(set_attr "type" "alus_ext")]
2791 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2792   [(set (reg:CC_NZ CC_REGNUM)
2793         (compare:CC_NZ
2794          (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2795                     (ashift:GPI 
2796                      (ANY_EXTEND:GPI
2797                       (match_operand:ALLX 2 "register_operand" "r"))
2798                      (match_operand 3 "aarch64_imm3" "Ui3")))
2799          (const_int 0)))
2800    (set (match_operand:GPI 0 "register_operand" "=rk")
2801         (minus:GPI (match_dup 1)
2802                    (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
2803                                (match_dup 3))))]
2804   ""
2805   "subs\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size> %3"
2806   [(set_attr "type" "alus_ext")]
2809 (define_insn "*add<mode>3nr_compare0"
2810   [(set (reg:CC_NZ CC_REGNUM)
2811         (compare:CC_NZ
2812          (plus:GPI (match_operand:GPI 0 "register_operand")
2813                    (match_operand:GPI 1 "aarch64_plus_operand"))
2814          (const_int 0)))]
2815   ""
2816   {@ [ cons: 0 , 1 ; attrs: type ]
2817      [ %r      , r ; alus_sreg   ] cmn\t%<w>0, %<w>1
2818      [ r       , I ; alus_imm    ] cmn\t%<w>0, %1
2819      [ r       , J ; alus_imm    ] cmp\t%<w>0, #%n1
2820   }
2823 (define_insn "aarch64_sub<mode>_compare0"
2824   [(set (reg:CC_NZ CC_REGNUM)
2825         (compare:CC_NZ
2826          (minus:GPI (match_operand:GPI 0 "register_operand" "r")
2827                    (match_operand:GPI 1 "aarch64_plus_operand" "r"))
2828          (const_int 0)))]
2829   ""
2830   "cmp\\t%<w>0, %<w>1"
2831   [(set_attr "type" "alus_sreg")]
2834 (define_insn "*compare_neg<mode>"
2835   [(set (reg:CC_Z CC_REGNUM)
2836         (compare:CC_Z
2837          (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2838          (match_operand:GPI 1 "register_operand" "r")))]
2839   ""
2840   "cmn\\t%<w>1, %<w>0"
2841   [(set_attr "type" "alus_sreg")]
2844 (define_insn "*add_<shift>_<mode>"
2845   [(set (match_operand:GPI 0 "register_operand" "=r")
2846         (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2847                               (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2848                   (match_operand:GPI 3 "register_operand" "r")))]
2849   ""
2850   "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2851   [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
2854 ;; zero_extend version of above
2855 (define_insn "*add_<shift>_si_uxtw"
2856   [(set (match_operand:DI 0 "register_operand" "=r")
2857         (zero_extend:DI
2858          (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2859                              (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2860                   (match_operand:SI 3 "register_operand" "r"))))]
2861   ""
2862   "add\\t%w0, %w3, %w1, <shift> %2"
2863   [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
2866 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2867   [(set (match_operand:GPI 0 "register_operand" "=rk")
2868         (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2869                   (match_operand:GPI 2 "register_operand" "r")))]
2870   ""
2871   "add\\t%<GPI:w>0, %<GPI:w>2, %w1, <su>xt<ALLX:size>"
2872   [(set_attr "type" "alu_ext")]
2875 ;; zero_extend version of above
2876 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2877   [(set (match_operand:DI 0 "register_operand" "=rk")
2878         (zero_extend:DI
2879          (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2880                   (match_operand:GPI 2 "register_operand" "r"))))]
2881   ""
2882   "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2883   [(set_attr "type" "alu_ext")]
2886 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2887   [(set (match_operand:GPI 0 "register_operand" "=rk")
2888         (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2889                                (match_operand:ALLX 1 "register_operand" "r"))
2890                               (match_operand 2 "aarch64_imm3" "Ui3"))
2891                   (match_operand:GPI 3 "register_operand" "r")))]
2892   ""
2893   "add\\t%<GPI:w>0, %<GPI:w>3, %w1, <su>xt<ALLX:size> %2"
2894   [(set_attr "type" "alu_ext")]
2897 ;; zero_extend version of above
2898 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2899   [(set (match_operand:DI 0 "register_operand" "=rk")
2900         (zero_extend:DI
2901          (plus:SI (ashift:SI (ANY_EXTEND:SI
2902                               (match_operand:SHORT 1 "register_operand" "r"))
2903                              (match_operand 2 "aarch64_imm3" "Ui3"))
2904                   (match_operand:SI 3 "register_operand" "r"))))]
2905   ""
2906   "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2907   [(set_attr "type" "alu_ext")]
2910 (define_expand "add<mode>3_carryin"
2911   [(set (match_operand:GPI 0 "register_operand")
2912         (plus:GPI
2913           (plus:GPI
2914             (ltu:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2915             (match_operand:GPI 1 "aarch64_reg_or_zero"))
2916           (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2917    ""
2918    ""
2921 ;; Note that add with carry with two zero inputs is matched by cset,
2922 ;; and that add with carry with one zero input is matched by cinc.
2924 (define_insn "*add<mode>3_carryin"
2925   [(set (match_operand:GPI 0 "register_operand" "=r")
2926         (plus:GPI
2927           (plus:GPI
2928             (match_operand:GPI 3 "aarch64_carry_operation" "")
2929             (match_operand:GPI 1 "register_operand" "r"))
2930           (match_operand:GPI 2 "register_operand" "r")))]
2931    ""
2932    "adc\\t%<w>0, %<w>1, %<w>2"
2933   [(set_attr "type" "adc_reg")]
2936 ;; zero_extend version of above
2937 (define_insn "*addsi3_carryin_uxtw"
2938   [(set (match_operand:DI 0 "register_operand" "=r")
2939         (zero_extend:DI
2940           (plus:SI
2941             (plus:SI
2942               (match_operand:SI 3 "aarch64_carry_operation" "")
2943               (match_operand:SI 1 "register_operand" "r"))
2944             (match_operand:SI 2 "register_operand" "r"))))]
2945    ""
2946    "adc\\t%w0, %w1, %w2"
2947   [(set_attr "type" "adc_reg")]
2950 (define_expand "add<mode>3_carryinC"
2951   [(parallel
2952      [(set (match_dup 3)
2953            (compare:CC_ADC
2954              (plus:<DWI>
2955                (plus:<DWI>
2956                  (match_dup 4)
2957                  (zero_extend:<DWI>
2958                    (match_operand:GPI 1 "register_operand")))
2959                (zero_extend:<DWI>
2960                  (match_operand:GPI 2 "register_operand")))
2961              (match_dup 6)))
2962       (set (match_operand:GPI 0 "register_operand")
2963            (plus:GPI
2964              (plus:GPI (match_dup 5) (match_dup 1))
2965              (match_dup 2)))])]
2966    ""
2968   operands[3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
2969   rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2970   operands[4] = gen_rtx_LTU (<DWI>mode, ccin, const0_rtx);
2971   operands[5] = gen_rtx_LTU (<MODE>mode, ccin, const0_rtx);
2972   operands[6] = immed_wide_int_const (wi::shwi (1, <DWI>mode)
2973                                       << GET_MODE_BITSIZE (<MODE>mode),
2974                                       TImode);
2977 (define_insn "*add<mode>3_carryinC_zero"
2978   [(set (reg:CC_ADC CC_REGNUM)
2979         (compare:CC_ADC
2980           (plus:<DWI>
2981             (match_operand:<DWI> 2 "aarch64_carry_operation" "")
2982             (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2983           (match_operand 4 "const_scalar_int_operand" "")))
2984    (set (match_operand:GPI 0 "register_operand" "=r")
2985         (plus:GPI (match_operand:GPI 3 "aarch64_carry_operation" "")
2986                   (match_dup 1)))]
2987   "rtx_mode_t (operands[4], <DWI>mode)
2988    == (wi::shwi (1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2989    "adcs\\t%<w>0, %<w>1, <w>zr"
2990   [(set_attr "type" "adc_reg")]
2993 (define_insn "*add<mode>3_carryinC"
2994   [(set (reg:CC_ADC CC_REGNUM)
2995         (compare:CC_ADC
2996           (plus:<DWI>
2997             (plus:<DWI>
2998               (match_operand:<DWI> 3 "aarch64_carry_operation" "")
2999               (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
3000             (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
3001           (match_operand 5 "const_scalar_int_operand" "")))
3002    (set (match_operand:GPI 0 "register_operand" "=r")
3003         (plus:GPI
3004           (plus:GPI (match_operand:GPI 4 "aarch64_carry_operation" "")
3005                     (match_dup 1))
3006           (match_dup 2)))]
3007   "rtx_mode_t (operands[5], <DWI>mode)
3008    == (wi::shwi (1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
3009    "adcs\\t%<w>0, %<w>1, %<w>2"
3010   [(set_attr "type" "adc_reg")]
3013 (define_expand "add<mode>3_carryinV"
3014   [(parallel
3015      [(set (reg:CC_V CC_REGNUM)
3016            (compare:CC_V
3017              (plus:<DWI>
3018                (plus:<DWI>
3019                  (match_dup 3)
3020                  (sign_extend:<DWI>
3021                    (match_operand:GPI 1 "register_operand")))
3022                (sign_extend:<DWI>
3023                  (match_operand:GPI 2 "register_operand")))
3024            (sign_extend:<DWI>
3025              (plus:GPI
3026                (plus:GPI (match_dup 4) (match_dup 1))
3027                (match_dup 2)))))
3028       (set (match_operand:GPI 0 "register_operand")
3029            (plus:GPI
3030              (plus:GPI (match_dup 4) (match_dup 1))
3031              (match_dup 2)))])]
3032    ""
3034   rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
3035   operands[3] = gen_rtx_LTU (<DWI>mode, cc, const0_rtx);
3036   operands[4] = gen_rtx_LTU (<MODE>mode, cc, const0_rtx);
3039 (define_insn "*add<mode>3_carryinV_zero"
3040   [(set (reg:CC_V CC_REGNUM)
3041         (compare:CC_V
3042           (plus:<DWI>
3043             (match_operand:<DWI> 2 "aarch64_carry_operation" "")
3044             (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
3045           (sign_extend:<DWI>
3046             (plus:GPI
3047               (match_operand:GPI 3 "aarch64_carry_operation" "")
3048               (match_dup 1)))))
3049    (set (match_operand:GPI 0 "register_operand" "=r")
3050         (plus:GPI (match_dup 3) (match_dup 1)))]
3051    ""
3052    "adcs\\t%<w>0, %<w>1, <w>zr"
3053   [(set_attr "type" "adc_reg")]
3056 (define_insn "*add<mode>3_carryinV"
3057   [(set (reg:CC_V CC_REGNUM)
3058         (compare:CC_V
3059           (plus:<DWI>
3060             (plus:<DWI>
3061               (match_operand:<DWI> 3 "aarch64_carry_operation" "")
3062               (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
3063             (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
3064           (sign_extend:<DWI>
3065             (plus:GPI
3066               (plus:GPI
3067                 (match_operand:GPI 4 "aarch64_carry_operation" "")
3068                 (match_dup 1))
3069               (match_dup 2)))))
3070    (set (match_operand:GPI 0 "register_operand" "=r")
3071         (plus:GPI
3072           (plus:GPI (match_dup 4) (match_dup 1))
3073           (match_dup 2)))]
3074    ""
3075    "adcs\\t%<w>0, %<w>1, %<w>2"
3076   [(set_attr "type" "adc_reg")]
3079 (define_insn "*add_uxt<mode>_shift2"
3080   [(set (match_operand:GPI 0 "register_operand" "=rk")
3081         (plus:GPI (and:GPI
3082                    (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3083                                (match_operand 2 "aarch64_imm3" "Ui3"))
3084                    (match_operand 3 "const_int_operand" "n"))
3085                   (match_operand:GPI 4 "register_operand" "r")))]
3086   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
3087   "*
3088   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
3089                                            INTVAL (operands[3])));
3090   return \"add\t%<w>0, %<w>4, %w1, uxt%e3 %2\";"
3091   [(set_attr "type" "alu_ext")]
3094 ;; zero_extend version of above
3095 (define_insn "*add_uxtsi_shift2_uxtw"
3096   [(set (match_operand:DI 0 "register_operand" "=rk")
3097         (zero_extend:DI
3098          (plus:SI (and:SI
3099                    (ashift:SI (match_operand:SI 1 "register_operand" "r")
3100                               (match_operand 2 "aarch64_imm3" "Ui3"))
3101                    (match_operand 3 "const_int_operand" "n"))
3102                   (match_operand:SI 4 "register_operand" "r"))))]
3103   "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
3104   "*
3105   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3106                                            INTVAL (operands[3])));
3107   return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
3108   [(set_attr "type" "alu_ext")]
3111 (define_insn "subsi3"
3112   [(set (match_operand:SI 0 "register_operand" "=rk")
3113         (minus:SI (match_operand:SI 1 "register_operand" "rk")
3114                   (match_operand:SI 2 "register_operand" "r")))]
3115   ""
3116   "sub\\t%w0, %w1, %w2"
3117   [(set_attr "type" "alu_sreg")]
3120 ;; zero_extend version of above
3121 (define_insn "*subsi3_uxtw"
3122   [(set (match_operand:DI 0 "register_operand" "=rk")
3123         (zero_extend:DI
3124          (minus:SI (match_operand:SI 1 "register_operand" "rk")
3125                    (match_operand:SI 2 "register_operand" "r"))))]
3126   ""
3127   "sub\\t%w0, %w1, %w2"
3128   [(set_attr "type" "alu_sreg")]
3131 (define_insn "subdi3"
3132   [(set (match_operand:DI 0 "register_operand")
3133         (minus:DI (match_operand:DI 1 "register_operand")
3134                   (match_operand:DI 2 "register_operand")))]
3135   ""
3136   {@ [ cons: =0 , 1  , 2 ; attrs: type , arch  ]
3137      [ rk       , rk , r ; alu_sreg    , *     ] sub\t%x0, %x1, %x2
3138      [ w        , w  , w ; neon_sub    , simd  ] sub\t%d0, %d1, %d2
3139   }
3142 (define_expand "subv<GPI:mode>4"
3143   [(match_operand:GPI 0 "register_operand")
3144    (match_operand:GPI 1 "register_operand")
3145    (match_operand:GPI 2 "aarch64_plus_operand")
3146    (label_ref (match_operand 3 "" ""))]
3147   ""
3149   if (CONST_INT_P (operands[2]))
3150     emit_insn (gen_subv<mode>_imm (operands[0], operands[1], operands[2]));
3151   else
3152     emit_insn (gen_subv<mode>_insn (operands[0], operands[1], operands[2]));
3153   aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
3155   DONE;
3158 (define_insn "subv<GPI:mode>_insn"
3159   [(set (reg:CC_V CC_REGNUM)
3160         (compare:CC_V
3161          (sign_extend:<DWI>
3162           (minus:GPI
3163            (match_operand:GPI 1 "register_operand" "rk")
3164            (match_operand:GPI 2 "register_operand" "r")))
3165          (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
3166                       (sign_extend:<DWI> (match_dup 2)))))
3167    (set (match_operand:GPI 0 "register_operand" "=r")
3168         (minus:GPI (match_dup 1) (match_dup 2)))]
3169   ""
3170   "subs\\t%<w>0, %<w>1, %<w>2"
3171   [(set_attr "type" "alus_sreg")]
3174 (define_insn "subv<GPI:mode>_imm"
3175   [(set (reg:CC_V CC_REGNUM)
3176         (compare:CC_V
3177          (sign_extend:<DWI>
3178           (minus:GPI
3179            (match_operand:GPI 1 "register_operand")
3180            (match_operand:GPI 2 "aarch64_plus_immediate")))
3181          (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
3182                       (match_dup 2))))
3183    (set (match_operand:GPI 0 "register_operand")
3184         (minus:GPI (match_dup 1) (match_dup 2)))]
3185   ""
3186   {@ [ cons: =0 , 1  , 2  ]
3187      [ r        , rk , I  ] subs\t%<w>0, %<w>1, %2
3188      [ r        , rk , J  ] adds\t%<w>0, %<w>1, #%n2
3189   }
3190   [(set_attr "type" "alus_sreg")]
3193 (define_expand "negv<GPI:mode>3"
3194   [(match_operand:GPI 0 "register_operand")
3195    (match_operand:GPI 1 "register_operand")
3196    (label_ref (match_operand 2 "" ""))]
3197   ""
3198   {
3199     emit_insn (gen_negv<mode>_insn (operands[0], operands[1]));
3200     aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
3202     DONE;
3203   }
3206 (define_insn "negv<GPI:mode>_insn"
3207   [(set (reg:CC_V CC_REGNUM)
3208         (compare:CC_V
3209          (sign_extend:<DWI>
3210           (neg:GPI (match_operand:GPI 1 "register_operand" "r")))
3211          (neg:<DWI> (sign_extend:<DWI> (match_dup 1)))))
3212    (set (match_operand:GPI 0 "register_operand" "=r")
3213         (neg:GPI (match_dup 1)))]
3214   ""
3215   "negs\\t%<w>0, %<w>1"
3216   [(set_attr "type" "alus_sreg")]
3219 (define_insn "negv<GPI:mode>_cmp_only"
3220   [(set (reg:CC_V CC_REGNUM)
3221         (compare:CC_V
3222          (sign_extend:<DWI>
3223           (neg:GPI (match_operand:GPI 0 "register_operand" "r")))
3224          (neg:<DWI> (sign_extend:<DWI> (match_dup 0)))))]
3225   ""
3226   "negs\\t%<w>zr, %<w>0"
3227   [(set_attr "type" "alus_sreg")]
3230 (define_insn "*cmpv<GPI:mode>_insn"
3231   [(set (reg:CC_V CC_REGNUM)
3232         (compare:CC_V
3233          (sign_extend:<DWI>
3234           (minus:GPI (match_operand:GPI 0 "register_operand")
3235                      (match_operand:GPI 1 "aarch64_plus_operand")))
3236          (minus:<DWI> (sign_extend:<DWI> (match_dup 0))
3237                     (sign_extend:<DWI> (match_dup 1)))))]
3238   ""
3239   {@ [ cons: 0 , 1  ]
3240      [ r       , r  ] cmp\t%<w>0, %<w>1
3241      [ r       , I  ] cmp\t%<w>0, %1
3242      [ r       , J  ] cmp\t%<w>0, #%n1
3243   }
3244   [(set_attr "type" "alus_sreg")]
3247 (define_expand "usubv<mode>4"
3248   [(match_operand:GPI 0 "register_operand")
3249    (match_operand:GPI 1 "aarch64_reg_or_zero")
3250    (match_operand:GPI 2 "aarch64_reg_or_zero")
3251    (label_ref (match_operand 3 "" ""))]
3252   ""
3254   emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
3255   aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
3257   DONE;
3260 (define_expand "subti3"
3261   [(set (match_operand:TI 0 "register_operand")
3262         (minus:TI (match_operand:TI 1 "aarch64_reg_or_zero")
3263                   (match_operand:TI 2 "register_operand")))]
3264   ""
3266   rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
3268   aarch64_subvti_scratch_regs (operands[1], operands[2],
3269                                &low_dest, &op1_low, &op2_low,
3270                                &high_dest, &op1_high, &op2_high);
3272   emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
3273   emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
3275   emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
3276   emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
3277   DONE;
3280 (define_expand "subvti4"
3281   [(match_operand:TI 0 "register_operand")
3282    (match_operand:TI 1 "register_operand")
3283    (match_operand:TI 2 "aarch64_reg_or_imm")
3284    (label_ref (match_operand 3 "" ""))]
3285   ""
3287   rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
3289   aarch64_subvti_scratch_regs (operands[1], operands[2],
3290                                &low_dest, &op1_low, &op2_low,
3291                                &high_dest, &op1_high, &op2_high);
3292   aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
3293                          high_dest, op1_high, op2_high, false);
3295   aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
3296   DONE;
3299 (define_expand "usubvti4"
3300   [(match_operand:TI 0 "register_operand")
3301    (match_operand:TI 1 "register_operand")
3302    (match_operand:TI 2 "aarch64_reg_or_imm")
3303    (label_ref (match_operand 3 "" ""))]
3304   ""
3306   rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
3308   aarch64_subvti_scratch_regs (operands[1], operands[2],
3309                                     &low_dest, &op1_low, &op2_low,
3310                                &high_dest, &op1_high, &op2_high);
3311   aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
3312                          high_dest, op1_high, op2_high, true);
3314   aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
3315   DONE;
3318 (define_expand "negvti3"
3319   [(match_operand:TI 0 "register_operand")
3320    (match_operand:TI 1 "register_operand")
3321    (label_ref (match_operand 2 "" ""))]
3322   ""
3323   {
3324     emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[0]),
3325                                    gen_lowpart (DImode, operands[1])));
3326     emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[0]),
3327                                     gen_highpart (DImode, operands[1])));
3328     aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
3330     DONE;
3331   }
3334 (define_insn "negdi_carryout"
3335   [(set (reg:CC CC_REGNUM)
3336         (compare:CC
3337          (const_int 0) (match_operand:DI 1 "register_operand" "r")))
3338    (set (match_operand:DI 0 "register_operand" "=r")
3339         (neg:DI (match_dup 1)))]
3340   ""
3341   "negs\\t%0, %1"
3342   [(set_attr "type" "alus_sreg")]
3345 (define_insn "negvdi_carryinV"
3346   [(set (reg:CC_V CC_REGNUM)
3347         (compare:CC_V
3348          (neg:TI (plus:TI
3349                   (ltu:TI (reg:CC CC_REGNUM) (const_int 0))
3350                   (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))))
3351          (sign_extend:TI
3352           (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
3353                            (match_dup 1))))))
3354    (set (match_operand:DI 0 "register_operand" "=r")
3355         (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
3356                          (match_dup 1))))]
3357   ""
3358   "ngcs\\t%0, %1"
3359   [(set_attr "type" "alus_sreg")]
3362 (define_insn "*sub<mode>3_compare0"
3363   [(set (reg:CC_NZ CC_REGNUM)
3364         (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3365                                   (match_operand:GPI 2 "register_operand" "r"))
3366                        (const_int 0)))
3367    (set (match_operand:GPI 0 "register_operand" "=r")
3368         (minus:GPI (match_dup 1) (match_dup 2)))]
3369   ""
3370   "subs\\t%<w>0, %<w>1, %<w>2"
3371   [(set_attr "type" "alus_sreg")]
3374 ;; zero_extend version of above
3375 (define_insn "*subsi3_compare0_uxtw"
3376   [(set (reg:CC_NZ CC_REGNUM)
3377         (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "rk")
3378                                  (match_operand:SI 2 "register_operand" "r"))
3379                        (const_int 0)))
3380    (set (match_operand:DI 0 "register_operand" "=r")
3381         (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
3382   ""
3383   "subs\\t%w0, %w1, %w2"
3384   [(set_attr "type" "alus_sreg")]
3387 (define_insn "sub<mode>3_compare1_imm"
3388   [(set (reg:CC CC_REGNUM)
3389         (compare:CC
3390           (match_operand:GPI 1 "register_operand")
3391           (match_operand:GPI 2 "aarch64_plus_immediate")))
3392    (set (match_operand:GPI 0 "register_operand")
3393         (plus:GPI
3394           (match_dup 1)
3395           (match_operand:GPI 3 "aarch64_plus_immediate")))]
3396   "UINTVAL (operands[2]) == -UINTVAL (operands[3])"
3397   {@ [ cons: =0 , 1  , 2 , 3  ]
3398      [ r        , rk , I , J  ] subs\t%<w>0, %<w>1, %2
3399      [ r        , rk , J , I  ] adds\t%<w>0, %<w>1, #%n2
3400   }
3401   [(set_attr "type" "alus_imm")]
3404 (define_insn "sub<mode>3_compare1"
3405   [(set (reg:CC CC_REGNUM)
3406         (compare:CC
3407           (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ")
3408           (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
3409    (set (match_operand:GPI 0 "register_operand" "=r")
3410         (minus:GPI (match_dup 1) (match_dup 2)))]
3411   ""
3412   "subs\\t%<w>0, %<w>1, %<w>2"
3413   [(set_attr "type" "alus_sreg")]
3416 (define_peephole2
3417   [(set (match_operand:GPI 0 "aarch64_general_reg")
3418         (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
3419                     (match_operand:GPI 2 "aarch64_reg_or_zero")))
3420    (set (reg:CC CC_REGNUM)
3421         (compare:CC
3422           (match_dup 1)
3423           (match_dup 2)))]
3424   "!reg_overlap_mentioned_p (operands[0], operands[1])
3425    && !reg_overlap_mentioned_p (operands[0], operands[2])"
3426   [(const_int 0)]
3427   {
3428     emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
3429                                          operands[2]));
3430     DONE;
3431   }
3434 ;; Same as the above peephole but with the compare and minus in
3435 ;; swapped order.  The restriction on overlap between operand 0
3436 ;; and operands 1 and 2 doesn't apply here.
3437 (define_peephole2
3438   [(set (reg:CC CC_REGNUM)
3439         (compare:CC
3440           (match_operand:GPI 1 "aarch64_reg_or_zero")
3441           (match_operand:GPI 2 "aarch64_reg_or_zero")))
3442    (set (match_operand:GPI 0 "aarch64_general_reg")
3443         (minus:GPI (match_dup 1)
3444                    (match_dup 2)))]
3445   ""
3446   [(const_int 0)]
3447   {
3448     emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
3449                                          operands[2]));
3450     DONE;
3451   }
3454 (define_peephole2
3455   [(set (match_operand:GPI 0 "aarch64_general_reg")
3456         (plus:GPI (match_operand:GPI 1 "register_operand")
3457                   (match_operand:GPI 2 "aarch64_plus_immediate")))
3458    (set (reg:CC CC_REGNUM)
3459         (compare:CC
3460           (match_dup 1)
3461           (match_operand:GPI 3 "const_int_operand")))]
3462   "!reg_overlap_mentioned_p (operands[0], operands[1])
3463    && INTVAL (operands[3]) == -INTVAL (operands[2])"
3464   [(const_int 0)]
3465   {
3466     emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3467                                          operands[3], operands[2]));
3468     DONE;
3469   }
3472 ;; Same as the above peephole but with the compare and minus in
3473 ;; swapped order.  The restriction on overlap between operand 0
3474 ;; and operands 1 doesn't apply here.
3475 (define_peephole2
3476   [(set (reg:CC CC_REGNUM)
3477         (compare:CC
3478           (match_operand:GPI 1 "register_operand")
3479           (match_operand:GPI 3 "const_int_operand")))
3480    (set (match_operand:GPI 0 "aarch64_general_reg")
3481         (plus:GPI (match_dup 1)
3482                   (match_operand:GPI 2 "aarch64_plus_immediate")))]
3483   "INTVAL (operands[3]) == -INTVAL (operands[2])"
3484   [(const_int 0)]
3485   {
3486     emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3487                                          operands[3], operands[2]));
3488     DONE;
3489   }
3492 (define_insn "*sub_<shift>_<mode>"
3493   [(set (match_operand:GPI 0 "register_operand" "=r")
3494         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3495                    (ASHIFT:GPI
3496                     (match_operand:GPI 1 "register_operand" "r")
3497                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3498   ""
3499   "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
3500   [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3503 ;; zero_extend version of above
3504 (define_insn "*sub_<shift>_si_uxtw"
3505   [(set (match_operand:DI 0 "register_operand" "=r")
3506         (zero_extend:DI
3507          (minus:SI (match_operand:SI 3 "register_operand" "r")
3508                    (ASHIFT:SI
3509                     (match_operand:SI 1 "register_operand" "r")
3510                     (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
3511   ""
3512   "sub\\t%w0, %w3, %w1, <shift> %2"
3513   [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3516 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
3517   [(set (match_operand:GPI 0 "register_operand" "=rk")
3518         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3519                    (ANY_EXTEND:GPI
3520                     (match_operand:ALLX 2 "register_operand" "r"))))]
3521   ""
3522   "sub\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size>"
3523   [(set_attr "type" "alu_ext")]
3526 ;; zero_extend version of above
3527 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
3528   [(set (match_operand:DI 0 "register_operand" "=rk")
3529         (zero_extend:DI
3530          (minus:SI (match_operand:SI 1 "register_operand" "rk")
3531                    (ANY_EXTEND:SI
3532                     (match_operand:SHORT 2 "register_operand" "r")))))]
3533   ""
3534   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
3535   [(set_attr "type" "alu_ext")]
3538 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
3539   [(set (match_operand:GPI 0 "register_operand" "=rk")
3540         (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3541                    (ashift:GPI (ANY_EXTEND:GPI
3542                                 (match_operand:ALLX 2 "register_operand" "r"))
3543                                (match_operand 3 "aarch64_imm3" "Ui3"))))]
3544   ""
3545   "sub\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size> %3"
3546   [(set_attr "type" "alu_ext")]
3549 ;; zero_extend version of above
3550 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
3551   [(set (match_operand:DI 0 "register_operand" "=rk")
3552         (zero_extend:DI
3553          (minus:SI (match_operand:SI 1 "register_operand" "rk")
3554                    (ashift:SI (ANY_EXTEND:SI
3555                                (match_operand:SHORT 2 "register_operand" "r"))
3556                               (match_operand 3 "aarch64_imm3" "Ui3")))))]
3557   ""
3558   "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
3559   [(set_attr "type" "alu_ext")]
3562 ;; The hardware description is op1 + ~op2 + C.
3563 ;;                           = op1 + (-op2 + 1) + (1 - !C)
3564 ;;                           = op1 - op2 - 1 + 1 - !C
3565 ;;                           = op1 - op2 - !C.
3566 ;; We describe the latter.
3568 (define_insn "*sub<mode>3_carryin0"
3569   [(set (match_operand:GPI 0 "register_operand" "=r")
3570         (minus:GPI
3571           (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3572           (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
3573    ""
3574    "sbc\\t%<w>0, %<w>1, <w>zr"
3575   [(set_attr "type" "adc_reg")]
3578 ;; zero_extend version of the above
3579 (define_insn "*subsi3_carryin_uxtw"
3580   [(set (match_operand:DI 0 "register_operand" "=r")
3581         (zero_extend:DI
3582           (minus:SI
3583             (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3584             (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
3585    ""
3586    "sbc\\t%w0, %w1, wzr"
3587   [(set_attr "type" "adc_reg")]
3590 (define_expand "sub<mode>3_carryin"
3591   [(set (match_operand:GPI 0 "register_operand")
3592         (minus:GPI
3593           (minus:GPI
3594             (match_operand:GPI 1 "aarch64_reg_or_zero")
3595             (match_operand:GPI 2 "register_operand"))
3596           (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
3597    ""
3598    ""
3601 (define_insn "*sub<mode>3_carryin"
3602   [(set (match_operand:GPI 0 "register_operand" "=r")
3603         (minus:GPI
3604           (minus:GPI
3605             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3606             (match_operand:GPI 2 "register_operand" "r"))
3607           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3609    ""
3610    "sbc\\t%<w>0, %<w>1, %<w>2"
3611   [(set_attr "type" "adc_reg")]
3614 ;; zero_extend version of the above
3615 (define_insn "*subsi3_carryin_uxtw"
3616   [(set (match_operand:DI 0 "register_operand" "=r")
3617         (zero_extend:DI
3618           (minus:SI
3619             (minus:SI
3620               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3621               (match_operand:SI 2 "register_operand" "r"))
3622             (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
3624    ""
3625    "sbc\\t%w0, %w1, %w2"
3626   [(set_attr "type" "adc_reg")]
3629 (define_insn "*sub<mode>3_carryin_alt"
3630   [(set (match_operand:GPI 0 "register_operand" "=r")
3631         (minus:GPI
3632           (minus:GPI
3633             (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3634             (match_operand:GPI 3 "aarch64_borrow_operation" ""))
3635           (match_operand:GPI 2 "register_operand" "r")))]
3636    ""
3637    "sbc\\t%<w>0, %<w>1, %<w>2"
3638   [(set_attr "type" "adc_reg")]
3641 ;; zero_extend version of the above
3642 (define_insn "*subsi3_carryin_alt_uxtw"
3643   [(set (match_operand:DI 0 "register_operand" "=r")
3644         (zero_extend:DI
3645           (minus:SI
3646             (minus:SI
3647               (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3648               (match_operand:SI 3 "aarch64_borrow_operation" ""))
3649             (match_operand:SI 2 "register_operand" "r"))))]
3650    ""
3651    "sbc\\t%w0, %w1, %w2"
3652   [(set_attr "type" "adc_reg")]
3655 (define_expand "usub<GPI:mode>3_carryinC"
3656   [(parallel
3657      [(set (reg:CC CC_REGNUM)
3658            (compare:CC
3659              (zero_extend:<DWI>
3660                (match_operand:GPI 1 "aarch64_reg_or_zero"))
3661              (plus:<DWI>
3662                (zero_extend:<DWI>
3663                  (match_operand:GPI 2 "register_operand"))
3664                (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0)))))
3665       (set (match_operand:GPI 0 "register_operand")
3666            (minus:GPI
3667              (minus:GPI (match_dup 1) (match_dup 2))
3668              (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3669    ""
3672 (define_insn "*usub<GPI:mode>3_carryinC_z1"
3673   [(set (reg:CC CC_REGNUM)
3674         (compare:CC
3675           (const_int 0)
3676           (plus:<DWI>
3677             (zero_extend:<DWI>
3678               (match_operand:GPI 1 "register_operand" "r"))
3679             (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))))
3680    (set (match_operand:GPI 0 "register_operand" "=r")
3681         (minus:GPI
3682           (neg:GPI (match_dup 1))
3683           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3684    ""
3685    "sbcs\\t%<w>0, <w>zr, %<w>1"
3686   [(set_attr "type" "adc_reg")]
3689 (define_insn "*usub<GPI:mode>3_carryinC_z2"
3690   [(set (reg:CC CC_REGNUM)
3691         (compare:CC
3692           (zero_extend:<DWI>
3693             (match_operand:GPI 1 "register_operand" "r"))
3694           (match_operand:<DWI> 2 "aarch64_borrow_operation" "")))
3695    (set (match_operand:GPI 0 "register_operand" "=r")
3696         (minus:GPI
3697           (match_dup 1)
3698           (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3699    ""
3700    "sbcs\\t%<w>0, %<w>1, <w>zr"
3701   [(set_attr "type" "adc_reg")]
3704 (define_insn "*usub<GPI:mode>3_carryinC"
3705   [(set (reg:CC CC_REGNUM)
3706         (compare:CC
3707           (zero_extend:<DWI>
3708             (match_operand:GPI 1 "register_operand" "r"))
3709           (plus:<DWI>
3710             (zero_extend:<DWI>
3711               (match_operand:GPI 2 "register_operand" "r"))
3712             (match_operand:<DWI> 3 "aarch64_borrow_operation" ""))))
3713    (set (match_operand:GPI 0 "register_operand" "=r")
3714         (minus:GPI
3715           (minus:GPI (match_dup 1) (match_dup 2))
3716           (match_operand:GPI 4 "aarch64_borrow_operation" "")))]
3717    ""
3718    "sbcs\\t%<w>0, %<w>1, %<w>2"
3719   [(set_attr "type" "adc_reg")]
3722 (define_expand "sub<GPI:mode>3_carryinV"
3723   [(parallel
3724      [(set (reg:CC_V CC_REGNUM)
3725            (compare:CC_V
3726             (minus:<DWI>
3727              (sign_extend:<DWI>
3728                (match_operand:GPI 1 "aarch64_reg_or_zero"))
3729              (plus:<DWI>
3730                (sign_extend:<DWI>
3731                  (match_operand:GPI 2 "register_operand"))
3732                (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0))))
3733             (sign_extend:<DWI>
3734              (minus:GPI (match_dup 1)
3735                         (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))
3736                                   (match_dup 2))))))
3737       (set (match_operand:GPI 0 "register_operand")
3738            (minus:GPI
3739              (minus:GPI (match_dup 1) (match_dup 2))
3740              (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3741    ""
3744 (define_insn "*sub<mode>3_carryinV_z2"
3745   [(set (reg:CC_V CC_REGNUM)
3746         (compare:CC_V
3747          (minus:<DWI>
3748           (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
3749           (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))
3750          (sign_extend:<DWI>
3751           (minus:GPI (match_dup 1)
3752                      (match_operand:GPI 3 "aarch64_borrow_operation" "")))))
3753    (set (match_operand:GPI 0 "register_operand" "=r")
3754         (minus:GPI
3755          (match_dup 1) (match_dup 3)))]
3756    ""
3757    "sbcs\\t%<w>0, %<w>1, <w>zr"
3758   [(set_attr "type" "adc_reg")]
3761 (define_insn "*sub<mode>3_carryinV"
3762   [(set (reg:CC_V CC_REGNUM)
3763         (compare:CC_V
3764          (minus:<DWI>
3765           (sign_extend:<DWI>
3766             (match_operand:GPI 1 "register_operand" "r"))
3767           (plus:<DWI>
3768             (sign_extend:<DWI>
3769               (match_operand:GPI 2 "register_operand" "r"))
3770             (match_operand:<DWI> 3 "aarch64_borrow_operation" "")))
3771          (sign_extend:<DWI>
3772           (minus:GPI
3773            (match_dup 1)
3774            (plus:GPI (match_operand:GPI 4 "aarch64_borrow_operation" "")
3775                      (match_dup 2))))))
3776    (set (match_operand:GPI 0 "register_operand" "=r")
3777         (minus:GPI
3778           (minus:GPI (match_dup 1) (match_dup 2))
3779           (match_dup 4)))]
3780    ""
3781    "sbcs\\t%<w>0, %<w>1, %<w>2"
3782   [(set_attr "type" "adc_reg")]
3785 (define_insn "*sub_uxt<mode>_shift2"
3786   [(set (match_operand:GPI 0 "register_operand" "=rk")
3787         (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
3788                    (and:GPI
3789                     (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3790                                 (match_operand 2 "aarch64_imm3" "Ui3"))
3791                     (match_operand 3 "const_int_operand" "n"))))]
3792   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
3793   "*
3794   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3795                                            INTVAL (operands[3])));
3796   return \"sub\t%<w>0, %<w>4, %w1, uxt%e3 %2\";"
3797   [(set_attr "type" "alu_ext")]
3800 ;; zero_extend version of above
3801 (define_insn "*sub_uxtsi_shift2_uxtw"
3802   [(set (match_operand:DI 0 "register_operand" "=rk")
3803         (zero_extend:DI
3804          (minus:SI (match_operand:SI 4 "register_operand" "rk")
3805                    (and:SI
3806                     (ashift:SI (match_operand:SI 1 "register_operand" "r")
3807                                (match_operand 2 "aarch64_imm3" "Ui3"))
3808                     (match_operand 3 "const_int_operand" "n")))))]
3809   "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
3810   "*
3811   operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3812                                            INTVAL (operands[3])));
3813   return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
3814   [(set_attr "type" "alu_ext")]
3817 (define_insn "*aarch64_abs<mode>2_cssc_insn"
3818   [(set (match_operand:GPI 0 "register_operand" "=r")
3819         (abs:GPI (match_operand:GPI 1 "register_operand" "r")))]
3820   "TARGET_CSSC"
3821   "abs\\t%<w>0, %<w>1"
3822   [(set_attr "type" "alu_sreg")]
3825 (define_expand "abs<mode>2"
3826   [(set (match_operand:GPI 0 "register_operand")
3827         (abs:GPI (match_operand:GPI 1 "register_operand")))]
3828   ""
3829   {
3830     if (!TARGET_CSSC)
3831       {
3832         rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
3833         rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3834         emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
3835         DONE;
3836       }
3837   }
3840 (define_insn "neg<mode>2"
3841   [(set (match_operand:GPI 0 "register_operand")
3842         (neg:GPI (match_operand:GPI 1 "register_operand")))]
3843   ""
3844   {@ [ cons: =0 , 1 ; attrs: type , arch  ]
3845      [ r        , r ; alu_sreg    , *     ] neg\t%<w>0, %<w>1
3846      [ w        , w ; neon_neg<q> , simd  ] neg\t%<rtn>0<vas>, %<rtn>1<vas>
3847   }
3850 ;; zero_extend version of above
3851 (define_insn "*negsi2_uxtw"
3852   [(set (match_operand:DI 0 "register_operand" "=r")
3853         (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
3854   ""
3855   "neg\\t%w0, %w1"
3856   [(set_attr "type" "alu_sreg")]
3859 (define_insn "*ngc<mode>"
3860   [(set (match_operand:GPI 0 "register_operand" "=r")
3861         (minus:GPI
3862           (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
3863           (match_operand:GPI 1 "register_operand" "r")))]
3864   ""
3865   "ngc\\t%<w>0, %<w>1"
3866   [(set_attr "type" "adc_reg")]
3869 (define_insn "*ngcsi_uxtw"
3870   [(set (match_operand:DI 0 "register_operand" "=r")
3871         (zero_extend:DI
3872           (minus:SI
3873             (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
3874             (match_operand:SI 1 "register_operand" "r"))))]
3875   ""
3876   "ngc\\t%w0, %w1"
3877   [(set_attr "type" "adc_reg")]
3880 (define_insn "neg<mode>2_compare0"
3881   [(set (reg:CC_NZ CC_REGNUM)
3882         (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
3883                        (const_int 0)))
3884    (set (match_operand:GPI 0 "register_operand" "=r")
3885         (neg:GPI (match_dup 1)))]
3886   ""
3887   "negs\\t%<w>0, %<w>1"
3888   [(set_attr "type" "alus_sreg")]
3891 ;; zero_extend version of above
3892 (define_insn "*negsi2_compare0_uxtw"
3893   [(set (reg:CC_NZ CC_REGNUM)
3894         (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
3895                        (const_int 0)))
3896    (set (match_operand:DI 0 "register_operand" "=r")
3897         (zero_extend:DI (neg:SI (match_dup 1))))]
3898   ""
3899   "negs\\t%w0, %w1"
3900   [(set_attr "type" "alus_sreg")]
3903 (define_insn "*neg_<shift><mode>3_compare0"
3904   [(set (reg:CC_NZ CC_REGNUM)
3905         (compare:CC_NZ
3906          (neg:GPI (ASHIFT:GPI
3907                    (match_operand:GPI 1 "register_operand" "r")
3908                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3909          (const_int 0)))
3910    (set (match_operand:GPI 0 "register_operand" "=r")
3911         (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
3912   ""
3913   "negs\\t%<w>0, %<w>1, <shift> %2"
3914   [(set_attr "type" "alus_shift_imm")]
3917 (define_insn "*neg_<shift>_<mode>2"
3918   [(set (match_operand:GPI 0 "register_operand" "=r")
3919         (neg:GPI (ASHIFT:GPI
3920                   (match_operand:GPI 1 "register_operand" "r")
3921                   (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3922   ""
3923   "neg\\t%<w>0, %<w>1, <shift> %2"
3924   [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3927 ;; zero_extend version of above
3928 (define_insn "*neg_<shift>_si2_uxtw"
3929   [(set (match_operand:DI 0 "register_operand" "=r")
3930         (zero_extend:DI
3931          (neg:SI (ASHIFT:SI
3932                   (match_operand:SI 1 "register_operand" "r")
3933                   (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
3934   ""
3935   "neg\\t%w0, %w1, <shift> %2"
3936   [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3939 (define_insn "*neg_asr_si2_extr"
3940   [(set (match_operand:SI 0 "register_operand" "=r")
3941         (neg:SI (match_operator:SI 4 "subreg_lowpart_operator"
3942                   [(sign_extract:DI
3943                      (match_operand:DI 1 "register_operand" "r")
3944                      (match_operand 3 "aarch64_simd_shift_imm_offset_si" "n")
3945                      (match_operand 2 "aarch64_simd_shift_imm_offset_si" "n"))])))]
3946   "INTVAL (operands[2]) + INTVAL (operands[3]) == 32"
3947   "neg\\t%w0, %w1, asr %2"
3948   [(set_attr "autodetect_type" "alu_shift_asr_op2")]
3951 (define_insn "mul<mode>3"
3952   [(set (match_operand:GPI 0 "register_operand" "=r")
3953         (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3954                   (match_operand:GPI 2 "register_operand" "r")))]
3955   ""
3956   "mul\\t%<w>0, %<w>1, %<w>2"
3957   [(set_attr "type" "mul")]
3960 ;; zero_extend version of above
3961 (define_insn "*mulsi3_uxtw"
3962   [(set (match_operand:DI 0 "register_operand" "=r")
3963         (zero_extend:DI
3964          (mult:SI (match_operand:SI 1 "register_operand" "r")
3965                   (match_operand:SI 2 "register_operand" "r"))))]
3966   ""
3967   "mul\\t%w0, %w1, %w2"
3968   [(set_attr "type" "mul")]
3971 (define_insn "madd<mode>"
3972   [(set (match_operand:GPI 0 "register_operand" "=r")
3973         (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3974                             (match_operand:GPI 2 "register_operand" "r"))
3975                   (match_operand:GPI 3 "register_operand" "r")))]
3976   ""
3977   "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
3978   [(set_attr "type" "mla")]
3981 ;; zero_extend version of above
3982 (define_insn "*maddsi_uxtw"
3983   [(set (match_operand:DI 0 "register_operand" "=r")
3984         (zero_extend:DI
3985          (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
3986                            (match_operand:SI 2 "register_operand" "r"))
3987                   (match_operand:SI 3 "register_operand" "r"))))]
3988   ""
3989   "madd\\t%w0, %w1, %w2, %w3"
3990   [(set_attr "type" "mla")]
3993 (define_insn "*msub<mode>"
3994   [(set (match_operand:GPI 0 "register_operand" "=r")
3995         (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3996                    (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3997                              (match_operand:GPI 2 "register_operand" "r"))))]
3999   ""
4000   "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
4001   [(set_attr "type" "mla")]
4004 ;; zero_extend version of above
4005 (define_insn "*msubsi_uxtw"
4006   [(set (match_operand:DI 0 "register_operand" "=r")
4007         (zero_extend:DI
4008          (minus:SI (match_operand:SI 3 "register_operand" "r")
4009                    (mult:SI (match_operand:SI 1 "register_operand" "r")
4010                             (match_operand:SI 2 "register_operand" "r")))))]
4012   ""
4013   "msub\\t%w0, %w1, %w2, %w3"
4014   [(set_attr "type" "mla")]
4017 (define_insn "*mul<mode>_neg"
4018   [(set (match_operand:GPI 0 "register_operand" "=r")
4019         (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
4020                   (match_operand:GPI 2 "register_operand" "r")))]
4022   ""
4023   "mneg\\t%<w>0, %<w>1, %<w>2"
4024   [(set_attr "type" "mul")]
4027 ;; zero_extend version of above
4028 (define_insn "*mulsi_neg_uxtw"
4029   [(set (match_operand:DI 0 "register_operand" "=r")
4030         (zero_extend:DI
4031          (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
4032                   (match_operand:SI 2 "register_operand" "r"))))]
4034   ""
4035   "mneg\\t%w0, %w1, %w2"
4036   [(set_attr "type" "mul")]
4039 (define_insn "<su_optab>mulsidi3"
4040   [(set (match_operand:DI 0 "register_operand" "=r")
4041         (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
4042                  (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
4043   ""
4044   "<su>mull\\t%0, %w1, %w2"
4045   [(set_attr "type" "<su>mull")]
4048 (define_insn "<su_optab>maddsidi4"
4049   [(set (match_operand:DI 0 "register_operand" "=r")
4050         (plus:DI (mult:DI
4051                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
4052                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
4053                  (match_operand:DI 3 "register_operand" "r")))]
4054   ""
4055   "<su>maddl\\t%0, %w1, %w2, %3"
4056   [(set_attr "type" "<su>mlal")]
4059 (define_insn "<su_optab>msubsidi4"
4060   [(set (match_operand:DI 0 "register_operand" "=r")
4061         (minus:DI
4062          (match_operand:DI 3 "register_operand" "r")
4063          (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
4064                   (ANY_EXTEND:DI
4065                    (match_operand:SI 2 "register_operand" "r")))))]
4066   ""
4067   "<su>msubl\\t%0, %w1, %w2, %3"
4068   [(set_attr "type" "<su>mlal")]
4071 (define_insn "*<su_optab>mulsidi_neg"
4072   [(set (match_operand:DI 0 "register_operand" "=r")
4073         (mult:DI (neg:DI
4074                   (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
4075                   (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
4076   ""
4077   "<su>mnegl\\t%0, %w1, %w2"
4078   [(set_attr "type" "<su>mull")]
4081 (define_expand "<su_optab>mulditi3"
4082   [(set (match_operand:TI 0 "register_operand")
4083         (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
4084                  (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
4085   ""
4087   rtx low = gen_reg_rtx (DImode);
4088   emit_insn (gen_muldi3 (low, operands[1], operands[2]));
4090   rtx high = gen_reg_rtx (DImode);
4091   emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
4093   emit_move_insn (gen_lowpart (DImode, operands[0]), low);
4094   emit_move_insn (gen_highpart (DImode, operands[0]), high);
4095   DONE;
4098 ;; The default expansion of multi3 using umuldi3_highpart will perform
4099 ;; the additions in an order that fails to combine into two madd insns.
4100 (define_expand "multi3"
4101   [(set (match_operand:TI 0 "register_operand")
4102         (mult:TI (match_operand:TI 1 "register_operand")
4103                  (match_operand:TI 2 "register_operand")))]
4104   ""
4106   rtx l0 = gen_reg_rtx (DImode);
4107   rtx l1 = gen_lowpart (DImode, operands[1]);
4108   rtx l2 = gen_lowpart (DImode, operands[2]);
4109   rtx h0 = gen_reg_rtx (DImode);
4110   rtx h1 = gen_highpart (DImode, operands[1]);
4111   rtx h2 = gen_highpart (DImode, operands[2]);
4113   emit_insn (gen_muldi3 (l0, l1, l2));
4114   emit_insn (gen_umuldi3_highpart (h0, l1, l2));
4115   emit_insn (gen_madddi (h0, h1, l2, h0));
4116   emit_insn (gen_madddi (h0, l1, h2, h0));
4118   emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
4119   emit_move_insn (gen_highpart (DImode, operands[0]), h0);
4120   DONE;
4123 (define_insn "<su>muldi3_highpart"
4124   [(set (match_operand:DI 0 "register_operand" "=r")
4125         (truncate:DI
4126          (lshiftrt:TI
4127           (mult:TI
4128            (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
4129            (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
4130           (const_int 64))))]
4131   ""
4132   "<su>mulh\\t%0, %1, %2"
4133   [(set_attr "type" "<su>mull")]
4136 (define_insn "<su_optab>div<mode>3"
4137   [(set (match_operand:GPI 0 "register_operand" "=r")
4138         (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
4139                      (match_operand:GPI 2 "register_operand" "r")))]
4140   ""
4141   "<su>div\\t%<w>0, %<w>1, %<w>2"
4142   [(set_attr "type" "<su>div")]
4145 ;; zero_extend version of above
4146 (define_insn "*<su_optab>divsi3_uxtw"
4147   [(set (match_operand:DI 0 "register_operand" "=r")
4148         (zero_extend:DI
4149          (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
4150                      (match_operand:SI 2 "register_operand" "r"))))]
4151   ""
4152   "<su>div\\t%w0, %w1, %w2"
4153   [(set_attr "type" "<su>div")]
4156 ;; -------------------------------------------------------------------
4157 ;; Comparison insns
4158 ;; -------------------------------------------------------------------
4160 (define_insn "cmp<mode>"
4161   [(set (reg:CC CC_REGNUM)
4162         (compare:CC (match_operand:GPI 0 "register_operand")
4163                     (match_operand:GPI 1 "aarch64_plus_operand")))]
4164   ""
4165   {@ [ cons: 0 , 1 ; attrs: type ]
4166      [ rk      , r ; alus_sreg   ] cmp\t%<w>0, %<w>1
4167      [ rk      , I ; alus_imm    ] cmp\t%<w>0, %1
4168      [ rk      , J ; alus_imm    ] cmn\t%<w>0, #%n1
4169   }
4172 (define_insn "fcmp<mode>"
4173   [(set (reg:CCFP CC_REGNUM)
4174         (compare:CCFP (match_operand:GPF 0 "register_operand")
4175                       (match_operand:GPF 1 "aarch64_fp_compare_operand")))]
4176    "TARGET_FLOAT"
4177    {@ [ cons: 0 , 1  ]
4178       [ w       , Y  ] fcmp\t%<s>0, #0.0
4179       [ w       , w  ] fcmp\t%<s>0, %<s>1
4180   }
4181   [(set_attr "type" "fcmp<s>")]
4184 (define_insn "fcmpe<mode>"
4185   [(set (reg:CCFPE CC_REGNUM)
4186         (compare:CCFPE (match_operand:GPF 0 "register_operand")
4187                        (match_operand:GPF 1 "aarch64_fp_compare_operand")))]
4188    "TARGET_FLOAT"
4189    {@ [ cons: 0 , 1  ]
4190       [ w       , Y  ] fcmpe\t%<s>0, #0.0
4191       [ w       , w  ] fcmpe\t%<s>0, %<s>1
4192   }
4193   [(set_attr "type" "fcmp<s>")]
4196 (define_insn "*cmp_swp_<shift>_reg<mode>"
4197   [(set (reg:CC_SWP CC_REGNUM)
4198         (compare:CC_SWP (ASHIFT:GPI
4199                          (match_operand:GPI 0 "register_operand" "r")
4200                          (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
4201                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
4202   ""
4203   "cmp\\t%<w>2, %<w>0, <shift> %1"
4204   [(set_attr "type" "alus_shift_imm")]
4207 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
4208   [(set (reg:CC_SWP CC_REGNUM)
4209         (compare:CC_SWP (ANY_EXTEND:GPI
4210                          (match_operand:ALLX 0 "register_operand" "r"))
4211                         (match_operand:GPI 1 "register_operand" "r")))]
4212   ""
4213   "cmp\\t%<GPI:w>1, %w0, <su>xt<ALLX:size>"
4214   [(set_attr "type" "alus_ext")]
4217 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
4218   [(set (reg:CC_SWP CC_REGNUM)
4219         (compare:CC_SWP (ashift:GPI
4220                          (ANY_EXTEND:GPI
4221                           (match_operand:ALLX 0 "register_operand" "r"))
4222                          (match_operand 1 "aarch64_imm3" "Ui3"))
4223         (match_operand:GPI 2 "register_operand" "r")))]
4224   ""
4225   "cmp\\t%<GPI:w>2, %w0, <su>xt<ALLX:size> %1"
4226   [(set_attr "type" "alus_ext")]
4229 ;; -------------------------------------------------------------------
4230 ;; Store-flag and conditional select insns
4231 ;; -------------------------------------------------------------------
4233 (define_expand "cstore<mode>4"
4234   [(set (match_operand:SI 0 "register_operand")
4235         (match_operator:SI 1 "aarch64_comparison_operator"
4236          [(match_operand:GPI 2 "register_operand")
4237           (match_operand:GPI 3 "aarch64_plus_operand")]))]
4238   ""
4239   "
4240   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4241                                       operands[3]);
4242   operands[3] = const0_rtx;
4243   "
4246 (define_expand "cstorecc4"
4247   [(set (match_operand:SI 0 "register_operand")
4248        (match_operator 1 "aarch64_comparison_operator_mode"
4249         [(match_operand 2 "cc_register")
4250          (match_operand 3 "const0_operand")]))]
4251   ""
4253   emit_insn (gen_rtx_SET (operands[0], operands[1]));
4254   DONE;
4258 (define_expand "cstore<mode>4"
4259   [(set (match_operand:SI 0 "register_operand")
4260         (match_operator:SI 1 "aarch64_comparison_operator_mode"
4261          [(match_operand:GPF 2 "register_operand")
4262           (match_operand:GPF 3 "aarch64_fp_compare_operand")]))]
4263   ""
4264   "
4265   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4266                                       operands[3]);
4267   operands[3] = const0_rtx;
4268   "
4271 (define_insn "aarch64_cstore<mode>"
4272   [(set (match_operand:ALLI 0 "register_operand" "=r")
4273         (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
4274          [(match_operand 2 "cc_register" "") (const_int 0)]))]
4275   ""
4276   "cset\\t%<w>0, %m1"
4277   [(set_attr "type" "csel")]
4280 ;; For a 24-bit immediate CST we can optimize the compare for equality
4281 ;; and branch sequence from:
4282 ;;      mov     x0, #imm1
4283 ;;      movk    x0, #imm2, lsl 16 /* x0 contains CST.  */
4284 ;;      cmp     x1, x0
4285 ;;      cset    x2, <ne,eq>
4286 ;; into the shorter:
4287 ;;      sub     x0, x1, #(CST & 0xfff000)
4288 ;;      subs    x0, x0, #(CST & 0x000fff)
4289 ;;      cset x2, <ne, eq>.
4290 (define_insn_and_split "*compare_cstore<mode>_insn"
4291   [(set (match_operand:GPI 0 "register_operand" "=r")
4292          (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
4293                   (match_operand:GPI 2 "aarch64_imm24" "n")))
4294    (clobber (reg:CC CC_REGNUM))]
4295   "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
4296    && !aarch64_plus_operand (operands[2], <MODE>mode)
4297    && !reload_completed"
4298   "#"
4299   "&& true"
4300   [(const_int 0)]
4301   {
4302     HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
4303     HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
4304     rtx tmp = gen_reg_rtx (<MODE>mode);
4305     emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
4306     emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
4307     rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
4308     rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
4309     emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
4310     DONE;
4311   }
4312   [(set_attr "type" "csel")]
4315 ;; zero_extend version of the above
4316 (define_insn "*cstoresi_insn_uxtw"
4317   [(set (match_operand:DI 0 "register_operand" "=r")
4318         (zero_extend:DI
4319          (match_operator:SI 1 "aarch64_comparison_operator_mode"
4320           [(match_operand 2 "cc_register" "") (const_int 0)])))]
4321   ""
4322   "cset\\t%w0, %m1"
4323   [(set_attr "type" "csel")]
4326 (define_insn "cstore<mode>_neg"
4327   [(set (match_operand:ALLI 0 "register_operand" "=r")
4328         (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
4329                   [(match_operand 2 "cc_register" "") (const_int 0)])))]
4330   ""
4331   "csetm\\t%<w>0, %m1"
4332   [(set_attr "type" "csel")]
4335 ;; zero_extend version of the above
4336 (define_insn "*cstoresi_neg_uxtw"
4337   [(set (match_operand:DI 0 "register_operand" "=r")
4338         (zero_extend:DI
4339          (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
4340                   [(match_operand 2 "cc_register" "") (const_int 0)]))))]
4341   ""
4342   "csetm\\t%w0, %m1"
4343   [(set_attr "type" "csel")]
4346 (define_expand "cmov<mode>6"
4347   [(set (match_operand:GPI 0 "register_operand")
4348         (if_then_else:GPI
4349          (match_operator 1 "aarch64_comparison_operator"
4350           [(match_operand:GPI 2 "register_operand")
4351            (match_operand:GPI 3 "aarch64_plus_operand")])
4352          (match_operand:GPI 4 "register_operand")
4353          (match_operand:GPI 5 "register_operand")))]
4354   ""
4355   "
4356   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4357                                       operands[3]);
4358   operands[3] = const0_rtx;
4359   "
4362 (define_expand "cmov<mode>6"
4363   [(set (match_operand:GPF 0 "register_operand")
4364         (if_then_else:GPF
4365          (match_operator 1 "aarch64_comparison_operator"
4366           [(match_operand:GPF 2 "register_operand")
4367            (match_operand:GPF 3 "aarch64_fp_compare_operand")])
4368          (match_operand:GPF 4 "register_operand")
4369          (match_operand:GPF 5 "register_operand")))]
4370   ""
4371   "
4372   operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4373                                       operands[3]);
4374   operands[3] = const0_rtx;
4375   "
4378 (define_insn "*cmov<mode>_insn"
4379   [(set (match_operand:ALLI 0 "register_operand")
4380         (if_then_else:ALLI
4381          (match_operator 1 "aarch64_comparison_operator"
4382           [(match_operand 2 "cc_register") (const_int 0)])
4383          (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1")
4384          (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1")))]
4385   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
4386      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
4387   ;; Final two alternatives should be unreachable, but included for completeness
4388   {@ [ cons: =0 , 3   , 4   ; attrs: type ]
4389      [ r        , rZ  , rZ  ; csel        ] csel\t%<w>0, %<w>3, %<w>4, %m1
4390      [ r        , rZ  , UsM ; csel        ] csinv\t%<w>0, %<w>3, <w>zr, %m1
4391      [ r        , UsM , rZ  ; csel        ] csinv\t%<w>0, %<w>4, <w>zr, %M1
4392      [ r        , rZ  , Ui1 ; csel        ] csinc\t%<w>0, %<w>3, <w>zr, %m1
4393      [ r        , Ui1 , rZ  ; csel        ] csinc\t%<w>0, %<w>4, <w>zr, %M1
4394      [ r        , UsM , UsM ; mov_imm     ] mov\t%<w>0, -1
4395      [ r        , Ui1 , Ui1 ; mov_imm     ] mov\t%<w>0, 1
4396   }
4399 ;; zero_extend version of above
4400 (define_insn "*cmovsi_insn_uxtw"
4401   [(set (match_operand:DI 0 "register_operand")
4402         (zero_extend:DI
4403          (if_then_else:SI
4404           (match_operator 1 "aarch64_comparison_operator"
4405            [(match_operand 2 "cc_register") (const_int 0)])
4406           (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1")
4407           (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1"))))]
4408   "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
4409      || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
4410   ;; Final two alternatives should be unreachable, but included for completeness
4411   {@ [ cons: =0 , 3   , 4   ; attrs: type ]
4412      [ r        , rZ  , rZ  ; csel        ] csel\t%w0, %w3, %w4, %m1
4413      [ r        , rZ  , UsM ; csel        ] csinv\t%w0, %w3, wzr, %m1
4414      [ r        , UsM , rZ  ; csel        ] csinv\t%w0, %w4, wzr, %M1
4415      [ r        , rZ  , Ui1 ; csel        ] csinc\t%w0, %w3, wzr, %m1
4416      [ r        , Ui1 , rZ  ; csel        ] csinc\t%w0, %w4, wzr, %M1
4417      [ r        , UsM , UsM ; mov_imm     ] mov\t%w0, -1
4418      [ r        , Ui1 , Ui1 ; mov_imm     ] mov\t%w0, 1
4419   }
4422 ;; There are two canonical forms for `cmp ? -1 : a`.
4423 ;; This is the second form and is here to help combine.
4424 ;; Support `-(cmp) | a` into `cmp ? -1 : a` to be canonical in the backend.
4425 (define_insn_and_split "*cmov<mode>_insn_m1"
4426   [(set (match_operand:GPI 0 "register_operand" "=r")
4427         (ior:GPI
4428          (neg:GPI
4429           (match_operator:GPI 1 "aarch64_comparison_operator"
4430            [(match_operand 2 "cc_register" "") (const_int 0)]))
4431          (match_operand 3 "register_operand" "r")))]
4432   ""
4433   "#"
4434   "&& true"
4435   [(set (match_dup 0)
4436         (if_then_else:GPI (match_dup 1)
4437                           (const_int -1)
4438                           (match_dup 3)))]
4439   {}
4440   [(set_attr "type" "csel")]
4443 (define_insn "*cmovdi_insn_uxtw"
4444   [(set (match_operand:DI 0 "register_operand" "=r")
4445         (if_then_else:DI
4446          (match_operator 1 "aarch64_comparison_operator"
4447           [(match_operand 2 "cc_register" "") (const_int 0)])
4448          (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
4449          (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
4450   ""
4451   "csel\\t%w0, %w3, %w4, %m1"
4452   [(set_attr "type" "csel")]
4455 (define_insn "*cmov<mode>_insn"
4456   [(set (match_operand:GPF 0 "register_operand" "=w")
4457         (if_then_else:GPF
4458          (match_operator 1 "aarch64_comparison_operator"
4459           [(match_operand 2 "cc_register" "") (const_int 0)])
4460          (match_operand:GPF 3 "register_operand" "w")
4461          (match_operand:GPF 4 "register_operand" "w")))]
4462   "TARGET_FLOAT"
4463   "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
4464   [(set_attr "type" "fcsel")]
4467 (define_expand "mov<mode>cc"
4468   [(set (match_operand:ALLI 0 "register_operand")
4469         (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator")
4470                            (match_operand:ALLI 2 "register_operand")
4471                            (match_operand:ALLI 3 "register_operand")))]
4472   ""
4473   {
4474     rtx ccreg;
4475     enum rtx_code code = GET_CODE (operands[1]);
4477     if (code == UNEQ || code == LTGT)
4478       FAIL;
4480     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4481                                      XEXP (operands[1], 1));
4482     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4483   }
4486 (define_expand "mov<GPF:mode><GPI:mode>cc"
4487   [(set (match_operand:GPI 0 "register_operand")
4488         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator")
4489                           (match_operand:GPF 2 "register_operand")
4490                           (match_operand:GPF 3 "register_operand")))]
4491   ""
4492   {
4493     rtx ccreg;
4494     enum rtx_code code = GET_CODE (operands[1]);
4496     if (code == UNEQ || code == LTGT)
4497       FAIL;
4499     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4500                                   XEXP (operands[1], 1));
4501     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4502   }
4505 (define_expand "mov<mode>cc"
4506   [(set (match_operand:GPF 0 "register_operand")
4507         (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator")
4508                           (match_operand:GPF 2 "register_operand")
4509                           (match_operand:GPF 3 "register_operand")))]
4510   ""
4511   {
4512     rtx ccreg;
4513     enum rtx_code code = GET_CODE (operands[1]);
4515     if (code == UNEQ || code == LTGT)
4516       FAIL;
4518     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4519                                   XEXP (operands[1], 1));
4520     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4521   }
4524 (define_expand "<neg_not_op><mode>cc"
4525   [(set (match_operand:GPI 0 "register_operand")
4526         (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator")
4527                           (NEG_NOT:GPI (match_operand:GPI 2 "register_operand"))
4528                           (match_operand:GPI 3 "register_operand")))]
4529   ""
4530   {
4531     rtx ccreg;
4532     enum rtx_code code = GET_CODE (operands[1]);
4534     if (code == UNEQ || code == LTGT)
4535       FAIL;
4537     ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4538                                       XEXP (operands[1], 1));
4539     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4540   }
4543 ;; CRC32 instructions.
4544 (define_insn "aarch64_<crc_variant>"
4545   [(set (match_operand:SI 0 "register_operand" "=r")
4546         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
4547                     (match_operand:<crc_mode> 2 "register_operand" "r")]
4548          CRC))]
4549   "TARGET_CRC32"
4550   {
4551     if (GET_MODE_BITSIZE (<crc_mode>mode) >= 64)
4552       return "<crc_variant>\\t%w0, %w1, %x2";
4553     else
4554       return "<crc_variant>\\t%w0, %w1, %w2";
4555   }
4556   [(set_attr "type" "crc")]
4559 (define_insn "*csinc2<mode>_insn"
4560   [(set (match_operand:GPI 0 "register_operand" "=r")
4561         (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
4562                   (match_operand:GPI 1 "register_operand" "r")))]
4563   ""
4564   "cinc\\t%<w>0, %<w>1, %m2"
4565   [(set_attr "type" "csel")]
4568 (define_insn "csinc3<mode>_insn"
4569   [(set (match_operand:GPI 0 "register_operand" "=r")
4570         (if_then_else:GPI
4571           (match_operand 1 "aarch64_comparison_operation" "")
4572           (plus:GPI (match_operand:GPI 2 "register_operand" "r")
4573                     (const_int 1))
4574           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4575   ""
4576   "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
4577   [(set_attr "type" "csel")]
4580 (define_insn "*csinv3<mode>_insn"
4581   [(set (match_operand:GPI 0 "register_operand" "=r")
4582         (if_then_else:GPI
4583           (match_operand 1 "aarch64_comparison_operation" "")
4584           (not:GPI (match_operand:GPI 2 "register_operand" "r"))
4585           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4586   ""
4587   "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
4588   [(set_attr "type" "csel")]
4591 (define_insn "*cs<neg_not_cs>3_uxtw_insn4"
4592   [(set (match_operand:DI 0 "register_operand" "=r")
4593         (zero_extend:DI
4594           (if_then_else:SI
4595             (match_operand 1 "aarch64_comparison_operation" "")
4596             (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r"))
4597             (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
4598   ""
4599   "cs<neg_not_cs>\\t%w0, %w3, %w2, %M1"
4600   [(set_attr "type" "csel")]
4603 (define_insn "csneg3<mode>_insn"
4604   [(set (match_operand:GPI 0 "register_operand" "=r")
4605         (if_then_else:GPI
4606           (match_operand 1 "aarch64_comparison_operation" "")
4607           (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
4608           (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4609   ""
4610   "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
4611   [(set_attr "type" "csel")]
4614 (define_insn "*csinv3_uxtw_insn1"
4615   [(set (match_operand:DI 0 "register_operand" "=r")
4616         (if_then_else:DI
4617           (match_operand 1 "aarch64_comparison_operation" "")
4618           (zero_extend:DI
4619             (match_operand:SI 2 "register_operand" "r"))
4620           (zero_extend:DI
4621             (NEG_NOT:SI (match_operand:SI 3 "register_operand" "r")))))]
4622   ""
4623   "cs<neg_not_cs>\\t%w0, %w2, %w3, %m1"
4624   [(set_attr "type" "csel")]
4627 (define_insn "*csinv3_uxtw_insn2"
4628   [(set (match_operand:DI 0 "register_operand" "=r")
4629         (if_then_else:DI
4630           (match_operand 1 "aarch64_comparison_operation" "")
4631           (zero_extend:DI
4632             (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
4633           (zero_extend:DI
4634             (match_operand:SI 3 "register_operand" "r"))))]
4635   ""
4636   "cs<neg_not_cs>\\t%w0, %w3, %w2, %M1"
4637   [(set_attr "type" "csel")]
4640 (define_insn "*csinv3_uxtw_insn3"
4641   [(set (match_operand:DI 0 "register_operand" "=r")
4642         (if_then_else:DI
4643           (match_operand 1 "aarch64_comparison_operation" "")
4644           (zero_extend:DI
4645             (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
4646           (const_int 0)))]
4647   ""
4648   "cs<neg_not_cs>\\t%w0, wzr, %w2, %M1"
4649   [(set_attr "type" "csel")]
4652 ;; There are two canonical forms for `cmp ? ~a : a`.
4653 ;; This is the second form and is here to help combine.
4654 ;; Support `-(cmp) ^ a` into `cmp ? ~a : a`
4655 ;; The second pattern is to support the zero extend'ed version.
4657 (define_insn_and_split "*cmov<mode>_insn_insv"
4658   [(set (match_operand:GPI 0 "register_operand" "=r")
4659         (xor:GPI
4660          (neg:GPI
4661           (match_operator:GPI 1 "aarch64_comparison_operator"
4662            [(match_operand 2 "cc_register" "") (const_int 0)]))
4663          (match_operand:GPI 3 "general_operand" "r")))]
4664   ""
4665   "#"
4666   "&& true"
4667   [(set (match_dup 0)
4668         (if_then_else:GPI (match_dup 1)
4669                           (not:GPI (match_dup 3))
4670                           (match_dup 3)))]
4671   {
4672     /* After reload this will be a nop due to the constraint.  */
4673     operands[3] = force_reg (<MODE>mode, operands[3]);
4674   }
4675   [(set_attr "type" "csel")]
4678 (define_insn_and_split "*cmov_uxtw_insn_insv"
4679   [(set (match_operand:DI 0 "register_operand" "=r")
4680         (zero_extend:DI
4681          (xor:SI
4682           (neg:SI
4683            (match_operator:SI 1 "aarch64_comparison_operator"
4684             [(match_operand 2 "cc_register" "") (const_int 0)]))
4685           (match_operand:SI 3 "general_operand" "r"))))]
4686   ""
4687   "#"
4688   "&& true"
4689   [(set (match_dup 0)
4690         (if_then_else:DI (match_dup 1)
4691                           (zero_extend:DI (not:SI (match_dup 3)))
4692                           (zero_extend:DI (match_dup 3))))]
4693   {
4694     operands[3] = force_reg (SImode, operands[3]);
4695   }
4696   [(set_attr "type" "csel")]
4699 ;; If X can be loaded by a single CNT[BHWD] instruction,
4701 ;;    A = UMAX (B, X)
4703 ;; is equivalent to:
4705 ;;    TMP = UQDEC[BHWD] (B, X)
4706 ;;    A = TMP + X
4708 ;; Defining the pattern this way means that:
4710 ;;    A = UMAX (B, X) - X
4712 ;; becomes:
4714 ;;    TMP1 = UQDEC[BHWD] (B, X)
4715 ;;    TMP2 = TMP1 + X
4716 ;;    A = TMP2 - X
4718 ;; which combine can optimize to:
4720 ;;    A = UQDEC[BHWD] (B, X)
4722 ;; We don't use match_operand predicates because the order of the operands
4723 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4724 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4725 (define_expand "umax<mode>3"
4726   [(set (match_operand:GPI 0 "register_operand")
4727         (umax:GPI (match_operand:GPI 1 "")
4728                   (match_operand:GPI 2 "")))]
4729   "TARGET_SVE || TARGET_CSSC"
4730   {
4731     if (aarch64_sve_cnt_immediate (operands[1], <MODE>mode))
4732       std::swap (operands[1], operands[2]);
4733     else if (aarch64_sve_cnt_immediate (operands[2], <MODE>mode))
4734       ;
4735     else if (TARGET_CSSC)
4736       {
4737         if (aarch64_uminmax_immediate (operands[1], <MODE>mode))
4738           std::swap (operands[1], operands[2]);
4739         operands[1] = force_reg (<MODE>mode, operands[1]);
4740         if (!aarch64_uminmax_operand (operands[2], <MODE>mode))
4741           operands[2] = force_reg (<MODE>mode, operands[2]);
4742         emit_move_insn (operands[0], gen_rtx_UMAX (<MODE>mode, operands[1],
4743                                                    operands[2]));
4744         DONE;
4745       }
4746     else
4747       FAIL;
4748     rtx temp = gen_reg_rtx (<MODE>mode);
4749     operands[1] = force_reg (<MODE>mode, operands[1]);
4750     emit_insn (gen_aarch64_uqdec<mode> (temp, operands[1], operands[2]));
4751     emit_insn (gen_add<mode>3 (operands[0], temp, operands[2]));
4752     DONE;
4753   }
4756 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4757 (define_insn "aarch64_uqdec<mode>"
4758   [(set (match_operand:GPI 0 "register_operand" "=r")
4759         (minus:GPI
4760          (umax:GPI (match_operand:GPI 1 "register_operand" "0")
4761                    (match_operand:GPI 2 "aarch64_sve_cnt_immediate" "Usv"))
4762          (match_dup 2)))]
4763   "TARGET_SVE"
4764   {
4765     return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>0", operands[2]);
4766   }
4769 ;; Implement MAX/MIN (A, B) - C using SUBS/ADDS followed by CSEL/CSINV/CSINC.
4770 ;; See aarch64_maxmin_plus_const for details about the supported cases.
4771 (define_insn_and_split "*aarch64_minmax_plus"
4772   [(set (match_operand:GPI 0 "register_operand" "=r")
4773         (plus:GPI
4774           (MAXMIN:GPI
4775             (match_operand:GPI 1 "register_operand" "r")
4776             (match_operand:GPI 2 "const_int_operand"))
4777           (match_operand:GPI 3 "aarch64_plus_immediate")))
4778    (clobber (reg:CC CC_REGNUM))]
4779   "aarch64_maxmin_plus_const (<CODE>, operands, false)"
4780   "#"
4781   "&& 1"
4782   [(parallel
4783      [(set (reg:CC CC_REGNUM)
4784            (compare:CC (match_dup 1) (match_dup 4)))
4785       (set (match_dup 6)
4786            (plus:GPI (match_dup 1) (match_dup 3)))])
4787    (set (match_dup 0)
4788         (if_then_else:GPI (match_dup 5) (match_dup 6) (match_dup 7)))]
4789   {
4790     if (!aarch64_maxmin_plus_const (<CODE>, operands, true))
4791       gcc_unreachable ();
4792   }
4793   [(set_attr "length" "8")]
4796 ;; -------------------------------------------------------------------
4797 ;; Logical operations
4798 ;; -------------------------------------------------------------------
4801 (define_insn_and_split "*aarch64_and<mode>_imm2"
4802   [(set (match_operand:GPI 0 "register_operand" "=rk")
4803         (and:GPI (match_operand:GPI 1 "register_operand" "%r")
4804                  (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
4805   ""
4806   "#"
4807   "true"
4808   [(const_int 0)]
4809   {
4810      HOST_WIDE_INT val = INTVAL (operands[2]);
4811      rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4812      rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4814      emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
4815      emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
4816      DONE;
4817   }
4820 (define_insn "<optab><mode>3"
4821   [(set (match_operand:GPI 0 "register_operand")
4822         (LOGICAL:GPI (match_operand:GPI 1 "register_operand")
4823                      (match_operand:GPI 2 "aarch64_logical_operand")))]
4824   ""
4825   {@ [ cons: =0 , 1  , 2        ; attrs: type , arch  ]
4826      [ r        , %r , r        ; logic_reg   , *     ] <logical>\t%<w>0, %<w>1, %<w>2
4827      [ rk       , r  , <lconst> ; logic_imm   , *     ] <logical>\t%<w>0, %<w>1, %2
4828      [ w        , 0  , <lconst> ; *           , sve   ] <logical>\t%Z0.<s>, %Z0.<s>, #%2
4829      [ w        , w  , w        ; neon_logic  , simd  ] <logical>\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>
4830   }
4833 ;; zero_extend version of above
4834 (define_insn "*<optab>si3_uxtw"
4835   [(set (match_operand:DI 0 "register_operand")
4836         (zero_extend:DI
4837          (LOGICAL:SI (match_operand:SI 1 "register_operand")
4838                      (match_operand:SI 2 "aarch64_logical_operand"))))]
4839   ""
4840   {@ [ cons: =0 , 1  , 2 ; attrs: type ]
4841      [ r        , %r , r ; logic_reg   ] <logical>\t%w0, %w1, %w2
4842      [ rk       , r  , K ; logic_imm   ] <logical>\t%w0, %w1, %2
4843   }
4846 (define_insn "*and<mode>3_compare0"
4847   [(set (reg:CC_NZV CC_REGNUM)
4848         (compare:CC_NZV
4849          (and:GPI (match_operand:GPI 1 "register_operand")
4850                   (match_operand:GPI 2 "aarch64_logical_operand"))
4851          (const_int 0)))
4852    (set (match_operand:GPI 0 "register_operand")
4853         (and:GPI (match_dup 1) (match_dup 2)))]
4854   ""
4855   {@ [ cons: =0 , 1  , 2        ; attrs: type ]
4856      [ r        , %r , r        ; logics_reg  ] ands\t%<w>0, %<w>1, %<w>2
4857      [ r        , r  , <lconst> ; logics_imm  ] ands\t%<w>0, %<w>1, %2
4858   }
4861 ;; zero_extend version of above
4862 (define_insn "*andsi3_compare0_uxtw"
4863   [(set (reg:CC_NZV CC_REGNUM)
4864         (compare:CC_NZV
4865          (and:SI (match_operand:SI 1 "register_operand")
4866                  (match_operand:SI 2 "aarch64_logical_operand"))
4867          (const_int 0)))
4868    (set (match_operand:DI 0 "register_operand")
4869         (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
4870   ""
4871   {@ [ cons: =0 , 1  , 2 ; attrs: type ]
4872      [ r        , %r , r ; logics_reg  ] ands\t%w0, %w1, %w2
4873      [ r        , r  , K ; logics_imm  ] ands\t%w0, %w1, %2
4874   }
4877 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
4878   [(set (reg:CC_NZV CC_REGNUM)
4879         (compare:CC_NZV
4880          (and:GPI (SHIFT:GPI
4881                    (match_operand:GPI 1 "register_operand" "r")
4882                    (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4883                   (match_operand:GPI 3 "register_operand" "r"))
4884          (const_int 0)))
4885    (set (match_operand:GPI 0 "register_operand" "=r")
4886         (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
4887   ""
4889   if (<SHIFT:is_rotl>)
4890     operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4891   return "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
4893   [(set_attr "type" "logics_shift_imm")]
4896 ;; zero_extend version of above
4897 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4898   [(set (reg:CC_NZV CC_REGNUM)
4899         (compare:CC_NZV
4900          (and:SI (SHIFT:SI
4901                   (match_operand:SI 1 "register_operand" "r")
4902                   (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4903                  (match_operand:SI 3 "register_operand" "r"))
4904          (const_int 0)))
4905    (set (match_operand:DI 0 "register_operand" "=r")
4906         (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
4907                                 (match_dup 3))))]
4908   ""
4910   if (<SHIFT:is_rotl>)
4911     operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
4912   return "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2";
4914   [(set_attr "type" "logics_shift_imm")]
4917 (define_insn "<LOGICAL:optab>_<SHIFT:optab><mode>3"
4918   [(set (match_operand:GPI 0 "register_operand" "=r")
4919         (LOGICAL:GPI (SHIFT:GPI
4920                       (match_operand:GPI 1 "register_operand" "r")
4921                       (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4922                      (match_operand:GPI 3 "register_operand" "r")))]
4923   ""
4925   if (<SHIFT:is_rotl>)
4926     operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4927   return "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
4929   [(set_attr "type" "logic_shift_imm")]
4932 (define_split
4933   [(set (match_operand:GPI 0 "register_operand")
4934         (LOGICAL_OR_PLUS:GPI
4935           (and:GPI
4936             (lshiftrt:GPI (match_operand:GPI 1 "register_operand")
4937                           (match_operand:QI 2 "aarch64_shift_imm_<mode>"))
4938             (match_operand:GPI 3 "aarch64_logical_immediate"))
4939           (match_operand:GPI 4 "register_operand")))]
4940   "can_create_pseudo_p ()
4941    && aarch64_bitmask_imm (UINTVAL (operands[3]) << UINTVAL (operands[2]),
4942                            <MODE>mode)"
4943   [(set (match_dup 5) (and:GPI (match_dup 1) (match_dup 6)))
4944    (set (match_dup 0) (LOGICAL_OR_PLUS:GPI
4945                        (lshiftrt:GPI (match_dup 5) (match_dup 2))
4946                        (match_dup 4)))]
4947   {
4948     operands[5] = gen_reg_rtx (<MODE>mode);
4949     operands[6]
4950       = gen_int_mode (UINTVAL (operands[3]) << UINTVAL (operands[2]),
4951                       <MODE>mode);
4952   }
4955 (define_split
4956   [(set (match_operand:GPI 0 "register_operand")
4957         (LOGICAL_OR_PLUS:GPI
4958           (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand")
4959                                (match_operand:QI 2 "aarch64_shift_imm_<mode>"))
4960                    (match_operand:GPI 3 "const_int_operand"))
4961           (zero_extend:GPI (match_operand 4 "register_operand"))))]
4962   "can_create_pseudo_p ()
4963    && ((paradoxical_subreg_p (operands[1])
4964         && rtx_equal_p (SUBREG_REG (operands[1]), operands[4]))
4965        || (REG_P (operands[1])
4966            && REG_P (operands[4])
4967            && REGNO (operands[1]) == REGNO (operands[4])))
4968    && (trunc_int_for_mode (GET_MODE_MASK (GET_MODE (operands[4]))
4969                            << INTVAL (operands[2]), <MODE>mode)
4970        == INTVAL (operands[3]))
4971    && (<CODE> != PLUS
4972        || (GET_MODE_MASK (GET_MODE (operands[4]))
4973            & INTVAL (operands[3])) == 0)"
4974   [(set (match_dup 5) (zero_extend:GPI (match_dup 4)))
4975    (set (match_dup 0) (match_dup 6))]
4976   {
4977     operands[5] = gen_reg_rtx (<MODE>mode);
4978     rtx shift = gen_rtx_ASHIFT (<MODE>mode, operands[5], operands[2]);
4979     rtx_code new_code = (<CODE> == PLUS ? IOR : <CODE>);
4980     operands[6] = gen_rtx_fmt_ee (new_code, <MODE>mode, shift, operands[5]);
4981   }
4984 (define_split
4985   [(set (match_operand:GPI 0 "register_operand")
4986         (LOGICAL_OR_PLUS:GPI
4987           (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand")
4988                                (match_operand:QI 2 "aarch64_shift_imm_<mode>"))
4989                    (match_operand:GPI 4 "const_int_operand"))
4990           (and:GPI (match_dup 1) (match_operand:GPI 3 "const_int_operand"))))]
4991   "can_create_pseudo_p ()
4992    && pow2_or_zerop (UINTVAL (operands[3]) + 1)
4993    && (trunc_int_for_mode (UINTVAL (operands[3])
4994                            << INTVAL (operands[2]), <MODE>mode)
4995        == INTVAL (operands[4]))
4996    && (<CODE> != PLUS
4997        || (INTVAL (operands[4]) & INTVAL (operands[3])) == 0)"
4998   [(set (match_dup 5) (and:GPI (match_dup 1) (match_dup 3)))
4999    (set (match_dup 0) (match_dup 6))]
5000   {
5001     operands[5] = gen_reg_rtx (<MODE>mode);
5002     rtx shift = gen_rtx_ASHIFT (<MODE>mode, operands[5], operands[2]);
5003     rtx_code new_code = (<CODE> == PLUS ? IOR : <CODE>);
5004     operands[6] = gen_rtx_fmt_ee (new_code, <MODE>mode, shift, operands[5]);
5005   }
5008 (define_split
5009   [(set (match_operand:GPI 0 "register_operand")
5010         (LOGICAL:GPI
5011           (ashift:GPI (sign_extend:GPI (match_operand 1 "register_operand"))
5012                       (match_operand:QI 2 "aarch64_shift_imm_<mode>"))
5013           (sign_extend:GPI (match_dup 1))))]
5014   "can_create_pseudo_p ()"
5015   [(set (match_dup 3) (sign_extend:GPI (match_dup 1)))
5016    (set (match_dup 0) (LOGICAL:GPI (ashift:GPI (match_dup 3) (match_dup 2))
5017                                    (match_dup 3)))]
5018   "operands[3] = gen_reg_rtx (<MODE>mode);"
5021 ;; zero_extend versions of above
5022 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
5023   [(set (match_operand:DI 0 "register_operand" "=r")
5024         (zero_extend:DI
5025          (LOGICAL:SI (SHIFT:SI
5026                       (match_operand:SI 1 "register_operand" "r")
5027                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
5028                      (match_operand:SI 3 "register_operand" "r"))))]
5029   ""
5031   if (<SHIFT:is_rotl>)
5032     operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
5033   return "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2";
5035   [(set_attr "type" "logic_shift_imm")]
5038 (define_insn "one_cmpl<mode>2"
5039   [(set (match_operand:GPI 0 "register_operand")
5040         (not:GPI (match_operand:GPI 1 "register_operand")))]
5041   ""
5042   {@ [ cons: =0 , 1 ; attrs: type , arch  ]
5043      [ r        , r ; logic_reg   , *     ] mvn\t%<w>0, %<w>1
5044      [ w        , w ; neon_logic  , simd  ] mvn\t%0.8b, %1.8b
5045   }
5048 (define_insn "*one_cmpl_zero_extend"
5049   [(set (match_operand:DI 0 "register_operand" "=r")
5050         (zero_extend:DI
5051           (not:SI (match_operand:SI 1 "register_operand" "r"))))]
5052   ""
5053   "mvn\\t%w0, %w1"
5054   [(set_attr "type" "logic_reg")]
5057 (define_insn "*one_cmpl_<optab><mode>2"
5058   [(set (match_operand:GPI 0 "register_operand" "=r")
5059         (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
5060                             (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
5061   ""
5063   if (<SHIFT:is_rotl>)
5064     operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5065   return "mvn\\t%<w>0, %<w>1, <shift> %2";
5067   [(set_attr "type" "logic_shift_imm")]
5070 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
5072 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
5073   [(set (match_operand:GPI 0 "register_operand")
5074         (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand"))
5075                      (match_operand:GPI 2 "register_operand")))]
5076   ""
5077   {@ [ cons: =0 , 1 , 2 ; attrs: type , arch  ]
5078      [ r        , r , r ; logic_reg   , *     ] <NLOGICAL:nlogical>\t%<w>0, %<w>2, %<w>1
5079      [ w        , w , w ; neon_logic  , simd  ] <NLOGICAL:nlogical>\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>
5080   }
5083 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
5084   [(set (match_operand:DI 0 "register_operand" "=r")
5085         (zero_extend:DI
5086           (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
5087                        (match_operand:SI 2 "register_operand" "r"))))]
5088   ""
5089   "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
5090   [(set_attr "type" "logic_reg")]
5093 (define_insn "*xor_one_cmplsidi3_ze"
5094   [(set (match_operand:DI 0 "register_operand" "=r")
5095         (zero_extend:DI
5096           (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
5097                           (match_operand:SI 2 "register_operand" "r")))))]
5098   ""
5099   "eon\\t%w0, %w1, %w2"
5100   [(set_attr "type" "logic_reg")]
5103 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
5104 ;; eon does not operate on SIMD registers so the vector variant must be split.
5105 (define_insn_and_split "*xor_one_cmpl<mode>3"
5106   [(set (match_operand:GPI 0 "register_operand" "=r,w")
5107         (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
5108                           (match_operand:GPI 2 "register_operand" "r,w"))))]
5109   ""
5110   "@
5111   eon\\t%<w>0, %<w>1, %<w>2
5112   #"
5113   "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
5114   [(set (match_operand:GPI 0 "register_operand" "=w")
5115         (xor:GPI (match_operand:GPI 1 "register_operand" "w")
5116                  (match_operand:GPI 2 "register_operand" "w")))
5117    (set (match_dup 0) (not:GPI (match_dup 0)))]
5118   ""
5119   [(set_attr "type" "logic_reg,multiple")
5120    (set_attr "arch" "*,simd")]
5123 (define_insn "*and_one_cmpl<mode>3_compare0"
5124   [(set (reg:CC_NZV CC_REGNUM)
5125         (compare:CC_NZV
5126          (and:GPI (not:GPI
5127                    (match_operand:GPI 1 "register_operand" "r"))
5128                   (match_operand:GPI 2 "register_operand" "r"))
5129          (const_int 0)))
5130    (set (match_operand:GPI 0 "register_operand" "=r")
5131         (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
5132   ""
5133   "bics\\t%<w>0, %<w>2, %<w>1"
5134   [(set_attr "type" "logics_reg")]
5137 ;; zero_extend version of above
5138 (define_insn "*and_one_cmplsi3_compare0_uxtw"
5139   [(set (reg:CC_NZV CC_REGNUM)
5140         (compare:CC_NZV
5141          (and:SI (not:SI
5142                   (match_operand:SI 1 "register_operand" "r"))
5143                  (match_operand:SI 2 "register_operand" "r"))
5144          (const_int 0)))
5145    (set (match_operand:DI 0 "register_operand" "=r")
5146         (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
5147   ""
5148   "bics\\t%w0, %w2, %w1"
5149   [(set_attr "type" "logics_reg")]
5152 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
5153   [(set (reg:CC_NZV CC_REGNUM)
5154     (compare:CC_NZV
5155      (and:GPI (not:GPI
5156            (match_operand:GPI 0 "register_operand" "r"))
5157           (match_operand:GPI 1 "register_operand" "r"))
5158      (const_int 0)))]
5159   ""
5160   "bics\\t<w>zr, %<w>1, %<w>0"
5161   [(set_attr "type" "logics_reg")]
5164 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
5165   [(set (match_operand:GPI 0 "register_operand" "=r")
5166         (LOGICAL:GPI (not:GPI
5167                       (SHIFT:GPI
5168                        (match_operand:GPI 1 "register_operand" "r")
5169                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
5170                      (match_operand:GPI 3 "register_operand" "r")))]
5171   ""
5173   if (<SHIFT:is_rotl>)
5174     operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5175   return "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
5177   [(set_attr "type" "logic_shift_imm")]
5180 ;; Zero-extend version of the above.
5181 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab>sidi_uxtw"
5182   [(set (match_operand:DI 0 "register_operand" "=r")
5183         (zero_extend:DI (LOGICAL:SI (not:SI
5184                          (SHIFT:SI
5185                           (match_operand:SI 1 "register_operand" "r")
5186                           (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
5187                          (match_operand:SI 3 "register_operand" "r"))))]
5188   ""
5190   if (<SHIFT:is_rotl>)
5191     operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
5192   return "<LOGICAL:nlogical>\\t%w0, %w3, %w1, <SHIFT:shift> %2";
5194   [(set_attr "type" "logic_shift_imm")]
5197 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
5198   [(set (match_operand:GPI 0 "register_operand" "=r")
5199         (not:GPI (xor:GPI
5200                       (SHIFT:GPI
5201                        (match_operand:GPI 1 "register_operand" "r")
5202                        (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
5203                      (match_operand:GPI 3 "register_operand" "r"))))]
5204   ""
5206   if (<SHIFT:is_rotl>)
5207     operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5208   return "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
5210   [(set_attr "type" "logic_shift_imm")]
5213 ;; Zero-extend version of the above.
5214 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
5215   [(set (match_operand:DI 0 "register_operand" "=r")
5216         (zero_extend:DI
5217           (not:SI (xor:SI
5218                     (SHIFT:SI
5219                       (match_operand:SI 1 "register_operand" "r")
5220                       (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
5221                     (match_operand:SI 3 "register_operand" "r")))))]
5222   ""
5224   if (<SHIFT:is_rotl>)
5225     operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
5226   return "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2";
5228   [(set_attr "type" "logic_shift_imm")]
5231 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
5232   [(set (reg:CC_NZV CC_REGNUM)
5233         (compare:CC_NZV
5234          (and:GPI (not:GPI
5235                    (SHIFT:GPI
5236                     (match_operand:GPI 1 "register_operand" "r")
5237                     (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
5238                   (match_operand:GPI 3 "register_operand" "r"))
5239          (const_int 0)))
5240    (set (match_operand:GPI 0 "register_operand" "=r")
5241         (and:GPI (not:GPI
5242                   (SHIFT:GPI
5243                    (match_dup 1) (match_dup 2))) (match_dup 3)))]
5244   ""
5246   if (<SHIFT:is_rotl>)
5247     operands[2] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5248   return "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2";
5250   [(set_attr "type" "logics_shift_imm")]
5253 ;; zero_extend version of above
5254 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
5255   [(set (reg:CC_NZV CC_REGNUM)
5256         (compare:CC_NZV
5257          (and:SI (not:SI
5258                   (SHIFT:SI
5259                    (match_operand:SI 1 "register_operand" "r")
5260                    (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
5261                  (match_operand:SI 3 "register_operand" "r"))
5262          (const_int 0)))
5263    (set (match_operand:DI 0 "register_operand" "=r")
5264         (zero_extend:DI (and:SI
5265                          (not:SI
5266                           (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
5267   ""
5269   if (<SHIFT:is_rotl>)
5270     operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
5271   return "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2";
5273   [(set_attr "type" "logics_shift_imm")]
5276 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
5277   [(set (reg:CC_NZV CC_REGNUM)
5278     (compare:CC_NZV
5279      (and:GPI (not:GPI
5280            (SHIFT:GPI
5281             (match_operand:GPI 0 "register_operand" "r")
5282             (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
5283           (match_operand:GPI 2 "register_operand" "r"))
5284      (const_int 0)))]
5285   ""
5287   if (<SHIFT:is_rotl>)
5288     operands[1] = GEN_INT (<sizen> - UINTVAL (operands[1]));
5289   return "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1";
5291   [(set_attr "type" "logics_shift_imm")]
5294 (define_insn "clz<mode>2"
5295   [(set (match_operand:GPI 0 "register_operand" "=r")
5296         (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
5297   ""
5298   "clz\\t%<w>0, %<w>1"
5299   [(set_attr "type" "clz")]
5302 (define_expand "ffs<mode>2"
5303   [(match_operand:GPI 0 "register_operand")
5304    (match_operand:GPI 1 "register_operand")]
5305   ""
5306   {
5307     rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
5308     rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
5310     emit_insn (gen_aarch64_rbit (<MODE>mode, operands[0], operands[1]));
5311     emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
5312     emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
5313     DONE;
5314   }
5317 (define_insn "*aarch64_popcount<mode>2_cssc_insn"
5318   [(set (match_operand:GPI 0 "register_operand" "=r")
5319         (popcount:GPI (match_operand:GPI 1 "register_operand" "r")))]
5320   "TARGET_CSSC"
5321   "cnt\\t%<w>0, %<w>1"
5322   [(set_attr "type" "clz")]
5325 ;; The CSSC instructions can do popcount in the GP registers directly through
5326 ;; CNT.  If it is not available then we can use CNT on the Advanced SIMD side
5327 ;; through:
5328 ;; MOV  v.1d, x0
5329 ;; CNT  v1.8b, v.8b
5330 ;; ADDV b2, v1.8b
5331 ;; MOV  w0, v2.b[0]
5333 (define_expand "popcount<mode>2"
5334   [(set (match_operand:GPI 0 "register_operand")
5335         (popcount:GPI (match_operand:GPI 1 "register_operand")))]
5336   "TARGET_CSSC || TARGET_SIMD"
5338   if (!TARGET_CSSC)
5339     {
5340       rtx v = gen_reg_rtx (V8QImode);
5341       rtx v1 = gen_reg_rtx (V8QImode);
5342       rtx in = operands[1];
5343       rtx out = operands[0];
5344       if(<MODE>mode == SImode)
5345         {
5346           rtx tmp;
5347           tmp = gen_reg_rtx (DImode);
5348           /* If we have SImode, zero extend to DImode, pop count does
5349              not change if we have extra zeros. */
5350           emit_insn (gen_zero_extendsidi2 (tmp, in));
5351           in = tmp;
5352         }
5353       emit_move_insn (v, gen_lowpart (V8QImode, in));
5354       emit_insn (gen_popcountv8qi2 (v1, v));
5355       emit_insn (gen_aarch64_zero_extend<mode>_reduc_plus_v8qi (out, v1));
5356       DONE;
5357     }
5360 (define_insn "clrsb<mode>2"
5361   [(set (match_operand:GPI 0 "register_operand" "=r")
5362         (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
5363   ""
5364   "cls\\t%<w>0, %<w>1"
5365   [(set_attr "type" "clz")]
5368 (define_insn "@aarch64_rbit<mode>"
5369   [(set (match_operand:GPI 0 "register_operand" "=r")
5370         (bitreverse:GPI (match_operand:GPI 1 "register_operand" "r")))]
5371   ""
5372   "rbit\\t%<w>0, %<w>1"
5373   [(set_attr "type" "rbit")]
5376 ;; Split after reload into RBIT + CLZ.  Since RBIT is represented as an UNSPEC
5377 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
5378 ;; expression and split after reload to enable scheduling them apart if
5379 ;; needed.  For TARGET_CSSC we have a single CTZ instruction that can do this.
5381 (define_insn_and_split "ctz<mode>2"
5382  [(set (match_operand:GPI           0 "register_operand" "=r")
5383        (ctz:GPI (match_operand:GPI  1 "register_operand" "r")))]
5384   ""
5385   { return TARGET_CSSC ? "ctz\\t%<w>0, %<w>1" : "#"; }
5386   "reload_completed && !TARGET_CSSC"
5387   [(const_int 0)]
5388   "
5389   emit_insn (gen_aarch64_rbit (<MODE>mode, operands[0], operands[1]));
5390   emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
5391   DONE;
5394 (define_insn "*and<mode>_compare0"
5395   [(set (reg:CC_Z CC_REGNUM)
5396         (compare:CC_Z
5397          (match_operand:SHORT 0 "register_operand" "r")
5398          (const_int 0)))]
5399   ""
5400   "tst\\t%<w>0, <short_mask>"
5401   [(set_attr "type" "alus_imm")]
5404 (define_insn "*ands<GPI:mode>_compare0"
5405   [(set (reg:CC_Z CC_REGNUM)
5406         (compare:CC_Z
5407          (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
5408          (const_int 0)))
5409    (set (match_operand:GPI 0 "register_operand" "=r")
5410         (zero_extend:GPI (match_dup 1)))]
5411   ""
5412   "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
5413   [(set_attr "type" "alus_imm")]
5416 (define_insn "@aarch64_and<mode>3nr_compare0"
5417   [(set (reg:CC_NZV CC_REGNUM)
5418         (compare:CC_NZV
5419          (and:GPI (match_operand:GPI 0 "register_operand")
5420                   (match_operand:GPI 1 "aarch64_logical_operand"))
5421          (const_int 0)))]
5422   ""
5423   {@ [ cons: 0 , 1        ; attrs: type ]
5424      [ %r      , r        ; logics_reg  ] tst\t%<w>0, %<w>1
5425      [ r       , <lconst> ; logics_imm  ] tst\t%<w>0, %1
5426   }
5429 (define_split
5430   [(set (reg:CC_NZV CC_REGNUM)
5431         (compare:CC_NZV
5432          (and:GPI (match_operand:GPI 0 "register_operand")
5433                   (match_operand:GPI 1 "aarch64_mov_imm_operand"))
5434          (const_int 0)))
5435    (clobber (match_operand:SI 2 "register_operand"))]
5436   ""
5437   [(set (match_dup 2) (match_dup 1))
5438    (set (reg:CC_NZV CC_REGNUM)
5439         (compare:CC_NZV
5440          (and:GPI (match_dup 0)
5441                   (match_dup 2))
5442          (const_int 0)))]
5445 (define_insn "*and<mode>3nr_compare0_zextract"
5446   [(set (reg:CC_Z CC_REGNUM)
5447         (compare:CC_Z
5448          (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
5449                   (match_operand:GPI 1 "const_int_operand" "n")
5450                   (match_operand:GPI 2 "const_int_operand" "n"))
5451          (const_int 0)))]
5452   "INTVAL (operands[1]) > 0
5453    && ((INTVAL (operands[1]) + INTVAL (operands[2]))
5454         <= GET_MODE_BITSIZE (<MODE>mode))
5455    && aarch64_bitmask_imm (
5456         UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
5457                                                  operands[2])),
5458         <MODE>mode)"
5459   {
5460     operands[1]
5461       = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
5462     return "tst\\t%<w>0, %1";
5463   }
5464   [(set_attr "type" "logics_shift_imm")]
5467 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
5468   [(set (reg:CC_NZV CC_REGNUM)
5469         (compare:CC_NZV
5470          (and:GPI (SHIFT:GPI
5471                    (match_operand:GPI 0 "register_operand" "r")
5472                    (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
5473                   (match_operand:GPI 2 "register_operand" "r"))
5474         (const_int 0)))]
5475   ""
5477   if (<SHIFT:is_rotl>)
5478     operands[1] = GEN_INT (<sizen> - UINTVAL (operands[1]));
5479   return "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1";
5481   [(set_attr "type" "logics_shift_imm")]
5484 (define_split
5485   [(set (reg:CC_NZV CC_REGNUM)
5486         (compare:CC_NZV
5487          (and:GPI (SHIFT:GPI
5488                    (match_operand:GPI 0 "register_operand")
5489                    (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
5490                   (match_operand:GPI 2 "aarch64_mov_imm_operand"))
5491         (const_int 0)))
5492     (clobber (match_operand:SI 3 "register_operand"))]
5493   ""
5494   [(set (match_dup 3) (match_dup 2))
5495    (set (reg:CC_NZV CC_REGNUM)
5496         (compare:CC_NZV
5497          (and:GPI (SHIFT:GPI
5498                    (match_dup 0)
5499                    (match_dup 1))
5500                   (match_dup 3))
5501          (const_int 0)))]
5504 ;; -------------------------------------------------------------------
5505 ;; Shifts
5506 ;; -------------------------------------------------------------------
5508 (define_expand "<optab><mode>3"
5509   [(set (match_operand:GPI 0 "register_operand")
5510         (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
5511                     (match_operand:QI 2 "aarch64_reg_or_imm")))]
5512   ""
5513   {
5514     if (CONST_INT_P (operands[2]))
5515       {
5516         operands[2] = GEN_INT (INTVAL (operands[2])
5517                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
5519         if (operands[2] == const0_rtx)
5520           {
5521             emit_insn (gen_mov<mode> (operands[0], operands[1]));
5522             DONE;
5523           }
5524       }
5525   }
5528 (define_expand "ashl<mode>3"
5529   [(set (match_operand:SHORT 0 "register_operand")
5530         (ashift:SHORT (match_operand:SHORT 1 "register_operand")
5531                       (match_operand:QI 2 "const_int_operand")))]
5532   ""
5533   {
5534     operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
5536     if (operands[2] == const0_rtx)
5537       {
5538         emit_insn (gen_mov<mode> (operands[0], operands[1]));
5539         DONE;
5540       }
5541   }
5544 (define_expand "rotr<mode>3"
5545   [(set (match_operand:GPI 0 "register_operand")
5546         (rotatert:GPI (match_operand:GPI 1 "register_operand")
5547                       (match_operand:QI 2 "aarch64_reg_or_imm")))]
5548   ""
5549   {
5550     if (CONST_INT_P (operands[2]))
5551       {
5552         operands[2] = GEN_INT (INTVAL (operands[2])
5553                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
5555         if (operands[2] == const0_rtx)
5556           {
5557             emit_insn (gen_mov<mode> (operands[0], operands[1]));
5558             DONE;
5559           }
5560       }
5561   }
5564 (define_expand "rotl<mode>3"
5565   [(set (match_operand:GPI 0 "register_operand")
5566         (rotatert:GPI (match_operand:GPI 1 "register_operand")
5567                       (match_operand:QI 2 "aarch64_reg_or_imm")))]
5568   ""
5569   {
5570     /* (SZ - cnt) % SZ == -cnt % SZ */
5571     if (CONST_INT_P (operands[2]))
5572       {
5573         operands[2] = GEN_INT ((-UINTVAL (operands[2]))
5574                                & (GET_MODE_BITSIZE (<MODE>mode) - 1));
5575         if (operands[2] == const0_rtx)
5576           {
5577             emit_insn (gen_mov<mode> (operands[0], operands[1]));
5578             DONE;
5579           }
5580       }
5581     else
5582       operands[2] = expand_simple_unop (QImode, NEG, operands[2],
5583                                         NULL_RTX, 1);
5584   }
5587 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
5588 ;; they truncate the shift/rotate amount by the size of the registers they
5589 ;; operate on: 32 for W-regs, 64 for X-regs.  This allows us to optimise away
5590 ;; such redundant masking instructions.  GCC can do that automatically when
5591 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
5592 ;; because some of the SISD shift alternatives don't perform this truncations.
5593 ;; So this pattern exists to catch such cases.
5595 (define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
5596   [(set (match_operand:GPI 0 "register_operand" "=r")
5597         (SHIFT:GPI
5598           (match_operand:GPI 1 "register_operand" "r")
5599           (match_operator 4 "subreg_lowpart_operator"
5600            [(and:GPI (match_operand:GPI 2 "register_operand" "r")
5601                      (match_operand 3 "const_int_operand" "n"))])))]
5602   "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
5603   "<shift>\t%<w>0, %<w>1, %<w>2"
5604   [(set_attr "type" "shift_reg")]
5607 (define_insn_and_split "*aarch64_<optab>_reg_<mode>3_neg_mask2"
5608   [(set (match_operand:GPI 0 "register_operand" "=&r")
5609         (SHIFT:GPI
5610           (match_operand:GPI 1 "register_operand" "r")
5611           (match_operator 4 "subreg_lowpart_operator"
5612           [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
5613                            (match_operand 3 "const_int_operand" "n")))])))]
5614   "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
5615   "#"
5616   "&& true"
5617   [(const_int 0)]
5618   {
5619     rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5620                : lowpart_subreg (SImode, operands[0], <MODE>mode));
5621     emit_insn (gen_negsi2 (tmp, operands[2]));
5623     rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
5624     rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
5625                                      SUBREG_BYTE (operands[4]));
5626     emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
5627     DONE;
5628   }
5631 (define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask"
5632   [(set (match_operand:GPI 0 "register_operand" "=&r")
5633         (ashift:GPI
5634           (match_operand:GPI 1 "register_operand" "r")
5635           (minus:QI (match_operand 2 "const_int_operand" "n")
5636                     (match_operator 5 "subreg_lowpart_operator"
5637                     [(and:SI (match_operand:SI 3 "register_operand" "r")
5638                              (match_operand 4 "const_int_operand" "n"))]))))]
5639   "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
5640    && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
5641   "#"
5642   "&& true"
5643   [(const_int 0)]
5644   {
5645     rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5646                : operands[0]);
5648     emit_insn (gen_negsi2 (tmp, operands[3]));
5650     rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
5651     rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
5652                                      SUBREG_BYTE (operands[5]));
5654     emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
5655     DONE;
5656   }
5659 (define_insn "*aarch64_<optab>_reg_di3_mask2"
5660   [(set (match_operand:DI 0 "register_operand" "=r")
5661         (SHIFT:DI
5662           (match_operand:DI 1 "register_operand" "r")
5663           (match_operator 4 "subreg_lowpart_operator"
5664            [(and:SI (match_operand:SI 2 "register_operand" "r")
5665                     (match_operand 3 "const_int_operand" "n"))])))]
5666   "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)"
5668   rtx xop[3];
5669   xop[0] = operands[0];
5670   xop[1] = operands[1];
5671   xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
5672   output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
5673   return "";
5675   [(set_attr "type" "shift_reg")]
5678 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>3"
5679   [(set (match_operand:GPI 0 "register_operand" "=&r")
5680         (ASHIFT:GPI
5681           (match_operand:GPI 1 "register_operand" "r")
5682           (minus:QI (match_operand 2 "const_int_operand" "n")
5683                     (match_operand:QI 3 "register_operand" "r"))))]
5684   "INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
5685   "#"
5686   "&& true"
5687   [(const_int 0)]
5688   {
5689     rtx subreg_tmp = gen_lowpart (SImode, operands[3]);
5691     rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5692                : gen_lowpart (SImode, operands[0]));
5694     emit_insn (gen_negsi2 (tmp, subreg_tmp));
5696     rtx and_op = gen_rtx_AND (SImode, tmp,
5697                               GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1));
5699     rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
5701     emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp2));
5702     DONE;
5703   }
5704   [(set_attr "length" "8")]
5707 ;; Logical left shift using SISD or Integer instruction
5708 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
5709   [(set (match_operand:GPI 0 "register_operand")
5710         (ashift:GPI
5711           (match_operand:GPI 1 "register_operand")
5712           (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>")))]
5713   ""
5714   {@ [ cons: =0 , 1 , 2         ; attrs: type       , arch  ]
5715      [ r        , r , Us<cmode> ; bfx               , *     ] lsl\t%<w>0, %<w>1, %2
5716      [ r        , r , r         ; shift_reg         , *     ] lsl\t%<w>0, %<w>1, %<w>2
5717      [ w        , w , Us<cmode> ; neon_shift_imm<q> , simd  ] shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5718      [ w        , w , w         ; neon_shift_reg<q> , simd  ] ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
5719   }
5722 ;; Logical right shift using SISD or Integer instruction
5723 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
5724   [(set (match_operand:GPI 0 "register_operand")
5725         (lshiftrt:GPI
5726          (match_operand:GPI 1 "register_operand")
5727          (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>")))]
5728   ""
5729   {@ [ cons: =0 , 1 , 2              ; attrs: type       , arch  ]
5730      [ r        , r , Us<cmode>      ; bfx               , *     ] lsr\t%<w>0, %<w>1, %2
5731      [ r        , r , r              ; shift_reg         , *     ] lsr\t%<w>0, %<w>1, %<w>2
5732      [ w        , w , Us<cmode_simd> ; neon_shift_imm<q> , simd  ] ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5733      [ &w       , w , w              ; neon_shift_reg<q> , simd  ] #
5734      [ &w       , w , 0              ; neon_shift_reg<q> , simd  ] #
5735   }
5738 (define_split
5739   [(set (match_operand:DI 0 "aarch64_simd_register")
5740         (lshiftrt:DI
5741            (match_operand:DI 1 "aarch64_simd_register")
5742            (match_operand:QI 2 "aarch64_simd_register")))]
5743   "TARGET_SIMD && reload_completed"
5744   [(set (match_dup 3)
5745         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5746    (set (match_dup 0)
5747         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
5748   {
5749     operands[3] = gen_lowpart (QImode, operands[0]);
5750   }
5753 (define_split
5754   [(set (match_operand:SI 0 "aarch64_simd_register")
5755         (lshiftrt:SI
5756            (match_operand:SI 1 "aarch64_simd_register")
5757            (match_operand:QI 2 "aarch64_simd_register")))]
5758   "TARGET_SIMD && reload_completed"
5759   [(set (match_dup 3)
5760         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5761    (set (match_dup 0)
5762         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
5763   {
5764     operands[3] = gen_lowpart (QImode, operands[0]);
5765   }
5768 ;; Arithmetic right shift using SISD or Integer instruction
5769 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
5770   [(set (match_operand:GPI 0 "register_operand")
5771         (ashiftrt:GPI
5772           (match_operand:GPI 1 "register_operand")
5773           (match_operand:QI 2 "aarch64_reg_or_shift_imm_di")))]
5774   ""
5775   {@ [ cons: =0 , 1 , 2              ; attrs: type       , arch  ]
5776      [ r        , r , Us<cmode>      ; bfx               , *     ] asr\t%<w>0, %<w>1, %2
5777      [ r        , r , r              ; shift_reg         , *     ] asr\t%<w>0, %<w>1, %<w>2
5778      [ w        , w , Us<cmode_simd> ; neon_shift_imm<q> , simd  ] sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5779      [ &w       , w , w              ; neon_shift_reg<q> , simd  ] #
5780      [ &w       , w , 0              ; neon_shift_reg<q> , simd  ] #
5781   }
5784 (define_split
5785   [(set (match_operand:DI 0 "aarch64_simd_register")
5786         (ashiftrt:DI
5787            (match_operand:DI 1 "aarch64_simd_register")
5788            (match_operand:QI 2 "aarch64_simd_register")))]
5789   "TARGET_SIMD && reload_completed"
5790   [(set (match_dup 3)
5791         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5792    (set (match_dup 0)
5793         (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
5795   operands[3] = gen_lowpart (QImode, operands[0]);
5799 (define_split
5800   [(set (match_operand:SI 0 "aarch64_simd_register")
5801         (ashiftrt:SI
5802            (match_operand:SI 1 "aarch64_simd_register")
5803            (match_operand:QI 2 "aarch64_simd_register")))]
5804   "TARGET_SIMD && reload_completed"
5805   [(set (match_dup 3)
5806         (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5807    (set (match_dup 0)
5808         (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
5810   operands[3] = gen_lowpart (QImode, operands[0]);
5814 (define_insn "*aarch64_sisd_ushl"
5815   [(set (match_operand:DI 0 "register_operand" "=w")
5816         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
5817                     (match_operand:QI 2 "register_operand" "w")]
5818                    UNSPEC_SISD_USHL))]
5819   "TARGET_SIMD"
5820   "ushl\t%d0, %d1, %d2"
5821   [(set_attr "type" "neon_shift_reg")]
5824 (define_insn "*aarch64_ushl_2s"
5825   [(set (match_operand:SI 0 "register_operand" "=w")
5826         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
5827                     (match_operand:QI 2 "register_operand" "w")]
5828                    UNSPEC_USHL_2S))]
5829   "TARGET_SIMD"
5830   "ushl\t%0.2s, %1.2s, %2.2s"
5831   [(set_attr "type" "neon_shift_reg")]
5834 (define_insn "*aarch64_sisd_sshl"
5835   [(set (match_operand:DI 0 "register_operand" "=w")
5836         (unspec:DI [(match_operand:DI 1 "register_operand" "w")
5837                     (match_operand:QI 2 "register_operand" "w")]
5838                    UNSPEC_SISD_SSHL))]
5839   "TARGET_SIMD"
5840   "sshl\t%d0, %d1, %d2"
5841   [(set_attr "type" "neon_shift_reg")]
5844 (define_insn "*aarch64_sshl_2s"
5845   [(set (match_operand:SI 0 "register_operand" "=w")
5846         (unspec:SI [(match_operand:SI 1 "register_operand" "w")
5847                     (match_operand:QI 2 "register_operand" "w")]
5848                    UNSPEC_SSHL_2S))]
5849   "TARGET_SIMD"
5850   "sshl\t%0.2s, %1.2s, %2.2s"
5851   [(set_attr "type" "neon_shift_reg")]
5854 (define_insn "*aarch64_sisd_neg_qi"
5855   [(set (match_operand:QI 0 "register_operand" "=w")
5856         (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
5857                    UNSPEC_SISD_NEG))]
5858   "TARGET_SIMD"
5859   "neg\t%d0, %d1"
5860   [(set_attr "type" "neon_neg")]
5863 ;; Rotate right
5864 (define_insn "*ror<mode>3_insn"
5865   [(set (match_operand:GPI 0 "register_operand")
5866      (rotatert:GPI
5867        (match_operand:GPI 1 "register_operand")
5868        (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>")))]
5869   ""
5870   {@ [ cons: =0 , 1 , 2         ; attrs: type ]
5871      [ r        , r , Us<cmode> ; rotate_imm  ] ror\t%<w>0, %<w>1, %2
5872      [ r        , r , r         ; shift_reg   ] ror\t%<w>0, %<w>1, %<w>2
5873   }
5876 (define_insn "*rol<mode>3_insn"
5877   [(set (match_operand:GPI 0 "register_operand" "=r")
5878         (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
5879                     (match_operand 2 "const_int_operand" "n")))]
5880   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
5882   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5883   return "ror\\t%<w>0, %<w>1, %3";
5885   [(set_attr "type" "rotate_imm")]
5888 ;; zero_extend version of shifts
5889 (define_insn "*<optab>si3_insn_uxtw"
5890   [(set (match_operand:DI 0 "register_operand")
5891         (zero_extend:DI (SHIFT_no_rotate:SI
5892          (match_operand:SI 1 "register_operand")
5893          (match_operand:QI 2 "aarch64_reg_or_shift_imm_si"))))]
5894   ""
5895   {@ [ cons: =0 , 1 , 2   ; attrs: type ]
5896      [ r        , r , Uss ; bfx         ] <shift>\t%w0, %w1, %2
5897      [ r        , r , r   ; shift_reg   ] <shift>\t%w0, %w1, %w2
5898   }
5901 ;; zero_extend version of rotate right
5902 (define_insn "*rorsi3_insn_uxtw"
5903   [(set (match_operand:DI 0 "register_operand" "=r")
5904         (zero_extend:DI
5905          (rotatert:SI (match_operand:SI 1 "register_operand" "r")
5906                     (match_operand 2 "const_int_operand" "n"))))]
5907   "UINTVAL (operands[2]) < 32"
5908   "ror\\t%w0, %w1, %2"
5909   [(set_attr "type" "rotate_imm")]
5912 ;; zero_extend version of rotate left
5913 (define_insn "*rolsi3_insn_uxtw"
5914   [(set (match_operand:DI 0 "register_operand" "=r")
5915         (zero_extend:DI
5916          (rotate:SI (match_operand:SI 1 "register_operand" "r")
5917                     (match_operand 2 "const_int_operand" "n"))))]
5918   "UINTVAL (operands[2]) < 32"
5920   operands[2] = GEN_INT (32 - UINTVAL (operands[2]));
5921   return "ror\\t%w0, %w1, %2";
5923   [(set_attr "type" "rotate_imm")]
5926 (define_insn "*<optab><mode>3_insn"
5927   [(set (match_operand:SHORT 0 "register_operand" "=r")
5928         (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
5929                       (match_operand 2 "const_int_operand" "n")))]
5930   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
5932   operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5933   return "<bfshift>\t%w0, %w1, %2, %3";
5935   [(set_attr "type" "bfx")]
5938 (define_insn "*extr<mode>5_insn"
5939   [(set (match_operand:GPI 0 "register_operand" "=r")
5940         (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5941                              (match_operand 3 "const_int_operand" "n"))
5942                  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
5943                                (match_operand 4 "const_int_operand" "n"))))]
5944   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5945    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
5946   "extr\\t%<w>0, %<w>1, %<w>2, %4"
5947   [(set_attr "type" "rotate_imm")]
5950 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5951 ;; so we have to match both orderings.
5952 (define_insn "*extr<mode>5_insn_alt"
5953   [(set (match_operand:GPI 0 "register_operand" "=r")
5954         (ior:GPI  (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
5955                                 (match_operand 4 "const_int_operand" "n"))
5956                   (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5957                               (match_operand 3 "const_int_operand" "n"))))]
5958   "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
5959    && (UINTVAL (operands[3]) + UINTVAL (operands[4])
5960        == GET_MODE_BITSIZE (<MODE>mode))"
5961   "extr\\t%<w>0, %<w>1, %<w>2, %4"
5962   [(set_attr "type" "rotate_imm")]
5965 ;; zero_extend version of the above
5966 (define_insn "*extrsi5_insn_uxtw"
5967   [(set (match_operand:DI 0 "register_operand" "=r")
5968         (zero_extend:DI
5969          (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
5970                             (match_operand 3 "const_int_operand" "n"))
5971                  (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
5972                               (match_operand 4 "const_int_operand" "n")))))]
5973   "UINTVAL (operands[3]) < 32 &&
5974    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
5975   "extr\\t%w0, %w1, %w2, %4"
5976   [(set_attr "type" "rotate_imm")]
5979 (define_insn "*extrsi5_insn_uxtw_alt"
5980   [(set (match_operand:DI 0 "register_operand" "=r")
5981         (zero_extend:DI
5982          (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
5983                                (match_operand 4 "const_int_operand" "n"))
5984                  (ashift:SI (match_operand:SI 1 "register_operand" "r")
5985                             (match_operand 3 "const_int_operand" "n")))))]
5986   "UINTVAL (operands[3]) < 32 &&
5987    (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
5988   "extr\\t%w0, %w1, %w2, %4"
5989   [(set_attr "type" "rotate_imm")]
5992 (define_insn "*extrsi5_insn_di"
5993   [(set (match_operand:SI 0 "register_operand" "=r")
5994         (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
5995                            (match_operand 3 "const_int_operand" "n"))
5996                 (match_operator:SI 6 "subreg_lowpart_operator"
5997                   [(zero_extract:DI
5998                      (match_operand:DI 2 "register_operand" "r")
5999                      (match_operand 5 "const_int_operand" "n")
6000                      (match_operand 4 "const_int_operand" "n"))])))]
6001   "UINTVAL (operands[3]) < 32
6002    && UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32
6003    && INTVAL (operands[3]) == INTVAL (operands[5])"
6004   "extr\\t%w0, %w1, %w2, %4"
6005   [(set_attr "type" "rotate_imm")]
6008 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
6009   [(set (match_operand:GPI 0 "register_operand" "=r")
6010         (ANY_EXTEND:GPI
6011          (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
6012                        (match_operand 2 "const_int_operand" "n"))))]
6013   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
6015   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
6016   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
6018   [(set_attr "type" "bfx")]
6021 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
6022   [(set (match_operand:GPI 0 "register_operand" "=r")
6023         (zero_extend:GPI
6024          (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
6025                          (match_operand 2 "const_int_operand" "n"))))]
6026   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
6028   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
6029   return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
6031   [(set_attr "type" "bfx")]
6034 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
6035   [(set (match_operand:GPI 0 "register_operand" "=r")
6036         (sign_extend:GPI
6037          (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
6038                          (match_operand 2 "const_int_operand" "n"))))]
6039   "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
6041   operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
6042   return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
6044   [(set_attr "type" "bfx")]
6047 ;; -------------------------------------------------------------------
6048 ;; Bitfields
6049 ;; -------------------------------------------------------------------
6051 (define_expand "<optab>"
6052   [(set (match_operand:DI 0 "register_operand")
6053         (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
6054                         (match_operand 2
6055                           "aarch64_simd_shift_imm_offset_di")
6056                         (match_operand 3 "aarch64_simd_shift_imm_di")))]
6057   ""
6058   {
6059     if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
6060                    1, GET_MODE_BITSIZE (DImode) - 1))
6061      FAIL;
6062   }
6066 (define_insn "*<optab><mode>"
6067   [(set (match_operand:GPI 0 "register_operand" "=r")
6068         (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
6069                          (match_operand 2
6070                            "aarch64_simd_shift_imm_offset_<mode>" "n")
6071                          (match_operand 3
6072                            "aarch64_simd_shift_imm_<mode>" "n")))]
6073   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
6074              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
6075   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
6076   [(set_attr "type" "bfx")]
6079 ;; When the bit position and width add up to 32 we can use a W-reg LSR
6080 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
6081 (define_split
6082   [(set (match_operand:DI 0 "register_operand")
6083         (zero_extract:DI (match_operand:DI 1 "register_operand")
6084                          (match_operand 2
6085                            "aarch64_simd_shift_imm_offset_di")
6086                          (match_operand 3
6087                            "aarch64_simd_shift_imm_di")))]
6088   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
6089              GET_MODE_BITSIZE (DImode) - 1)
6090    && (INTVAL (operands[2]) + INTVAL (operands[3]))
6091        == GET_MODE_BITSIZE (SImode)"
6092   [(set (match_dup 0)
6093         (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
6094   {
6095     operands[4] = gen_lowpart (SImode, operands[1]);
6096   }
6099 ;; Bitfield Insert (insv)
6100 (define_expand "insv<mode>"
6101   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
6102                           (match_operand 1 "const_int_operand")
6103                           (match_operand 2 "const_int_operand"))
6104         (match_operand:GPI 3 "general_operand"))]
6105   ""
6107   unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
6108   unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
6109   rtx value = operands[3];
6111   if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
6112     FAIL;
6114   if (CONST_INT_P (value))
6115     {
6116       unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
6118       /* Prefer AND/OR for inserting all zeros or all ones.  */
6119       if ((UINTVAL (value) & mask) == 0
6120            || (UINTVAL (value) & mask) == mask)
6121         FAIL;
6123       /* 16-bit aligned 16-bit wide insert is handled by insv_imm.  */
6124       if (width == 16 && (pos % 16) == 0)
6125         DONE;
6126     }
6127   operands[3] = force_reg (<MODE>mode, value);
6130 (define_insn "*insv_reg<mode>_<SUBDI_BITS>"
6131   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r,w,?w")
6132                           (const_int SUBDI_BITS)
6133                           (match_operand 1 "const_int_operand"))
6134         (match_operand:GPI 2 "register_operand" "r,w,r"))]
6135   "multiple_p (UINTVAL (operands[1]), <SUBDI_BITS>)
6136    && UINTVAL (operands[1]) + <SUBDI_BITS> <= <GPI:sizen>"
6137   {
6138     if (which_alternative == 0)
6139       return "bfi\t%<w>0, %<w>2, %1, <SUBDI_BITS>";
6141     operands[1] = gen_int_mode (UINTVAL (operands[1]) / <SUBDI_BITS>, SImode);
6142     if (which_alternative == 1)
6143       return "ins\t%0.<bits_etype>[%1], %2.<bits_etype>[0]";
6144     return "ins\t%0.<bits_etype>[%1], %w2";
6145   }
6146   [(set_attr "type" "bfm,neon_ins_q,neon_ins_q")]
6149 (define_insn "*insv_reg<mode>"
6150   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
6151                           (match_operand 1 "const_int_operand" "n")
6152                           (match_operand 2 "const_int_operand" "n"))
6153         (match_operand:GPI 3 "register_operand" "r"))]
6154   "!(UINTVAL (operands[1]) == 0
6155      || (UINTVAL (operands[2]) + UINTVAL (operands[1])
6156          > GET_MODE_BITSIZE (<MODE>mode)))"
6157   "bfi\\t%<w>0, %<w>3, %2, %1"
6158   [(set_attr "type" "bfm")]
6161 (define_insn_and_split "*aarch64_bfi<GPI:mode><ALLX:mode>_<SUBDI_BITS>"
6162   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r,w,?w")
6163                           (const_int SUBDI_BITS)
6164                           (match_operand 1 "const_int_operand"))
6165         (zero_extend:GPI (match_operand:ALLX 2  "register_operand" "r,w,r")))]
6166   "<SUBDI_BITS> <= <ALLX:sizen>
6167    && multiple_p (UINTVAL (operands[1]), <SUBDI_BITS>)
6168    && UINTVAL (operands[1]) + <SUBDI_BITS> <= <GPI:sizen>"
6169   "#"
6170   "&& 1"
6171   [(set (zero_extract:GPI (match_dup 0)
6172                           (const_int SUBDI_BITS)
6173                           (match_dup 1))
6174         (match_dup 2))]
6175   {
6176     operands[2] = lowpart_subreg (<GPI:MODE>mode, operands[2],
6177                                   <ALLX:MODE>mode);
6178   }
6179   [(set_attr "type" "bfm,neon_ins_q,neon_ins_q")]
6182 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
6183   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
6184                           (match_operand 1 "const_int_operand" "n")
6185                           (match_operand 2 "const_int_operand" "n"))
6186         (zero_extend:GPI (match_operand:ALLX 3  "register_operand" "r")))]
6187   "UINTVAL (operands[1]) <= <ALLX:sizen>"
6188   "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
6189   [(set_attr "type" "bfm")]
6192 (define_insn_and_split "*aarch64_bfidi<ALLX:mode>_subreg_<SUBDI_BITS>"
6193   [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r,w,?w")
6194                          (const_int SUBDI_BITS)
6195                          (match_operand 1 "const_int_operand"))
6196         (match_operator:DI 2 "subreg_lowpart_operator"
6197           [(zero_extend:SI
6198              (match_operand:ALLX 3  "register_operand" "r,w,r"))]))]
6199   "<SUBDI_BITS> <= <ALLX:sizen>
6200    && multiple_p (UINTVAL (operands[1]), <SUBDI_BITS>)
6201    && UINTVAL (operands[1]) + <SUBDI_BITS> <= 64"
6202   "#"
6203   "&& 1"
6204   [(set (zero_extract:DI (match_dup 0)
6205                          (const_int SUBDI_BITS)
6206                          (match_dup 1))
6207         (match_dup 2))]
6208   {
6209     operands[2] = lowpart_subreg (DImode, operands[3], <ALLX:MODE>mode);
6210   }
6211   [(set_attr "type" "bfm,neon_ins_q,neon_ins_q")]
6214 ;;  Match a bfi instruction where the shift of OP3 means that we are
6215 ;;  actually copying the least significant bits of OP3 into OP0 by way
6216 ;;  of the AND masks and the IOR instruction.  A similar instruction
6217 ;;  with the two parts of the IOR swapped around was never triggered
6218 ;;  in a bootstrap build and test of GCC so it was not included.
6220 (define_insn "*aarch64_bfi<GPI:mode>5_shift"
6221   [(set (match_operand:GPI 0 "register_operand" "=r")
6222         (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
6223                           (match_operand:GPI 2 "const_int_operand" "n"))
6224                  (and:GPI (ashift:GPI
6225                            (match_operand:GPI 3 "register_operand" "r")
6226                            (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n"))
6227                           (match_operand:GPI 5 "const_int_operand" "n"))))]
6228   "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]),
6229                                       UINTVAL (operands[4]),
6230                                       UINTVAL(operands[5]))"
6231   "bfi\t%<GPI:w>0, %<GPI:w>3, %4, %P5"
6232   [(set_attr "type" "bfm")]
6235 (define_insn "*aarch64_bfi<GPI:mode>5_shift_alt"
6236   [(set (match_operand:GPI 0 "register_operand" "=r")
6237         (ior:GPI (and:GPI (ashift:GPI
6238                            (match_operand:GPI 1 "register_operand" "r")
6239                            (match_operand:GPI 2 "aarch64_simd_shift_imm_<mode>" "n"))
6240                           (match_operand:GPI 3 "const_int_operand" "n"))
6241                  (and:GPI (match_operand:GPI 4 "register_operand" "0")
6242                           (match_operand:GPI 5 "const_int_operand" "n"))))]
6243   "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[5]),
6244                                       UINTVAL (operands[2]),
6245                                       UINTVAL(operands[3]))"
6246   "bfi\t%<GPI:w>0, %<GPI:w>1, %2, %P3"
6247   [(set_attr "type" "bfm")]
6250 ;; Like *aarch64_bfi<GPI:mode>5_shift but with no and of the ashift because
6251 ;; the shift is large enough to remove the need for an AND instruction.
6253 (define_insn "*aarch64_bfi<GPI:mode>4_noand"
6254   [(set (match_operand:GPI 0 "register_operand" "=r")
6255         (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
6256                           (match_operand:GPI 2 "const_int_operand" "n"))
6257                  (ashift:GPI
6258                           (match_operand:GPI 3 "register_operand" "r")
6259                           (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n"))))]
6260   "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]),
6261                                       UINTVAL (operands[4]),
6262                                       HOST_WIDE_INT_M1U << UINTVAL (operands[4]) )"
6264   operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[4]));
6265   return "bfi\t%<GPI:w>0, %<GPI:w>3, %4, %5";
6267   [(set_attr "type" "bfm")]
6270 (define_insn "*aarch64_bfi<GPI:mode>4_noand_alt"
6271   [(set (match_operand:GPI 0 "register_operand" "=r")
6272         (ior:GPI (ashift:GPI
6273                           (match_operand:GPI 1 "register_operand" "r")
6274                           (match_operand:GPI 2 "aarch64_simd_shift_imm_<mode>" "n"))
6275                  (and:GPI (match_operand:GPI 3 "register_operand" "0")
6276                           (match_operand:GPI 4 "const_int_operand" "n"))))]
6277   "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[4]),
6278                                       UINTVAL (operands[2]),
6279                                       HOST_WIDE_INT_M1U << UINTVAL (operands[2]) )"
6281   operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[2]));
6282   return "bfi\t%<GPI:w>0, %<GPI:w>1, %2, %5";
6284   [(set_attr "type" "bfm")]
6287 ;; Like *aarch64_bfi<GPI:mode>5_shift but with no shifting, we are just
6288 ;; copying the least significant bits of OP3 to OP0.  We need two versions
6289 ;; of the instruction to handle different checks on the constant values.
6291 (define_insn "*aarch64_bfi<GPI:mode>4_noshift"
6292   [(set (match_operand:GPI 0 "register_operand" "=r")
6293         (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
6294                           (match_operand:GPI 2 "const_int_operand" "n"))
6295                  (and:GPI (match_operand:GPI 3 "register_operand" "r")
6296                           (match_operand:GPI 4 "const_int_operand" "n"))))]
6297   "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]), 0,
6298                                       UINTVAL (operands[4]))"
6299   "bfi\t%<GPI:w>0, %<GPI:w>3, 0, %P4"
6300   [(set_attr "type" "bfm")]
6303 (define_insn "*aarch64_bfi<GPI:mode>4_noshift_alt"
6304   [(set (match_operand:GPI 0 "register_operand" "=r")
6305         (ior:GPI (and:GPI (match_operand:GPI 3 "register_operand" "r")
6306                           (match_operand:GPI 4 "const_int_operand" "n"))
6307                  (and:GPI (match_operand:GPI 1 "register_operand" "0")
6308                           (match_operand:GPI 2 "const_int_operand" "n"))))]
6309   "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]), 0,
6310                                       UINTVAL (operands[4]))"
6311   "bfi\t%<GPI:w>0, %<GPI:w>3, 0, %P4"
6312   [(set_attr "type" "bfm")]
6315 (define_insn "*aarch64_bfxil<mode>_extr"
6316   [(set (match_operand:GPI 0 "register_operand" "=r")
6317         (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
6318                           (match_operand:GPI 2 "const_int_operand" "n"))
6319                  (zero_extract:GPI
6320                    (match_operand:GPI 3 "register_operand" "r")
6321                    (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n")
6322                    (match_operand:GPI 5 "aarch64_simd_shift_imm_<mode>" "n"))))]
6323   "UINTVAL (operands[2]) == HOST_WIDE_INT_M1U << INTVAL (operands[4])
6324    && INTVAL (operands[4])
6325    && (UINTVAL (operands[4]) + UINTVAL (operands[5])
6326        <= GET_MODE_BITSIZE (<MODE>mode))"
6327   "bfxil\t%<GPI:w>0, %<GPI:w>3, %5, %4"
6328   [(set_attr "type" "bfm")]
6331 (define_insn "*aarch64_bfxilsi_extrdi"
6332   [(set (match_operand:SI 0 "register_operand" "=r")
6333         (ior:SI (and:SI (match_operand:SI 1 "register_operand" "0")
6334                         (match_operand:SI 2 "const_int_operand" "n"))
6335                 (match_operator:SI 6 "subreg_lowpart_operator"
6336                   [(zero_extract:DI
6337                      (match_operand:DI 3 "register_operand" "r")
6338                      (match_operand:SI 4 "aarch64_simd_shift_imm_si" "n")
6339                      (match_operand:SI 5 "aarch64_simd_shift_imm_si" "n"))])))]
6340   "UINTVAL (operands[2]) == HOST_WIDE_INT_M1U << INTVAL (operands[4])
6341    && INTVAL (operands[4])
6342    && UINTVAL (operands[4]) + UINTVAL (operands[5]) <= 32"
6343   "bfxil\t%w0, %w3, %5, %4"
6344   [(set_attr "type" "bfm")]
6347 (define_insn "*extr_insv_lower_reg<mode>"
6348   [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
6349                           (match_operand 1 "const_int_operand" "n")
6350                           (const_int 0))
6351         (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
6352                           (match_dup 1)
6353                           (match_operand 3 "const_int_operand" "n")))]
6354   "!(UINTVAL (operands[1]) == 0
6355      || (UINTVAL (operands[3]) + UINTVAL (operands[1])
6356          > GET_MODE_BITSIZE (<MODE>mode)))"
6357   "bfxil\\t%<w>0, %<w>2, %3, %1"
6358   [(set_attr "type" "bfm")]
6361 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
6362   [(set (match_operand:GPI 0 "register_operand" "=r")
6363         (ashift:GPI (ANY_EXTEND:GPI
6364                      (match_operand:ALLX 1 "register_operand" "r"))
6365                     (match_operand 2 "const_int_operand" "n")))]
6366   "UINTVAL (operands[2]) < <GPI:sizen>"
6368   operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
6369               ? GEN_INT (<ALLX:sizen>)
6370               : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
6371   return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
6373   [(set_attr "type" "bfx")]
6376 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
6378 (define_insn "*andim_ashift<mode>_bfiz"
6379   [(set (match_operand:GPI 0 "register_operand" "=r")
6380         (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
6381                              (match_operand 2 "const_int_operand" "n"))
6382                  (match_operand 3 "const_int_operand" "n")))]
6383   "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
6384   "ubfiz\\t%<w>0, %<w>1, %2, %P3"
6385   [(set_attr "type" "bfx")]
6388 ;; Match sbfiz pattern in a shift left + shift right operation.
6390 (define_insn "*ashift<mode>_extv_bfiz"
6391   [(set (match_operand:GPI 0 "register_operand" "=r")
6392         (ashift:GPI (sign_extract:GPI (match_operand:GPI 1 "register_operand" "r")
6393                                       (match_operand 2 "aarch64_simd_shift_imm_offset_<mode>" "n")
6394                                       (const_int 0))
6395                      (match_operand 3 "aarch64_simd_shift_imm_<mode>" "n")))]
6396   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
6397              1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
6398   "sbfiz\\t%<w>0, %<w>1, %3, %2"
6399   [(set_attr "type" "bfx")]
6402 (define_insn "*ashiftsi_extvdi_bfiz"
6403   [(set (match_operand:SI 0 "register_operand" "=r")
6404         (ashift:SI
6405           (match_operator:SI 4 "subreg_lowpart_operator"
6406             [(sign_extract:DI
6407                (match_operand:DI 1 "register_operand" "r")
6408                (match_operand 2 "aarch64_simd_shift_imm_offset_si")
6409                (const_int 0))])
6410           (match_operand 3 "aarch64_simd_shift_imm_si")))]
6411   "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
6412              1, GET_MODE_BITSIZE (SImode) - 1)"
6413   "sbfiz\\t%w0, %w1, %3, %2"
6414   [(set_attr "type" "bfx")]
6417 ;; When the bit position and width of the equivalent extraction add up to 32
6418 ;; we can use a W-reg LSL instruction taking advantage of the implicit
6419 ;; zero-extension of the X-reg.
6420 (define_split
6421   [(set (match_operand:DI 0 "register_operand")
6422         (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
6423                              (match_operand 2 "const_int_operand"))
6424                  (match_operand 3 "const_int_operand")))]
6425  "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
6426   && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
6427       == GET_MODE_BITSIZE (SImode)"
6428   [(set (match_dup 0)
6429         (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
6430   {
6431     operands[4] = gen_lowpart (SImode, operands[1]);
6432   }
6435 (define_insn "bswap<mode>2"
6436   [(set (match_operand:GPI 0 "register_operand" "=r")
6437         (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
6438   ""
6439   "rev\\t%<w>0, %<w>1"
6440   [(set_attr "type" "rev")]
6443 (define_insn "bswaphi2"
6444   [(set (match_operand:HI 0 "register_operand" "=r")
6445         (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
6446   ""
6447   "rev16\\t%w0, %w1"
6448   [(set_attr "type" "rev")]
6451 (define_insn "*aarch64_bfxil<mode>"
6452   [(set (match_operand:GPI 0 "register_operand" "=r,r")
6453     (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "r,0")
6454                     (match_operand:GPI 3 "const_int_operand" "n, Ulc"))
6455             (and:GPI (match_operand:GPI 2 "register_operand" "0,r")
6456                     (match_operand:GPI 4 "const_int_operand" "Ulc, n"))))]
6457   "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
6458   && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
6459     || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
6460   {
6461     switch (which_alternative)
6462     {
6463       case 0:
6464         operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
6465         return "bfxil\\t%<w>0, %<w>1, 0, %3";
6466       case 1:
6467         operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
6468         return "bfxil\\t%<w>0, %<w>2, 0, %3";
6469       default:
6470         gcc_unreachable ();
6471     }
6472   }
6473   [(set_attr "type" "bfm")]
6476 ; Zero-extended version of above (aarch64_bfxil)
6477 (define_insn "*aarch64_bfxilsi_uxtw"
6478   [(set (match_operand:DI 0 "register_operand" "=r,r")
6479         (zero_extend:DI (ior:SI (and:SI (match_operand:SI 1 "register_operand"
6480                                         "r,0")
6481                     (match_operand:SI 3 "const_int_operand" "n, Ulc"))
6482             (and:SI (match_operand:SI 2 "register_operand" "0,r")
6483                     (match_operand:SI 4 "const_int_operand" "Ulc, n")))))]
6484   "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
6485   && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
6486     || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
6487   {
6488     switch (which_alternative)
6489     {
6490       case 0:
6491         operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
6492         return "bfxil\\t%w0, %w1, 0, %3";
6493       case 1:
6494         operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
6495         return "bfxil\\t%w0, %w2, 0, %3";
6496       default:
6497         gcc_unreachable ();
6498     }
6499   }
6500   [(set_attr "type" "bfm")]
6503 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
6504 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
6505 ;; each valid permutation.
6507 (define_insn "aarch64_rev16<mode>2_alt1"
6508   [(set (match_operand:GPI 0 "register_operand" "=r")
6509         (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
6510                                       (const_int 8))
6511                           (match_operand:GPI 3 "const_int_operand" "n"))
6512                  (and:GPI (lshiftrt:GPI (match_dup 1)
6513                                         (const_int 8))
6514                           (match_operand:GPI 2 "const_int_operand" "n"))))]
6515   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
6516    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
6517   "rev16\\t%<w>0, %<w>1"
6518   [(set_attr "type" "rev")]
6521 (define_insn "*aarch64_rev16<mode>2_alt2"
6522   [(set (match_operand:GPI 0 "register_operand" "=r")
6523         (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
6524                                         (const_int 8))
6525                           (match_operand:GPI 2 "const_int_operand" "n"))
6526                  (and:GPI (ashift:GPI (match_dup 1)
6527                                       (const_int 8))
6528                           (match_operand:GPI 3 "const_int_operand" "n"))))]
6529   "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
6530    && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
6531   "rev16\\t%<w>0, %<w>1"
6532   [(set_attr "type" "rev")]
6535 ;; Similar pattern to match (rotate (bswap) 16)
6536 (define_insn "aarch64_rev16si2_alt3"
6537   [(set (match_operand:SI 0 "register_operand" "=r")
6538         (rotate:SI (bswap:SI (match_operand:SI 1 "register_operand" "r"))
6539                    (const_int 16)))]
6540   ""
6541   "rev16\\t%w0, %w1"
6542   [(set_attr "type" "rev")]
6545 ;; zero_extend version of above
6546 (define_insn "*bswapsi2_uxtw"
6547   [(set (match_operand:DI 0 "register_operand" "=r")
6548         (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
6549   ""
6550   "rev\\t%w0, %w1"
6551   [(set_attr "type" "rev")]
6554 ;; Expander for __rev16 intrinsics.  We have organic RTL patterns for rev16 above.
6555 ;; Use this expander to just create the shift constants needed.
6556 (define_expand "@aarch64_rev16<mode>"
6557   [(match_operand:GPI 0 "register_operand")
6558    (match_operand:GPI 1 "register_operand")]
6559   ""
6560   {
6561     rtx left = gen_int_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff00), <MODE>mode);
6562     rtx right = gen_int_mode (HOST_WIDE_INT_C (0xff00ff00ff00ff), <MODE>mode);
6563     emit_insn (gen_aarch64_rev16<mode>2_alt1 (operands[0], operands[1],
6564                                               right, left));
6565     DONE;
6566   }
6569 ;; -------------------------------------------------------------------
6570 ;; Floating-point intrinsics
6571 ;; -------------------------------------------------------------------
6573 ;; frint floating-point round to integral standard patterns.
6574 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, roundeven.
6576 (define_insn "<frint_pattern><mode>2"
6577   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6578         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
6579          FRINT))]
6580   "TARGET_FLOAT"
6581   "frint<frint_suffix>\\t%<s>0, %<s>1"
6582   [(set_attr "type" "f_rint<stype>")]
6585 ;; frcvt floating-point round to integer and convert standard patterns.
6586 ;; Expands to lbtrunc, lceil, lfloor, lround.
6587 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
6588   [(set (match_operand:GPI 0 "register_operand" "=r")
6589         (FIXUORS:GPI
6590           (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
6591            FCVT)))]
6592   "TARGET_FLOAT"
6593   "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
6594   [(set_attr "type" "f_cvtf2i")]
6597 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
6598   [(set (match_operand:GPI 0 "register_operand" "=r")
6599         (FIXUORS:GPI
6600           (mult:GPF
6601             (match_operand:GPF 1 "register_operand" "w")
6602             (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
6603   "TARGET_FLOAT
6604    && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
6605                 GET_MODE_BITSIZE (<GPI:MODE>mode))"
6606   {
6607     int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
6608     char buf[64];
6609     snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
6610     output_asm_insn (buf, operands);
6611     return "";
6612   }
6613   [(set_attr "type" "f_cvtf2i")]
6616 ;; fma - expand fma into patterns with the accumulator operand first since
6617 ;; reusing the accumulator results in better register allocation.
6618 ;; The register allocator considers copy preferences in operand order,
6619 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
6621 (define_expand "fma<mode>4"
6622   [(set (match_operand:GPF_F16 0 "register_operand")
6623         (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand")
6624                      (match_operand:GPF_F16 2 "register_operand")
6625                      (match_operand:GPF_F16 3 "register_operand")))]
6626   "TARGET_FLOAT"
6629 (define_insn "*aarch64_fma<mode>4"
6630   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6631         (fma:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w")
6632                      (match_operand:GPF_F16 3 "register_operand" "w")
6633                      (match_operand:GPF_F16 1 "register_operand" "w")))]
6634   "TARGET_FLOAT"
6635   "fmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
6636   [(set_attr "type" "fmac<stype>")]
6639 (define_expand "fnma<mode>4"
6640   [(set (match_operand:GPF_F16 0 "register_operand")
6641         (fma:GPF_F16
6642           (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand"))
6643           (match_operand:GPF_F16 2 "register_operand")
6644           (match_operand:GPF_F16 3 "register_operand")))]
6645   "TARGET_FLOAT"
6648 (define_insn "*aarch64_fnma<mode>4"
6649   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6650         (fma:GPF_F16
6651           (neg:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w"))
6652           (match_operand:GPF_F16 3 "register_operand" "w")
6653           (match_operand:GPF_F16 1 "register_operand" "w")))]
6654   "TARGET_FLOAT"
6655   "fmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
6656   [(set_attr "type" "fmac<stype>")]
6660 (define_expand "fms<mode>4"
6661   [(set (match_operand:GPF 0 "register_operand")
6662         (fma:GPF (match_operand:GPF 1 "register_operand")
6663                  (match_operand:GPF 2 "register_operand")
6664                  (neg:GPF (match_operand:GPF 3 "register_operand"))))]
6665   "TARGET_FLOAT"
6668 (define_insn "*aarch64_fms<mode>4"
6669   [(set (match_operand:GPF 0 "register_operand" "=w")
6670         (fma:GPF (match_operand:GPF 2 "register_operand" "w")
6671                  (match_operand:GPF 3 "register_operand" "w")
6672                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
6673   "TARGET_FLOAT"
6674   "fnmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
6675   [(set_attr "type" "fmac<s>")]
6678 (define_expand "fnms<mode>4"
6679   [(set (match_operand:GPF 0 "register_operand")
6680         (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand"))
6681                  (match_operand:GPF 2 "register_operand")
6682                  (neg:GPF (match_operand:GPF 3 "register_operand"))))]
6683   "TARGET_FLOAT"
6686 (define_insn "*aarch64_fnms<mode>4"
6687   [(set (match_operand:GPF 0 "register_operand" "=w")
6688         (fma:GPF (neg:GPF (match_operand:GPF 2 "register_operand" "w"))
6689                  (match_operand:GPF 3 "register_operand" "w")
6690                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
6691   "TARGET_FLOAT"
6692   "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
6693   [(set_attr "type" "fmac<s>")]
6696 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
6697 (define_insn "*aarch64_fnmadd<mode>4"
6698   [(set (match_operand:GPF 0 "register_operand" "=w")
6699         (neg:GPF (fma:GPF (match_operand:GPF 2 "register_operand" "w")
6700                           (match_operand:GPF 3 "register_operand" "w")
6701                           (match_operand:GPF 1 "register_operand" "w"))))]
6702   "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
6703   "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
6704   [(set_attr "type" "fmac<s>")]
6707 ;; -------------------------------------------------------------------
6708 ;; Floating-point conversions
6709 ;; -------------------------------------------------------------------
6711 (define_insn "extendsfdf2"
6712   [(set (match_operand:DF 0 "register_operand" "=w")
6713         (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
6714   "TARGET_FLOAT"
6715   "fcvt\\t%d0, %s1"
6716   [(set_attr "type" "f_cvt")]
6719 (define_insn "extendhfsf2"
6720   [(set (match_operand:SF 0 "register_operand" "=w")
6721         (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
6722   "TARGET_FLOAT"
6723   "fcvt\\t%s0, %h1"
6724   [(set_attr "type" "f_cvt")]
6727 (define_insn "extendhfdf2"
6728   [(set (match_operand:DF 0 "register_operand" "=w")
6729         (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
6730   "TARGET_FLOAT"
6731   "fcvt\\t%d0, %h1"
6732   [(set_attr "type" "f_cvt")]
6735 (define_insn "truncdfsf2"
6736   [(set (match_operand:SF 0 "register_operand" "=w")
6737         (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
6738   "TARGET_FLOAT"
6739   "fcvt\\t%s0, %d1"
6740   [(set_attr "type" "f_cvt")]
6743 (define_insn "truncsfhf2"
6744   [(set (match_operand:HF 0 "register_operand" "=w")
6745         (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
6746   "TARGET_FLOAT"
6747   "fcvt\\t%h0, %s1"
6748   [(set_attr "type" "f_cvt")]
6751 (define_insn "truncdfhf2"
6752   [(set (match_operand:HF 0 "register_operand" "=w")
6753         (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
6754   "TARGET_FLOAT"
6755   "fcvt\\t%h0, %d1"
6756   [(set_attr "type" "f_cvt")]
6759 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
6760 ;; and making r = w more expensive
6762 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>2"
6763   [(set (match_operand:GPI 0 "register_operand")
6764         (FIXUORS:GPI (match_operand:<FCVT_TARGET> 1 "register_operand")))]
6765   "TARGET_FLOAT"
6766   {@ [ cons: =0 , 1 ; attrs: type      , arch  ]
6767      [ w        , w ; neon_fp_to_int_s , simd  ] fcvtz<su>\t%<s>0, %<s>1
6768      [ ?r       , w ; f_cvtf2i         , fp    ] fcvtz<su>\t%<w>0, %<s>1
6769   }
6772 ;; Convert HF -> SI or DI
6774 (define_insn "<optab>_trunchf<GPI:mode>2"
6775   [(set (match_operand:GPI 0 "register_operand" "=r")
6776         (FIXUORS:GPI (match_operand:HF 1 "register_operand" "w")))]
6777   "TARGET_FP_F16INST"
6778   "fcvtz<su>\t%<w>0, %h1"
6779   [(set_attr "type" "f_cvtf2i")]
6782 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
6783 ;; input in a fp register and output in a integer register
6785 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>2"
6786   [(set (match_operand:GPI 0 "register_operand" "=r")
6787         (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand" "w")))]
6788   "TARGET_FLOAT"
6789   "fcvtz<su>\t%<w>0, %<fpw>1"
6790   [(set_attr "type" "f_cvtf2i")]
6793 (define_insn "*fix_to_zero_extend<mode>di2"
6794   [(set (match_operand:DI 0 "register_operand" "=r")
6795         (zero_extend:DI
6796          (unsigned_fix:SI
6797           (match_operand:GPF 1 "register_operand" "w"))))]
6798   "TARGET_FLOAT"
6799   "fcvtzu\t%w0, %<s>1"
6800   [(set_attr "type" "f_cvtf2i")]
6803 ;; Equal width integer to fp and multiply combine.
6804 (define_insn "*aarch64_<su_optab>cvtf<fcvt_target><GPF:mode>2_mult"
6805   [(set (match_operand:GPF 0 "register_operand" "=w,w")
6806         (mult:GPF (FLOATUORS:GPF
6807                    (match_operand:<FCVT_TARGET> 1 "register_operand" "w,?r"))
6808                    (match_operand:GPF 2 "aarch64_fp_pow2_recip" "Dt,Dt")))]
6809   "TARGET_FLOAT"
6810   {
6811     operands[2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[2]));
6812     switch (which_alternative)
6813     {
6814       case 0:
6815         return "<su_optab>cvtf\t%<GPF:s>0, %<s>1, #%2";
6816       case 1:
6817         return "<su_optab>cvtf\t%<GPF:s>0, %<w1>1, #%2";
6818       default:
6819         gcc_unreachable ();
6820     }
6821   }
6822   [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6823    (set_attr "arch" "simd,fp")]
6826 ;; Unequal width integer to fp and multiply combine.
6827 (define_insn "*aarch64_<su_optab>cvtf<fcvt_iesize><GPF:mode>2_mult"
6828   [(set (match_operand:GPF 0 "register_operand" "=w")
6829         (mult:GPF (FLOATUORS:GPF
6830                    (match_operand:<FCVT_IESIZE> 1 "register_operand" "r"))
6831                    (match_operand:GPF 2 "aarch64_fp_pow2_recip" "Dt")))]
6832   "TARGET_FLOAT"
6833   {
6834     operands[2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[2]));
6835     return "<su_optab>cvtf\t%<GPF:s>0, %<w2>1, #%2";
6836   }
6837   [(set_attr "type" "f_cvti2f")]
6840 ;; Equal width integer to fp conversion.
6841 (define_insn "<optab><fcvt_target><GPF:mode>2"
6842   [(set (match_operand:GPF 0 "register_operand")
6843         (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand")))]
6844   "TARGET_FLOAT"
6845   {@ [ cons: =0 , 1  ; attrs: type             , arch  ]
6846      [ w        , w  ; neon_int_to_fp_<Vetype> , simd  ] <su_optab>cvtf\t%<GPF:s>0, %<s>1
6847      [ w        , ?r ; f_cvti2f                , fp    ] <su_optab>cvtf\t%<GPF:s>0, %<w1>1
6848   }
6851 ;; Unequal width integer to fp conversions.
6852 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
6853   [(set (match_operand:GPF 0 "register_operand" "=w")
6854         (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
6855   "TARGET_FLOAT"
6856   "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
6857   [(set_attr "type" "f_cvti2f")]
6860 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
6861 ;; midend will arrange for an SImode conversion to HFmode to first go
6862 ;; through DFmode, then to HFmode.  But first it will try converting
6863 ;; to DImode then down, which would match our DImode pattern below and
6864 ;; give very poor code-generation.  So, we must provide our own emulation
6865 ;; of the mid-end logic.
6867 (define_insn "aarch64_fp16_<optab><mode>hf2"
6868   [(set (match_operand:HF 0 "register_operand" "=w")
6869         (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
6870   "TARGET_FP_F16INST"
6871   "<su_optab>cvtf\t%h0, %<w>1"
6872   [(set_attr "type" "f_cvti2f")]
6875 (define_expand "<optab>sihf2"
6876   [(set (match_operand:HF 0 "register_operand")
6877         (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
6878   "TARGET_FLOAT"
6880   if (TARGET_FP_F16INST)
6881     emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
6882   else
6883     {
6884       rtx convert_target = gen_reg_rtx (DFmode);
6885       emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
6886       emit_insn (gen_truncdfhf2 (operands[0], convert_target));
6887     }
6888   DONE;
6892 ;; For DImode there is no wide enough floating-point mode that we
6893 ;; can convert through natively (TFmode would work, but requires a library
6894 ;; call).  However, we know that any value >= 65504 will be rounded
6895 ;; to infinity on conversion.  This is well within the range of SImode, so
6896 ;; we can:
6897 ;;   Saturate to SImode.
6898 ;;   Convert from that to DFmode
6899 ;;   Convert from that to HFmode (phew!).
6900 ;; Note that the saturation to SImode requires the SIMD extensions.  If
6901 ;; we ever need to provide this pattern where the SIMD extensions are not
6902 ;; available, we would need a different approach.
6904 (define_expand "<optab>dihf2"
6905   [(set (match_operand:HF 0 "register_operand")
6906         (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
6907   "TARGET_FP_F16INST || TARGET_SIMD"
6909   if (TARGET_FP_F16INST)
6910     emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
6911   else
6912     {
6913       rtx sat_target = gen_reg_rtx (SImode);
6914       emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
6915       emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
6916     }
6918   DONE;
6922 ;; Convert between fixed-point and floating-point (scalar modes)
6924 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
6925   [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand")
6926         (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand")
6927                                    (match_operand:SI 2 "immediate_operand")]
6928          FCVT_F2FIXED))]
6929   ""
6930   {@ [ cons: =0 , 1 , 2 ; attrs: type                 , arch  ]
6931      [ r        , w , i ; f_cvtf2i                    , fp    ] <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
6932      [ w        , w , i ; neon_fp_to_int_<GPF:Vetype> , simd  ] <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2
6933   }
6936 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
6937   [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand")
6938         (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand")
6939                                    (match_operand:SI 2 "immediate_operand")]
6940          FCVT_FIXED2F))]
6941   ""
6942   {@ [ cons: =0 , 1 , 2 ; attrs: type                 , arch  ]
6943      [ w        , r , i ; f_cvti2f                    , fp    ] <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
6944      [ w        , w , i ; neon_int_to_fp_<GPI:Vetype> , simd  ] <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2
6945   }
6948 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
6949   [(set (match_operand:GPI 0 "register_operand" "=r")
6950         (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
6951                      (match_operand:SI 2 "immediate_operand" "i")]
6952          FCVT_F2FIXED))]
6953   "TARGET_FP_F16INST"
6954    "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
6955   [(set_attr "type" "f_cvtf2i")]
6958 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
6959   [(set (match_operand:HF 0 "register_operand" "=w")
6960         (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
6961                     (match_operand:SI 2 "immediate_operand" "i")]
6962          FCVT_FIXED2F))]
6963   "TARGET_FP_F16INST"
6964   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
6965   [(set_attr "type" "f_cvti2f")]
6968 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
6969   [(set (match_operand:HI 0 "register_operand" "=w")
6970         (unspec:HI [(match_operand:HF 1 "register_operand" "w")
6971                     (match_operand:SI 2 "immediate_operand" "i")]
6972          FCVT_F2FIXED))]
6973   "TARGET_SIMD"
6974   "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
6975   [(set_attr "type" "neon_fp_to_int_s")]
6978 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
6979   [(set (match_operand:HF 0 "register_operand" "=w")
6980         (unspec:HF [(match_operand:HI 1 "register_operand" "w")
6981                     (match_operand:SI 2 "immediate_operand" "i")]
6982          FCVT_FIXED2F))]
6983   "TARGET_SIMD"
6984   "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
6985   [(set_attr "type" "neon_int_to_fp_s")]
6988 ;; -------------------------------------------------------------------
6989 ;; Floating-point arithmetic
6990 ;; -------------------------------------------------------------------
6992 (define_insn "add<mode>3"
6993   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6994         (plus:GPF_F16
6995          (match_operand:GPF_F16 1 "register_operand" "w")
6996          (match_operand:GPF_F16 2 "register_operand" "w")))]
6997   "TARGET_FLOAT"
6998   "fadd\\t%<s>0, %<s>1, %<s>2"
6999   [(set_attr "type" "fadd<stype>")]
7002 (define_insn "sub<mode>3"
7003   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
7004         (minus:GPF_F16
7005          (match_operand:GPF_F16 1 "register_operand" "w")
7006          (match_operand:GPF_F16 2 "register_operand" "w")))]
7007   "TARGET_FLOAT"
7008   "fsub\\t%<s>0, %<s>1, %<s>2"
7009   [(set_attr "type" "fadd<stype>")]
7012 (define_insn "mul<mode>3"
7013   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
7014         (mult:GPF_F16
7015          (match_operand:GPF_F16 1 "register_operand" "w")
7016          (match_operand:GPF_F16 2 "register_operand" "w")))]
7017   "TARGET_FLOAT"
7018   "fmul\\t%<s>0, %<s>1, %<s>2"
7019   [(set_attr "type" "fmul<stype>")]
7022 (define_insn "*fnmul<mode>3"
7023   [(set (match_operand:GPF 0 "register_operand" "=w")
7024         (mult:GPF
7025                  (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
7026                  (match_operand:GPF 2 "register_operand" "w")))]
7027   "TARGET_FLOAT && !flag_rounding_math"
7028   "fnmul\\t%<s>0, %<s>1, %<s>2"
7029   [(set_attr "type" "fmul<s>")]
7032 (define_insn "*fnmul<mode>3"
7033   [(set (match_operand:GPF 0 "register_operand" "=w")
7034         (neg:GPF (mult:GPF
7035                  (match_operand:GPF 1 "register_operand" "w")
7036                  (match_operand:GPF 2 "register_operand" "w"))))]
7037   "TARGET_FLOAT"
7038   "fnmul\\t%<s>0, %<s>1, %<s>2"
7039   [(set_attr "type" "fmul<s>")]
7042 (define_expand "div<mode>3"
7043  [(set (match_operand:GPF_F16 0 "register_operand")
7044        (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
7045                     (match_operand:GPF_F16 2 "register_operand")))]
7046  "TARGET_FLOAT"
7048   if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
7049     DONE;
7051   operands[1] = force_reg (<MODE>mode, operands[1]);
7054 (define_insn "*div<mode>3"
7055   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
7056         (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
7057                      (match_operand:GPF_F16 2 "register_operand" "w")))]
7058   "TARGET_FLOAT"
7059   "fdiv\\t%<s>0, %<s>1, %<s>2"
7060   [(set_attr "type" "fdiv<stype>")]
7063 (define_insn "neg<mode>2"
7064   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
7065         (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
7066   "TARGET_FLOAT"
7067   "fneg\\t%<s>0, %<s>1"
7068   [(set_attr "type" "ffarith<stype>")]
7071 (define_expand "sqrt<mode>2"
7072   [(set (match_operand:GPF_F16 0 "register_operand")
7073         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand")))]
7074   "TARGET_FLOAT"
7076   if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
7077     DONE;
7080 (define_insn "*sqrt<mode>2"
7081   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
7082         (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
7083   "TARGET_FLOAT"
7084   "fsqrt\\t%<s>0, %<s>1"
7085   [(set_attr "type" "fsqrt<stype>")]
7088 (define_insn "abs<mode>2"
7089   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
7090         (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
7091   "TARGET_FLOAT"
7092   "fabs\\t%<s>0, %<s>1"
7093   [(set_attr "type" "ffarith<stype>")]
7096 ;; Expander for integer smin, smax, umin.  Mainly used to generate
7097 ;; straightforward RTL for TARGET_CSSC.  When that is not available
7098 ;; FAIL and let the generic expanders generate the CMP + CSEL sequences,
7099 ;; except for the SMIN and SMAX with zero cases, for which we have a
7100 ;; single instruction even for the base architecture.
7101 (define_expand "<optab><mode>3"
7102   [(set (match_operand:GPI 0 "register_operand")
7103         (MAXMIN_NOUMAX:GPI
7104           (match_operand:GPI 1 "register_operand")
7105           (match_operand:GPI 2 "aarch64_<su>minmax_operand")))]
7106   ""
7107   {
7108     if (!TARGET_CSSC)
7109       {
7110         if (operands[2] != CONST0_RTX (<MODE>mode)
7111             || !(<CODE> == SMAX || <CODE> == SMIN))
7112           FAIL;
7113       }
7114   }
7117 (define_insn "*aarch64_<optab><mode>3_cssc"
7118   [(set (match_operand:GPI 0 "register_operand")
7119         (MAXMIN:GPI (match_operand:GPI 1 "register_operand")
7120                 (match_operand:GPI 2 "aarch64_<su>minmax_operand")))]
7121   "TARGET_CSSC"
7122   {@ [ cons: =0 , 1 , 2      ; attrs: type ]
7123      [ r        , r , r      ; alu_sreg    ] <optab>\t%<w>0, %<w>1, %<w>2
7124      [ r        , r , U<su>m ; alu_imm     ] <optab>\t%<w>0, %<w>1, %2
7125   }
7128 (define_insn "*aarch64_<optab><mode>3_zero"
7129   [(set (match_operand:GPI 0 "register_operand" "=r")
7130         (FMAXMIN:GPI
7131           (match_operand:GPI 1 "register_operand" "r")
7132           (const_int 0)))]
7133   ""
7134   "<maxminand>\\t%<w>0, %<w>1, %<w>1, asr <sizem1>";
7135   [(set_attr "type" "logic_shift_imm")]
7138 ;; Given that smax/smin do not specify the result when either input is NaN,
7139 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
7140 ;; for smin.
7142 (define_insn "smax<mode>3"
7143   [(set (match_operand:GPF 0 "register_operand" "=w")
7144         (smax:GPF (match_operand:GPF 1 "register_operand" "w")
7145                   (match_operand:GPF 2 "register_operand" "w")))]
7146   "TARGET_FLOAT"
7147   "fmaxnm\\t%<s>0, %<s>1, %<s>2"
7148   [(set_attr "type" "f_minmax<s>")]
7151 (define_insn "smin<mode>3"
7152   [(set (match_operand:GPF 0 "register_operand" "=w")
7153         (smin:GPF (match_operand:GPF 1 "register_operand" "w")
7154                   (match_operand:GPF 2 "register_operand" "w")))]
7155   "TARGET_FLOAT"
7156   "fminnm\\t%<s>0, %<s>1, %<s>2"
7157   [(set_attr "type" "f_minmax<s>")]
7160 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
7161 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
7162 ;; which implement the IEEE fmax ()/fmin () functions.
7163 (define_insn "<fmaxmin><mode>3"
7164   [(set (match_operand:GPF_F16 0 "register_operand" "=w")
7165         (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
7166                      (match_operand:GPF_F16 2 "register_operand" "w")]
7167                      FMAXMIN_UNS))]
7168   "TARGET_FLOAT"
7169   "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
7170   [(set_attr "type" "f_minmax<stype>")]
7173 (define_expand "lrint<GPF:mode><GPI:mode>2"
7174   [(match_operand:GPI 0 "register_operand")
7175    (match_operand:GPF 1 "register_operand")]
7176   "TARGET_FLOAT
7177    && ((GET_MODE_BITSIZE (<GPF:MODE>mode) <= LONG_TYPE_SIZE)
7178    || !flag_trapping_math || flag_fp_int_builtin_inexact)"
7180   rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
7181   emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1]));
7182   emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt));
7183   DONE;
7187 ;; For copysign (x, y), we want to generate:
7189 ;;   LDR d2, #(1 << 63)
7190 ;;   BSL v2.8b, [y], [x]
7192 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.  Because
7193 ;; we expect these operations to nearly always operate on
7194 ;; floating-point values, we do not want the operation to be
7195 ;; simplified into a bit-field insert operation that operates on the
7196 ;; integer side, since typically that would involve three inter-bank
7197 ;; register copies.  As we do not expect copysign to be followed by
7198 ;; other logical operations on the result, it seems preferable to keep
7199 ;; this as an unspec operation, rather than exposing the underlying
7200 ;; logic to the compiler.
7202 (define_expand "copysign<GPF:mode>3"
7203   [(match_operand:GPF 0 "register_operand")
7204    (match_operand:GPF 1 "register_operand")
7205    (match_operand:GPF 2 "nonmemory_operand")]
7206   "TARGET_SIMD"
7208   rtx signbit_const = GEN_INT (HOST_WIDE_INT_M1U
7209                                << (GET_MODE_BITSIZE (<MODE>mode) - 1));
7210   /* copysign (x, -1) should instead be expanded as orr with the sign
7211      bit.  */
7212   rtx op2_elt = unwrap_const_vec_duplicate (operands[2]);
7213   if (GET_CODE (op2_elt) == CONST_DOUBLE
7214       && real_isneg (CONST_DOUBLE_REAL_VALUE (op2_elt)))
7215     {
7216       rtx v_bitmask
7217         = force_reg (V2<V_INT_EQUIV>mode,
7218                      gen_const_vec_duplicate (V2<V_INT_EQUIV>mode,
7219                                               signbit_const));
7221       emit_insn (gen_iorv2<v_int_equiv>3 (
7222         lowpart_subreg (V2<V_INT_EQUIV>mode, operands[0], <MODE>mode),
7223         lowpart_subreg (V2<V_INT_EQUIV>mode, operands[1], <MODE>mode),
7224         v_bitmask));
7225       DONE;
7226     }
7228   machine_mode int_mode = <V_INT_EQUIV>mode;
7229   rtx bitmask = gen_reg_rtx (int_mode);
7230   emit_move_insn (bitmask, signbit_const);
7231   operands[2] = force_reg (<MODE>mode, operands[2]);
7232   emit_insn (gen_copysign<mode>3_insn (operands[0], operands[1], operands[2],
7233                                        bitmask));
7234   DONE;
7238 (define_insn "copysign<GPF:mode>3_insn"
7239   [(set (match_operand:GPF 0 "register_operand")
7240         (unspec:GPF [(match_operand:GPF 1 "register_operand")
7241                      (match_operand:GPF 2 "register_operand")
7242                      (match_operand:<V_INT_EQUIV> 3 "register_operand")]
7243          UNSPEC_COPYSIGN))]
7244   "TARGET_SIMD"
7245   {@ [ cons: =0 , 1 , 2 , 3 ; attrs: type  ]
7246      [ w        , w , w , 0 ; neon_bsl<q>  ] bsl\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>
7247      [ w        , 0 , w , w ; neon_bsl<q>  ] bit\t%0.<Vbtype>, %2.<Vbtype>, %3.<Vbtype>
7248      [ w        , w , 0 , w ; neon_bsl<q>  ] bif\t%0.<Vbtype>, %1.<Vbtype>, %3.<Vbtype>
7249      [ r        , r , 0 , X ; bfm          ] bfxil\t%<w1>0, %<w1>1, #0, <sizem1>
7250   }
7254 ;; For xorsign (x, y), we want to generate:
7256 ;; LDR   d2, #1<<63
7257 ;; AND   v3.8B, v1.8B, v2.8B
7258 ;; EOR   v0.8B, v0.8B, v3.8B
7261 (define_expand "@xorsign<mode>3"
7262   [(match_operand:GPF 0 "register_operand")
7263    (match_operand:GPF 1 "register_operand")
7264    (match_operand:GPF 2 "register_operand")]
7265   "TARGET_SIMD"
7267   rtx tmp = gen_reg_rtx (<VCONQ>mode);
7268   rtx op1 = lowpart_subreg (<VCONQ>mode, operands[1], <MODE>mode);
7269   rtx op2 = lowpart_subreg (<VCONQ>mode, operands[2], <MODE>mode);
7270   emit_insn (gen_xorsign3 (<VCONQ>mode, tmp, op1, op2));
7271   emit_move_insn (operands[0],
7272                   lowpart_subreg (<MODE>mode, tmp, <VCONQ>mode));
7273   DONE;
7277 ;; -------------------------------------------------------------------
7278 ;; Reload support
7279 ;; -------------------------------------------------------------------
7280 ;; Reload Scalar Floating point modes from constant pool.
7281 ;; The AArch64 port doesn't have __int128 constant move support.
7282 ;; The patterns need constraints due to TARGET_SECONDARY_RELOAD hook.
7283 (define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
7284  [(set (match_operand:GPF_TF 0 "register_operand" "=w")
7285        (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
7286   (clobber (match_operand:P 2 "register_operand" "=&r"))]
7287  "TARGET_FLOAT"
7289    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
7290    emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
7291    DONE;
7295 ;; Reload Vector modes from constant pool.
7296 (define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
7297  [(set (match_operand:VALL 0 "register_operand" "=w")
7298        (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
7299   (clobber (match_operand:P 2 "register_operand" "=&r"))]
7300  "TARGET_FLOAT"
7302    aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
7303    emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
7304    DONE;
7308 (define_expand "@aarch64_reload_mov<mode>"
7309   [(set (match_operand:VTX 0 "register_operand" "=w")
7310         (match_operand:VTX 1 "register_operand" "w"))
7311    (clobber (match_operand:DI 2 "register_operand" "=&r"))
7312   ]
7313   "TARGET_FLOAT"
7314   {
7315     rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
7316     rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
7317     gen_aarch64_movtilow_tilow (op0, op1);
7318     gen_aarch64_movdi_tihigh (operands[2], op1);
7319     gen_aarch64_movtihigh_di (op0, operands[2]);
7320     DONE;
7321   }
7324 ;; The following secondary reload helpers patterns are invoked
7325 ;; after or during reload as we don't want these patterns to start
7326 ;; kicking in during the combiner.
7328 (define_insn "@aarch64_movdi_<mode>low"
7329   [(set (match_operand:DI 0 "register_operand" "=r")
7330         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
7331                          (const_int 64) (const_int 0)))]
7332   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
7333   "fmov\\t%x0, %d1"
7334   [(set_attr "type" "f_mrc")
7335    (set_attr "length" "4")
7336   ])
7338 (define_insn "@aarch64_movdi_<mode>high"
7339   [(set (match_operand:DI 0 "register_operand" "=r")
7340         (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
7341                          (const_int 64) (const_int 64)))]
7342   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
7343   "fmov\\t%x0, %1.d[1]"
7344   [(set_attr "type" "f_mrc")
7345    (set_attr "length" "4")
7346   ])
7348 (define_insn "@aarch64_mov<mode>high_di"
7349   [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
7350                          (const_int 64) (const_int 64))
7351         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
7352   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
7353   "fmov\\t%0.d[1], %x1"
7354   [(set_attr "type" "f_mcr")
7355    (set_attr "length" "4")
7356   ])
7358 (define_insn "@aarch64_mov<mode>low_di"
7359   [(set (match_operand:TX 0 "register_operand" "=w")
7360         (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
7361   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
7362   "fmov\\t%d0, %x1"
7363   [(set_attr "type" "f_mcr")
7364    (set_attr "length" "4")
7365   ])
7367 (define_insn "aarch64_movtilow_tilow"
7368   [(set (match_operand:TI 0 "register_operand" "=w")
7369         (zero_extend:TI
7370           (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
7371   "TARGET_FLOAT && (reload_completed || reload_in_progress)"
7372   "fmov\\t%d0, %d1"
7373   [(set_attr "type" "fmov")
7374    (set_attr "length" "4")
7375   ])
7377 ;; There is a deliberate reason why the parameters of high and lo_sum's
7378 ;; don't have modes for ADRP and ADD instructions.  This is to allow high
7379 ;; and lo_sum's to be used with the labels defining the jump tables in
7380 ;; rodata section.
7382 (define_expand "add_losym"
7383   [(set (match_operand 0 "register_operand")
7384         (lo_sum (match_operand 1 "register_operand")
7385                 (match_operand 2 "aarch64_valid_symref")))]
7386   ""
7388   machine_mode mode = GET_MODE (operands[0]);
7390   emit_insn ((mode == DImode
7391               ? gen_add_losym_di
7392               : gen_add_losym_si) (operands[0],
7393                                    operands[1],
7394                                    operands[2]));
7395   DONE;
7398 (define_insn "add_losym_<mode>"
7399   [(set (match_operand:P 0 "register_operand" "=r")
7400         (lo_sum:P (match_operand:P 1 "register_operand" "r")
7401                   (match_operand 2 "aarch64_valid_symref" "S")))]
7402   ""
7403   "add\\t%<w>0, %<w>1, :lo12:%c2"
7404   [(set_attr "type" "alu_imm")]
7407 (define_insn "ldr_got_small_28k_<mode>"
7408   [(set (match_operand:PTR 0 "register_operand" "=r")
7409         (unspec:PTR [(mem:PTR (lo_sum:PTR
7410                               (match_operand:PTR 1 "register_operand" "r")
7411                               (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
7412                     UNSPEC_GOTSMALLPIC28K))]
7413   ""
7414   "ldr\\t%<w>0, [%1, #:<got_modifier>:%c2]"
7415   [(set_attr "type" "load_<ldst_sz>")]
7418 (define_insn "ldr_got_small_28k_sidi"
7419   [(set (match_operand:DI 0 "register_operand" "=r")
7420         (zero_extend:DI
7421          (unspec:SI [(mem:SI (lo_sum:DI
7422                              (match_operand:DI 1 "register_operand" "r")
7423                              (match_operand:DI 2 "aarch64_valid_symref" "S")))]
7424                     UNSPEC_GOTSMALLPIC28K)))]
7425   "TARGET_ILP32"
7426   "ldr\\t%w0, [%1, #:gotpage_lo14:%c2]"
7427   [(set_attr "type" "load_4")]
7430 (define_insn "@ldr_got_tiny_<mode>"
7431   [(set (match_operand:PTR 0 "register_operand" "=r")
7432         (unspec:PTR [(match_operand:PTR 1 "aarch64_valid_symref" "S")]
7433                     UNSPEC_GOTTINYPIC))]
7434   ""
7435   "ldr\t%<w>0, %L1"
7436   [(set_attr "type" "load_<ldst_sz>")]
7439 (define_insn "ldr_got_tiny_sidi"
7440   [(set (match_operand:DI 0 "register_operand" "=r")
7441         (zero_extend:DI
7442           (unspec:SI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
7443                      UNSPEC_GOTTINYPIC)))]
7444   "TARGET_ILP32"
7445   "ldr\t%w0, %L1"
7446   [(set_attr "type" "load_4")]
7449 (define_insn "aarch64_load_tp_hard"
7450   [(set (match_operand:DI 0 "register_operand" "=r")
7451         (unspec:DI [(const_int 0)] UNSPEC_TLS))]
7452   ""
7453   "* return aarch64_output_load_tp (operands[0]);"
7454   [(set_attr "type" "mrs")]
7457 ;; The TLS ABI specifically requires that the compiler does not schedule
7458 ;; instructions in the TLS stubs, in order to enable linker relaxation.
7459 ;; Therefore we treat the stubs as an atomic sequence.
7460 (define_expand "tlsgd_small_<mode>"
7461  [(parallel [(set (match_operand:PTR 0 "register_operand")
7462                   (call (mem:DI (match_dup 2)) (const_int 1)))
7463              (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
7464              (unspec:DI [(match_operand 1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
7465              (clobber (reg:DI LR_REGNUM))])]
7466  ""
7468   operands[2] = aarch64_tls_get_addr ();
7471 (define_insn "*tlsgd_small_<mode>"
7472   [(set (match_operand:PTR 0 "register_operand" "")
7473         (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
7474    (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
7475    (unspec:DI [(match_operand 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
7476    (clobber (reg:DI LR_REGNUM))
7477   ]
7478   ""
7479   "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
7480   [(set_attr "type" "call")
7481    (set_attr "length" "16")])
7483 (define_insn "tlsie_small_<mode>"
7484   [(set (match_operand:PTR 0 "register_operand" "=r")
7485         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
7486                    UNSPEC_GOTSMALLTLS))]
7487   ""
7488   "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
7489   [(set_attr "type" "load_4")
7490    (set_attr "length" "8")]
7493 (define_insn "tlsie_small_sidi"
7494   [(set (match_operand:DI 0 "register_operand" "=r")
7495         (zero_extend:DI
7496           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
7497                       UNSPEC_GOTSMALLTLS)))]
7498   ""
7499   "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
7500   [(set_attr "type" "load_4")
7501    (set_attr "length" "8")]
7504 (define_insn "tlsie_tiny_<mode>"
7505   [(set (match_operand:PTR 0 "register_operand" "=&r")
7506         (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
7507                      (match_operand:PTR 2 "register_operand" "r")]
7508                    UNSPEC_GOTTINYTLS))]
7509   ""
7510   "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
7511   [(set_attr "type" "multiple")
7512    (set_attr "length" "8")]
7515 (define_insn "tlsie_tiny_sidi"
7516   [(set (match_operand:DI 0 "register_operand" "=&r")
7517         (zero_extend:DI
7518           (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
7519                       (match_operand:DI 2 "register_operand" "r")
7520                       ]
7521                       UNSPEC_GOTTINYTLS)))]
7522   ""
7523   "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
7524   [(set_attr "type" "multiple")
7525    (set_attr "length" "8")]
7528 (define_insn "tlsle12_<mode>"
7529   [(set (match_operand:P 0 "register_operand" "=r")
7530         (unspec:P [(match_operand:P 1 "register_operand" "r")
7531                    (match_operand 2 "aarch64_tls_le_symref" "S")]
7532                    UNSPEC_TLSLE12))]
7533   ""
7534   "add\\t%<w>0, %<w>1, #%L2";
7535   [(set_attr "type" "alu_sreg")
7536    (set_attr "length" "4")]
7539 (define_insn "tlsle24_<mode>"
7540   [(set (match_operand:P 0 "register_operand" "=r")
7541         (unspec:P [(match_operand:P 1 "register_operand" "r")
7542                    (match_operand 2 "aarch64_tls_le_symref" "S")]
7543                    UNSPEC_TLSLE24))]
7544   ""
7545   "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
7546   [(set_attr "type" "multiple")
7547    (set_attr "length" "8")]
7550 (define_insn "tlsle32_<mode>"
7551   [(set (match_operand:P 0 "register_operand" "=r")
7552         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
7553                    UNSPEC_TLSLE32))]
7554   ""
7555   "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
7556   [(set_attr "type" "multiple")
7557    (set_attr "length" "8")]
7560 (define_insn "tlsle48_<mode>"
7561   [(set (match_operand:P 0 "register_operand" "=r")
7562         (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
7563                    UNSPEC_TLSLE48))]
7564   ""
7565   "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
7566   [(set_attr "type" "multiple")
7567    (set_attr "length" "12")]
7570 (define_expand "tlsdesc_small_<mode>"
7571   [(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
7572   "TARGET_TLS_DESC"
7573   {
7574     if (TARGET_SVE)
7575       {
7576         rtx abi = aarch64_gen_callee_cookie (AARCH64_ISA_MODE,
7577                                              aarch64_tlsdesc_abi_id ());
7578         rtx_insn *call
7579           = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[0], abi));
7580         RTL_CONST_CALL_P (call) = 1;
7581       }
7582     else
7583       emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
7584     DONE;
7585   }
7588 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
7589 ;; R0 and LR.
7590 (define_insn "tlsdesc_small_advsimd_<mode>"
7591   [(set (reg:PTR R0_REGNUM)
7592         (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
7593                     UNSPEC_TLSDESC))
7594    (clobber (reg:DI LR_REGNUM))
7595    (clobber (reg:CC CC_REGNUM))
7596    (clobber (match_scratch:DI 1 "=r"))
7597    (use (reg:DI FP_REGNUM))]
7598   "TARGET_TLS_DESC && !TARGET_SVE"
7599   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
7600   [(set_attr "type" "call")
7601    (set_attr "length" "16")])
7603 ;; For SVE, model tlsdesc calls as normal calls, with the callee ABI
7604 ;; describing the extra call-preserved guarantees.  This would work
7605 ;; for non-SVE too, but avoiding a call is probably better if we can.
7606 (define_insn "tlsdesc_small_sve_<mode>"
7607   [(set (reg:PTR R0_REGNUM)
7608         (call (mem:DI (unspec:PTR
7609                         [(match_operand 0 "aarch64_valid_symref")]
7610                         UNSPEC_TLSDESC))
7611               (const_int 0)))
7612    (unspec:DI [(match_operand:DI 1 "const_int_operand")] UNSPEC_CALLEE_ABI)
7613    (clobber (reg:DI LR_REGNUM))]
7614   "TARGET_TLS_DESC && TARGET_SVE"
7615   "adrp\\tx0, %A0\;ldr\\t<w>30, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\tx30"
7616   [(set_attr "type" "call")
7617    (set_attr "length" "16")])
7619 (define_insn "stack_tie"
7620   [(set (mem:BLK (scratch))
7621         (unspec:BLK [(reg:DI SP_REGNUM)
7622                      (match_operand:DI 0 "register_operand" "rk")
7623                      (match_operand:DI 1 "const_int_operand")]
7624                     UNSPEC_PRLG_STK))]
7625   "REGNO (operands[0]) == INTVAL (operands[1])"
7626   ""
7627   [(set_attr "length" "0")]
7630 (define_insn "aarch64_fjcvtzs"
7631   [(set (match_operand:SI 0 "register_operand" "=r")
7632         (unspec:SI [(match_operand:DF 1 "register_operand" "w")]
7633                    UNSPEC_FJCVTZS))
7634    (clobber (reg:CC CC_REGNUM))]
7635   "TARGET_JSCVT"
7636   "fjcvtzs\\t%w0, %d1"
7637   [(set_attr "type" "f_cvtf2i")]
7640 ;; Pointer authentication patterns are always provided.  In architecture
7641 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
7642 ;; This lets the user write portable software which authenticates pointers
7643 ;; when run on something which implements ARMv8.3-A, and which runs
7644 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
7645 ;; implemented.
7647 ;; Signing/Authenticating R30 using SP as the salt.
7649 (define_insn "<pauth_mnem_prefix>sp"
7650   [(set (reg:DI R30_REGNUM)
7651         (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
7652   ""
7653   "hint\t<pauth_hint_num> // <pauth_mnem_prefix>sp";
7656 ;; Signing/Authenticating X17 using X16 as the salt.
7658 (define_insn "<pauth_mnem_prefix>1716"
7659   [(set (reg:DI R17_REGNUM)
7660         (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
7661   ""
7662   "hint\t<pauth_hint_num> // <pauth_mnem_prefix>1716";
7665 ;; Stripping the signature in R30.
7667 (define_insn "xpaclri"
7668   [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
7669   ""
7670   "hint\t7 // xpaclri"
7673 ;; Save X30 in the X18-based POST_INC stack (consistent with clang).
7674 (define_expand "scs_push"
7675   [(set (mem:DI (post_inc:DI (reg:DI R18_REGNUM)))
7676         (reg:DI R30_REGNUM))])
7678 ;; Load X30 form the X18-based PRE_DEC stack (consistent with clang).
7679 (define_expand "scs_pop"
7680   [(set (reg:DI R30_REGNUM)
7681         (mem:DI (pre_dec:DI (reg:DI R18_REGNUM))))])
7683 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7684 ;; all of memory.  This blocks insns from being moved across this point.
7686 (define_insn "blockage"
7687   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
7688   ""
7689   ""
7690   [(set_attr "length" "0")
7691    (set_attr "type" "block")]
7694 (define_insn "probe_stack_range"
7695   [(set (match_operand:DI 0 "register_operand" "=rk")
7696         (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
7697                              (match_operand:DI 2 "register_operand" "r")]
7698                               UNSPECV_PROBE_STACK_RANGE))]
7699   ""
7701   return aarch64_output_probe_stack_range (operands[0], operands[2]);
7703   [(set_attr "length" "32")]
7706 ;; This instruction is used to generate the stack clash stack adjustment and
7707 ;; probing loop.  We can't change the control flow during prologue and epilogue
7708 ;; code generation.  So we must emit a volatile unspec and expand it later on.
7710 (define_insn "@probe_sve_stack_clash_<mode>"
7711   [(set (match_operand:P 0 "register_operand" "=rk")
7712         (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
7713                             (match_operand:P 2 "register_operand" "r")
7714                             (match_operand:P 3 "const_int_operand" "n")
7715                             (match_operand:P 4 "aarch64_plus_immediate" "L")]
7716                              UNSPECV_PROBE_STACK_RANGE))]
7717   "TARGET_SVE"
7719   return aarch64_output_probe_sve_stack_clash (operands[0], operands[2],
7720                                                operands[3], operands[4]);
7722   [(set_attr "length" "28")]
7725 ;; Named pattern for expanding thread pointer reference.
7726 (define_expand "get_thread_pointerdi"
7727   [(match_operand:DI 0 "register_operand")]
7728   ""
7730   rtx tmp = aarch64_load_tp (operands[0]);
7731   if (tmp != operands[0])
7732     emit_move_insn (operands[0], tmp);
7733   DONE;
7736 ;; Defined for -mstack-protector-guard=sysreg, which goes through this
7737 ;; pattern rather than stack_protect_combined_set.  Our implementation
7738 ;; of the latter can handle both.
7739 (define_expand "stack_protect_set"
7740   [(match_operand 0 "memory_operand")
7741    (match_operand 1 "")]
7742   ""
7744   emit_insn (gen_stack_protect_combined_set (operands[0], operands[1]));
7745   DONE;
7748 (define_expand "stack_protect_combined_set"
7749   [(match_operand 0 "memory_operand")
7750    (match_operand 1 "")]
7751   ""
7753   machine_mode mode = GET_MODE (operands[0]);
7754   operands[1] = aarch64_stack_protect_canary_mem (mode, operands[1],
7755                                                   AARCH64_SALT_SSP_SET);
7756   emit_insn ((mode == DImode
7757               ? gen_stack_protect_set_di
7758               : gen_stack_protect_set_si) (operands[0], operands[1]));
7759   DONE;
7762 ;; Operand 1 is either AARCH64_SALT_SSP_SET or AARCH64_SALT_SSP_TEST.
7763 (define_insn "reg_stack_protect_address_<mode>"
7764  [(set (match_operand:PTR 0 "register_operand" "=r")
7765        (unspec:PTR [(match_operand 1 "const_int_operand")]
7766                    UNSPEC_SSP_SYSREG))]
7767  "aarch64_stack_protector_guard != SSP_GLOBAL"
7769    char buf[150];
7770    snprintf (buf, 150, "mrs\\t%%<w>0, %s",
7771             aarch64_stack_protector_guard_reg_str);
7772    output_asm_insn (buf, operands);
7773    return "";
7775  [(set_attr "type" "mrs")])
7777 ;; DO NOT SPLIT THIS PATTERN.  It is important for security reasons that the
7778 ;; canary value does not live beyond the life of this sequence.
7779 (define_insn "stack_protect_set_<mode>"
7780   [(set (match_operand:PTR 0 "memory_operand" "=m")
7781         (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
7782          UNSPEC_SP_SET))
7783    (set (match_scratch:PTR 2 "=&r") (const_int 0))]
7784   ""
7785   "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2, 0"
7786   [(set_attr "length" "12")
7787    (set_attr "type" "multiple")])
7789 ;; Defined for -mstack-protector-guard=sysreg, which goes through this
7790 ;; pattern rather than stack_protect_combined_test.  Our implementation
7791 ;; of the latter can handle both.
7792 (define_expand "stack_protect_test"
7793   [(match_operand 0 "memory_operand")
7794    (match_operand 1 "")
7795    (match_operand 2)]
7796   ""
7798   emit_insn (gen_stack_protect_combined_test (operands[0], operands[1],
7799                                               operands[2]));
7800   DONE;
7803 (define_expand "stack_protect_combined_test"
7804   [(match_operand 0 "memory_operand")
7805    (match_operand 1 "")
7806    (match_operand 2)]
7807   ""
7809   machine_mode mode = GET_MODE (operands[0]);
7810   operands[1] = aarch64_stack_protect_canary_mem (mode, operands[1],
7811                                                   AARCH64_SALT_SSP_TEST);
7812   emit_insn ((mode == DImode
7813              ? gen_stack_protect_test_di
7814              : gen_stack_protect_test_si) (operands[0], operands[1]));
7816   rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
7817   emit_jump_insn (gen_condjump (gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx),
7818                                 cc_reg, operands[2]));
7819   DONE;
7822 ;; DO NOT SPLIT THIS PATTERN.  It is important for security reasons that the
7823 ;; canary value does not live beyond the end of this sequence.
7824 (define_insn "stack_protect_test_<mode>"
7825   [(set (reg:CC CC_REGNUM)
7826         (unspec:CC [(match_operand:PTR 0 "memory_operand" "m")
7827                     (match_operand:PTR 1 "memory_operand" "m")]
7828                    UNSPEC_SP_TEST))
7829    (clobber (match_scratch:PTR 2 "=&r"))
7830    (clobber (match_scratch:PTR 3 "=&r"))]
7831   ""
7832   "ldr\t%<w>2, %0\;ldr\t%<w>3, %1\;subs\t%<w>2, %<w>2, %<w>3\;mov\t%3, 0"
7833   [(set_attr "length" "16")
7834    (set_attr "type" "multiple")])
7836 ;; Write into the Floating-point Status or Control Register.
7837 (define_insn "@aarch64_set_<fpscr_name><GPI:mode>"
7838   [(unspec_volatile [(match_operand:GPI 0 "register_operand" "r")] SET_FPSCR)]
7839   ""
7840   "msr\\t<fpscr_name>, %0"
7841   [(set_attr "type" "mrs")])
7843 ;; Read into the Floating-point Status or Control Register.
7844 (define_insn "@aarch64_get_<fpscr_name><GPI:mode>"
7845   [(set (match_operand:GPI 0 "register_operand" "=r")
7846         (unspec_volatile:GPI [(const_int 0)] GET_FPSCR))]
7847   ""
7848   "mrs\\t%0, <fpscr_name>"
7849   [(set_attr "type" "mrs")])
7851 ;; Define the subtract-one-and-jump insns so loop.c
7852 ;; knows what to generate.
7853 (define_expand "doloop_end"
7854   [(use (match_operand 0 "" ""))      ; loop pseudo
7855    (use (match_operand 1 "" ""))]     ; label
7856   "optimize > 0 && flag_modulo_sched"
7858   rtx s0;
7859   rtx bcomp;
7860   rtx loc_ref;
7861   rtx cc_reg;
7862   rtx insn;
7863   rtx cmp;
7865   /* Currently SMS relies on the do-loop pattern to recognize loops
7866      where (1) the control part consists of all insns defining and/or
7867      using a certain 'count' register and (2) the loop count can be
7868      adjusted by modifying this register prior to the loop.
7869      ??? The possible introduction of a new block to initialize the
7870      new IV can potentially affect branch optimizations.  */
7872   if (GET_MODE (operands[0]) != DImode)
7873     FAIL;
7875   s0 = operands [0];
7876   insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
7878   cmp = XVECEXP (PATTERN (insn), 0, 0);
7879   cc_reg = SET_DEST (cmp);
7880   bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
7881   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
7882   emit_jump_insn (gen_rtx_SET (pc_rtx,
7883                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
7884                                                      loc_ref, pc_rtx)));
7885   DONE;
7888 ;; Track speculation through conditional branches.  We assume that
7889 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
7890 (define_insn "speculation_tracker"
7891   [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7892         (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
7893          UNSPEC_SPECULATION_TRACKER))]
7894   ""
7895   {
7896     operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7897     output_asm_insn ("csel\\t%1, %1, xzr, %m0", operands);
7898     return "";
7899   }
7900   [(set_attr "type" "csel")]
7903 ;; Like speculation_tracker, but track the inverse condition.
7904 (define_insn "speculation_tracker_rev"
7905   [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7906         (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
7907          UNSPEC_SPECULATION_TRACKER_REV))]
7908   ""
7909   {
7910     operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7911     output_asm_insn ("csel\\t%1, %1, xzr, %M0", operands);
7912     return "";
7913   }
7914   [(set_attr "type" "csel")]
7917 ;; BTI <target> instructions
7918 (define_insn "bti_noarg"
7919   [(unspec_volatile [(const_int 0)] UNSPECV_BTI_NOARG)]
7920   ""
7921   "hint\t32 // bti"
7922   [(set_attr "type" "no_insn")]
7925 (define_insn "bti_c"
7926   [(unspec_volatile [(const_int 0)] UNSPECV_BTI_C)]
7927   ""
7928   "hint\t34 // bti c"
7929   [(set_attr "type" "no_insn")]
7932 (define_insn "bti_j"
7933   [(unspec_volatile [(const_int 0)] UNSPECV_BTI_J)]
7934   ""
7935   "hint\t36 // bti j"
7936   [(set_attr "type" "no_insn")]
7939 (define_insn "bti_jc"
7940   [(unspec_volatile [(const_int 0)] UNSPECV_BTI_JC)]
7941   ""
7942   "hint\t38 // bti jc"
7943   [(set_attr "type" "no_insn")]
7946 ;; Hard speculation barrier.
7947 (define_insn "speculation_barrier"
7948   [(unspec_volatile [(const_int 0)] UNSPECV_SPECULATION_BARRIER)]
7949   ""
7950   "isb\;dsb\\tsy"
7951   [(set_attr "length" "8")
7952    (set_attr "type" "block")
7953    (set_attr "speculation_barrier" "true")]
7956 ;; Support for __builtin_speculation_safe_value when we have speculation
7957 ;; tracking enabled.  Use the speculation tracker to decide whether to
7958 ;; copy operand 1 to the target, or to copy the fail value (operand 2).
7959 (define_expand "@despeculate_copy<ALLI_TI:mode>"
7960   [(set (match_operand:ALLI_TI 0 "register_operand")
7961         (unspec_volatile:ALLI_TI
7962          [(match_operand:ALLI_TI 1 "register_operand")
7963           (match_operand:ALLI_TI 2 "aarch64_reg_or_zero")
7964           (use (reg:DI SPECULATION_TRACKER_REGNUM))
7965           (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7966   ""
7967   "
7968   {
7969     if (operands[2] == const0_rtx)
7970       {
7971         rtx tracker;
7972         if (<MODE>mode == TImode)
7973           tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7974         else
7975           tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
7977         emit_insn (gen_despeculate_simple<mode> (operands[0], operands[1],
7978                                                  tracker));
7979         DONE;
7980       }
7981   }
7982   "
7985 ;; Patterns to match despeculate_copy<mode>.  Note that "hint 0x14" is the
7986 ;; encoding for CSDB, but will work in older versions of the assembler.
7987 (define_insn "*despeculate_copy<ALLI:mode>_insn"
7988   [(set (match_operand:ALLI 0 "register_operand" "=r")
7989         (unspec_volatile:ALLI
7990          [(match_operand:ALLI 1 "register_operand" "r")
7991           (match_operand:ALLI 2 "aarch64_reg_or_zero" "rZ")
7992           (use (reg:DI SPECULATION_TRACKER_REGNUM))
7993           (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7994   ""
7995   {
7996     operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7997     output_asm_insn ("cmp\\t%3, #0\;csel\\t%<w>0, %<w>1, %<w>2, ne\;hint\t0x14 // csdb",
7998                      operands);
7999     return "";
8000   }
8001   [(set_attr "length" "12")
8002    (set_attr "type" "block")
8003    (set_attr "speculation_barrier" "true")]
8006 ;; Pattern to match despeculate_copyti
8007 (define_insn "*despeculate_copyti_insn"
8008   [(set (match_operand:TI 0 "register_operand" "=r")
8009         (unspec_volatile:TI
8010          [(match_operand:TI 1 "register_operand" "r")
8011           (match_operand:TI 2 "aarch64_reg_or_zero" "rZ")
8012           (use (reg:DI SPECULATION_TRACKER_REGNUM))
8013           (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
8014   ""
8015   {
8016     operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
8017     output_asm_insn
8018       ("cmp\\t%3, #0\;csel\\t%0, %1, %2, ne\;csel\\t%H0, %H1, %H2, ne\;hint\t0x14 // csdb",
8019        operands);
8020     return "";
8021   }
8022   [(set_attr "length" "16")
8023    (set_attr "type" "block")
8024    (set_attr "speculation_barrier" "true")]
8027 (define_insn "despeculate_simple<ALLI:mode>"
8028   [(set (match_operand:ALLI 0 "register_operand" "=r")
8029         (unspec_volatile:ALLI
8030          [(match_operand:ALLI 1 "register_operand" "r")
8031           (use (match_operand:ALLI 2 "register_operand" ""))]
8032          UNSPECV_SPECULATION_BARRIER))]
8033   ""
8034   "and\\t%<w>0, %<w>1, %<w>2\;hint\t0x14 // csdb"
8035   [(set_attr "type" "block")
8036    (set_attr "length" "8")
8037    (set_attr "speculation_barrier" "true")]
8040 (define_insn "despeculate_simpleti"
8041   [(set (match_operand:TI 0 "register_operand" "=r")
8042         (unspec_volatile:TI
8043          [(match_operand:TI 1 "register_operand" "r")
8044           (use (match_operand:DI 2 "register_operand" ""))]
8045          UNSPECV_SPECULATION_BARRIER))]
8046   ""
8047   "and\\t%0, %1, %2\;and\\t%H0, %H1, %2\;hint\t0x14 // csdb"
8048   [(set_attr "type" "block")
8049    (set_attr "length" "12")
8050    (set_attr "speculation_barrier" "true")]
8053 (define_insn "aarch64_<frintnzs_op><mode>"
8054   [(set (match_operand:VSFDF 0 "register_operand" "=w")
8055         (unspec:VSFDF [(match_operand:VSFDF 1 "register_operand" "w")]
8056                       FRINTNZX))]
8057   "TARGET_FRINT && TARGET_FLOAT
8058    && !(VECTOR_MODE_P (<MODE>mode) && !TARGET_SIMD)"
8059   "<frintnzs_op>\\t%<v>0<Vmtype>, %<v>1<Vmtype>"
8060   [(set_attr "type" "f_rint<stype>")]
8063 ;; Transactional Memory Extension (TME) instructions.
8065 (define_insn "tstart"
8066   [(set (match_operand:DI 0 "register_operand" "=r")
8067         (unspec_volatile:DI [(const_int 0)] UNSPECV_TSTART))
8068    (clobber (mem:BLK (scratch)))]
8069   "TARGET_TME"
8070   "tstart\\t%0"
8071   [(set_attr "type" "tme")]
8074 (define_insn "ttest"
8075   [(set (match_operand:DI 0 "register_operand" "=r")
8076         (unspec_volatile:DI [(const_int 0)] UNSPEC_TTEST))
8077    (clobber (mem:BLK (scratch)))]
8078   "TARGET_TME"
8079   "ttest\\t%0"
8080   [(set_attr "type" "tme")]
8083 (define_insn "tcommit"
8084   [(unspec_volatile:BLK [(const_int 0)] UNSPECV_TCOMMIT)
8085    (clobber (mem:BLK (scratch)))]
8086   "TARGET_TME"
8087   "tcommit"
8088   [(set_attr "type" "tme")]
8091 (define_insn "tcancel"
8092   [(unspec_volatile:BLK
8093      [(match_operand 0 "const_int_operand" "n")] UNSPECV_TCANCEL)
8094    (clobber (mem:BLK (scratch)))]
8095   "TARGET_TME && (UINTVAL (operands[0]) <= 65535)"
8096   "tcancel\\t#%0"
8097   [(set_attr "type" "tme")]
8100 (define_insn "aarch64_rndr"
8101   [(set (match_operand:DI 0 "register_operand" "=r")
8102         (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDR))
8103    (set (reg:CC_Z CC_REGNUM)
8104         (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDR))]
8105   "TARGET_RNG"
8106   "mrs\t%0, RNDR"
8107   [(set_attr "type" "mrs")]
8110 (define_insn "aarch64_rndrrs"
8111   [(set (match_operand:DI 0 "register_operand" "=r")
8112         (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDRRS))
8113    (set (reg:CC_Z CC_REGNUM)
8114         (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDRRS))]
8115   "TARGET_RNG"
8116   "mrs\t%0, RNDRRS"
8117   [(set_attr "type" "mrs")]
8120 ;; Memory Tagging Extension (MTE) instructions.
8122 (define_insn "irg"
8123   [(set (match_operand:DI 0 "register_operand" "=rk")
8124         (ior:DI
8125          (and:DI (match_operand:DI 1 "register_operand" "rk")
8126                  (const_int -1080863910568919041)) ;; 0xf0ff...
8127          (ashift:DI (unspec:QI [(match_operand:DI 2 "register_operand" "r")]
8128                      UNSPEC_GEN_TAG_RND)
8129                     (const_int 56))))]
8130   "TARGET_MEMTAG"
8131   "irg\\t%0, %1, %2"
8132   [(set_attr "type" "memtag")]
8135 (define_insn "gmi"
8136   [(set (match_operand:DI 0 "register_operand" "=r")
8137         (ior:DI (ashift:DI
8138                  (const_int 1)
8139                  (and:QI (lshiftrt:DI
8140                           (match_operand:DI 1 "register_operand" "rk")
8141                           (const_int 56)) (const_int 15)))
8142                 (match_operand:DI 2 "register_operand" "r")))]
8143   "TARGET_MEMTAG"
8144   "gmi\\t%0, %1, %2"
8145   [(set_attr "type" "memtag")]
8148 (define_insn "addg"
8149   [(set (match_operand:DI 0 "register_operand" "=rk")
8150         (ior:DI
8151          (and:DI (plus:DI (match_operand:DI 1 "register_operand" "rk")
8152                           (match_operand:DI 2 "aarch64_granule16_uimm6" "i"))
8153                  (const_int -1080863910568919041)) ;; 0xf0ff...
8154          (ashift:DI
8155           (unspec:QI
8156            [(and:QI (lshiftrt:DI (match_dup 1) (const_int 56)) (const_int 15))
8157             (match_operand:QI 3 "aarch64_memtag_tag_offset" "i")]
8158            UNSPEC_GEN_TAG)
8159           (const_int 56))))]
8160   "TARGET_MEMTAG"
8161   "addg\\t%0, %1, #%2, #%3"
8162   [(set_attr "type" "memtag")]
8165 (define_insn "subp"
8166   [(set (match_operand:DI 0 "register_operand" "=r")
8167         (minus:DI
8168           (and:DI (match_operand:DI 1 "register_operand" "rk")
8169                   (const_int 72057594037927935)) ;; 0x00ff...
8170           (and:DI (match_operand:DI 2 "register_operand" "rk")
8171                   (const_int 72057594037927935))))] ;; 0x00ff...
8172   "TARGET_MEMTAG"
8173   "subp\\t%0, %1, %2"
8174   [(set_attr "type" "memtag")]
8177 ;; LDG will use the 16-byte aligned value of the address.
8178 (define_insn "ldg"
8179   [(set (match_operand:DI 0 "register_operand" "+r")
8180         (ior:DI
8181          (and:DI (match_dup 0) (const_int -1080863910568919041)) ;; 0xf0ff...
8182          (ashift:DI
8183           (mem:QI (unspec:DI
8184            [(and:DI (plus:DI (match_operand:DI 1 "register_operand" "rk")
8185                              (match_operand:DI 2 "aarch64_granule16_simm9" "i"))
8186                     (const_int -16))] UNSPEC_TAG_SPACE))
8187           (const_int 56))))]
8188   "TARGET_MEMTAG"
8189   "ldg\\t%0, [%1, #%2]"
8190   [(set_attr "type" "memtag")]
8193 ;; STG doesn't align the address but aborts with alignment fault
8194 ;; when the address is not 16-byte aligned.
8195 (define_insn "stg"
8196   [(set (mem:QI (unspec:DI
8197          [(plus:DI (match_operand:DI 1 "register_operand" "rk")
8198                    (match_operand:DI 2 "aarch64_granule16_simm9" "i"))]
8199          UNSPEC_TAG_SPACE))
8200         (and:QI (lshiftrt:DI (match_operand:DI 0 "register_operand" "rk")
8201                              (const_int 56)) (const_int 15)))]
8202   "TARGET_MEMTAG"
8203   "stg\\t%0, [%1, #%2]"
8204   [(set_attr "type" "memtag")]
8207 ;; Load/Store 64-bit (LS64) instructions.
8208 (define_insn "ld64b"
8209   [(set (match_operand:V8DI 0 "register_operand" "=r")
8210         (unspec_volatile:V8DI
8211           [(mem:V8DI (match_operand:DI 1 "register_operand" "r"))]
8212             UNSPEC_LD64B)
8213   )]
8214   "TARGET_LS64"
8215   "ld64b\\t%0, [%1]"
8216   [(set_attr "type" "ls64")]
8219 (define_insn "st64b"
8220   [(set (mem:V8DI (match_operand:DI 0 "register_operand" "r"))
8221         (unspec_volatile:V8DI [(match_operand:V8DI 1 "register_operand" "r")]
8222             UNSPEC_ST64B)
8223   )]
8224   "TARGET_LS64"
8225   "st64b\\t%1, [%0]"
8226   [(set_attr "type" "ls64")]
8229 (define_insn "st64bv"
8230   [(set (match_operand:DI 0 "register_operand" "=r")
8231         (unspec_volatile:DI [(const_int 0)] UNSPEC_ST64BV_RET))
8232    (set (mem:V8DI (match_operand:DI 1 "register_operand" "r"))
8233         (unspec_volatile:V8DI [(match_operand:V8DI 2 "register_operand" "r")]
8234             UNSPEC_ST64BV)
8235   )]
8236   "TARGET_LS64"
8237   "st64bv\\t%0, %2, [%1]"
8238   [(set_attr "type" "ls64")]
8241 (define_insn "st64bv0"
8242   [(set (match_operand:DI 0 "register_operand" "=r")
8243         (unspec_volatile:DI [(const_int 0)] UNSPEC_ST64BV0_RET))
8244    (set (mem:V8DI (match_operand:DI 1 "register_operand" "r"))
8245         (unspec_volatile:V8DI [(match_operand:V8DI 2 "register_operand" "r")]
8246             UNSPEC_ST64BV0)
8247   )]
8248   "TARGET_LS64"
8249   "st64bv0\\t%0, %2, [%1]"
8250   [(set_attr "type" "ls64")]
8253 (define_insn "patchable_area"
8254   [(unspec_volatile [(match_operand 0 "const_int_operand")
8255                      (match_operand 1 "const_int_operand")]
8256                     UNSPECV_PATCHABLE_AREA)]
8257   ""
8259   aarch64_output_patchable_area (INTVAL (operands[0]),
8260                                  INTVAL (operands[1]) != 0);
8261   return "";
8263   [(set (attr "length") (symbol_ref "INTVAL (operands[0])"))]
8266 (define_insn "aarch64_save_nzcv"
8267   [(set (match_operand:DI 0 "register_operand" "=r")
8268         (unspec:DI [(reg:CC CC_REGNUM)] UNSPEC_SAVE_NZCV))]
8269   ""
8270   "mrs\t%0, nzcv"
8273 (define_insn "aarch64_restore_nzcv"
8274   [(set (reg:CC CC_REGNUM)
8275         (unspec:CC [(match_operand:DI 0 "register_operand" "r")]
8276                    UNSPEC_RESTORE_NZCV))]
8277   ""
8278   "msr\tnzcv, %0"
8281 ;; AdvSIMD Stuff
8282 (include "aarch64-simd.md")
8284 ;; Atomic Operations
8285 (include "atomics.md")
8287 ;; ldp/stp peephole patterns
8288 (include "aarch64-ldpstp.md")
8290 ;; SVE.
8291 (include "aarch64-sve.md")
8293 ;; SVE2.
8294 (include "aarch64-sve2.md")
8296 ;; SME and extensions
8297 (include "aarch64-sme.md")