1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
3 ;; Contributed by ARM Ltd.
5 ;; This file is part of GCC.
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)
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/>.
91 ;; Defined only to make the DWARF description simpler.
109 (LAST_SAVED_REGNUM 83)
111 ;; "FFR token": a fake register used for representing the scheduling
112 ;; restrictions on FFR-related operations.
115 ;; ----------------------------------------------------------------
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.
127 ;; Represents the contents of the current function's TPIDR2 block,
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.
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?".
148 ;; Represents the property "are the current function's ZA contents
149 ;; stored in the lazy save buffer, rather than in ZA itself?".
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.
156 ;; The contents persist even when the architected ZA is off. Private-ZA
157 ;; functions have no effect on its contents.
160 ;; Similarly represents the contents of the current function's ZT0 state.
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.
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.
192 (define_c_enum "unspec" [
227 UNSPEC_GOTSMALLPIC28K
331 UNSPEC_SPECULATION_TRACKER
332 UNSPEC_SPECULATION_TRACKER_REV
334 UNSPEC_TTEST ; Represent transaction test.
344 ;; Represents an SVE-style lane index, in which the indexing applies
345 ;; within the containing 128-bit block.
346 UNSPEC_SVE_LANE_SELECT
349 UNSPEC_SVE_PREFETCH_GATHER
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.
359 UNSPECV_PATCHABLE_AREA
362 ;; Wraps a constant integer that should be multiplied by the number
363 ;; of quadwords in an SME vector.
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
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.
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.
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.
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.
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
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
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
458 (define_attr "fp" "no,yes"
460 (eq_attr "arch" "fp")
462 (const_string "no")))
464 (define_attr "arch_enabled" "no,yes"
469 (eq_attr "pred_clobber" "no")
470 (match_test "!TARGET_SVE_PRED_CLOBBER"))
472 (eq_attr "pred_clobber" "yes")
473 (match_test "TARGET_SVE_PRED_CLOBBER"))
474 (eq_attr "pred_clobber" "any"))
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"))))
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.
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")
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)]
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)]
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
575 (define_attr "ldpstp" "ldp,stp,none" (const_string "none"))
577 ;; -------------------------------------------------------------------
578 ;; Pipeline descriptions and scheduling
579 ;; -------------------------------------------------------------------
582 (include "aarch64-tune.md")
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" "")]
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" "")]
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")]
624 (define_insn "aarch64_write_sysregti"
625 [(unspec_volatile:TI [(match_operand 0 "aarch64_sysreg_string" "")
626 (match_operand:TI 1 "register_operand" "r")]
629 "msrr\t%x0, %x1, %H1"
632 (define_insn "indirect_jump"
633 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
636 output_asm_insn ("br\\t%0", operands);
637 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
639 [(set_attr "type" "branch")
640 (set_attr "sls_length" "retbr")]
644 [(set (pc) (label_ref (match_operand 0 "" "")))]
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 "" ""))
658 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
660 operands[2] = const0_rtx;
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 "" ""))
672 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
674 operands[2] = const0_rtx;
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 "" ""))
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")
695 (match_operand:GPI 2 "register_operand")
696 (match_operand:GPI 3 "aarch64_ccmp_operand"))
698 [(match_operand 5 "immediate_operand")]
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
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" "")
715 (match_operand:GPF 2 "register_operand" "w")
716 (match_operand:GPF 3 "register_operand" "w"))
718 [(match_operand 5 "immediate_operand")]
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")
732 [(match_operand 5 "immediate_operand")]
735 (match_operand:GPI 2 "register_operand")
736 (match_operand:GPI 3 "aarch64_ccmp_operand"))))]
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
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" "")
752 [(match_operand 5 "immediate_operand")]
755 (match_operand:GPF 2 "register_operand" "w")
756 (match_operand:GPF 3 "register_operand" "w"))))]
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:
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")]
775 HOST_WIDE_INT val = INTVAL (operands[2]);
778 || exact_log2 (val) <= 0
779 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
782 rtx mask = GEN_INT (val - 1);
784 /* In the special case of x0 % 2 we can do the even shorter:
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));
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));
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 "" ""))
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");
832 return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
834 [(set_attr "type" "branch")
836 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
837 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
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)))
847 ;; For a 24-bit immediate CST we can optimize the compare for equality
848 ;; and branch sequence from:
850 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
854 ;; sub x0, x1, #(CST & 0xfff000)
855 ;; subs x0, x0, #(CST & 0x000fff)
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 "" ""))
863 "!aarch64_move_imm (INTVAL (operands[1]), <GPI:MODE>mode)
864 && !aarch64_plus_operand (operands[1], <GPI:MODE>mode)
865 && !reload_completed"
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,
878 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
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
891 if (operands[1] != const0_rtx)
893 rtx reg = gen_reg_rtx (SImode);
895 /* Canonical RTL says that if you have:
899 then this should be emitted as:
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. */
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]));
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,
921 operands[0], operands[2], operands[4]));
923 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3]));
925 = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], operands[0]),
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]));
935 (define_expand "casesi_dispatch"
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 "")))])]
944 (define_insn "*casesi_dispatch"
947 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
948 (match_operand:SI 1 "register_operand" "r")]
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 "" "")))])]
956 return aarch64_output_casesi (operands);
958 [(set_attr "sls_length" "casesi")
959 (set_attr "type" "branch")]
963 [(unspec[(const_int 0)] UNSPEC_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" ""))]
975 const char * pftype[2][4] =
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"},
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
994 operands[0] = gen_rtx_MEM (DImode, operands[0]);
995 return pftype[INTVAL(operands[1])][locality];
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)]
1005 operands[1] = gen_rtx_MEM (DImode, operands[1]);
1006 return "prfm\\t%0, %1";
1008 [(set_attr "type" "load_4")]
1012 [(trap_if (const_int 1) (const_int 8))]
1015 [(set_attr "type" "trap")])
1017 (define_expand "prologue"
1018 [(clobber (const_int 0))]
1021 aarch64_expand_prologue ();
1026 (define_expand "epilogue"
1027 [(clobber (const_int 0))]
1030 aarch64_expand_epilogue (nullptr);
1035 (define_insn "*do_return"
1039 const char *ret = NULL;
1040 if (aarch64_return_address_signing_enabled ()
1043 if (aarch64_ra_sign_key == AARCH64_KEY_B)
1050 output_asm_insn (ret, operands);
1051 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1053 [(set_attr "type" "branch")
1054 (set_attr "sls_length" "retbr")]
1057 (define_expand "return"
1059 "aarch64_use_return_insn_p ()"
1063 (define_insn "simple_return"
1067 output_asm_insn ("ret", operands);
1068 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
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")
1077 (label_ref (match_operand 1 "" ""))
1079 "!aarch64_track_speculation"
1081 if (get_attr_length (insn) == 8)
1082 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
1084 return "<cbz>\\t%<w>0, %l1";
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)))
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)))
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 ""))
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,
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")
1121 "aarch64_simd_shift_imm_<ALLI:mode>" "n"))
1123 (label_ref (match_operand 2 "" ""))
1125 (clobber (reg:CC CC_REGNUM))]
1126 "!aarch64_track_speculation"
1128 if (get_attr_length (insn) == 8)
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, ");
1135 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
1136 return "tst\t%<ALLI:w>0, %1\;<bcond>\t%l2";
1140 return "<tbz>\t%<ALLI:w>0, %1, %l2";
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)))
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)))
1156 (define_insn "*cb<optab><mode>1"
1157 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
1159 (label_ref (match_operand 1 "" ""))
1161 (clobber (reg:CC CC_REGNUM))]
1162 "!aarch64_track_speculation"
1164 if (get_attr_length (insn) == 8)
1166 if (get_attr_far_branch (insn) == 1)
1167 return aarch64_gen_far_branch (operands, 1, "Ltb",
1168 "<inv_tb>\\t%<w>0, <sizem1>, ");
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";
1180 return "<tbz>\t%<w>0, <sizem1>, %l1";
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)))
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)))
1195 ;; -------------------------------------------------------------------
1196 ;; Subroutine calls and sibcalls
1197 ;; -------------------------------------------------------------------
1199 (define_expand "call"
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))])]
1208 aarch64_expand_call (NULL_RTX, operands[0], operands[2], false);
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))]
1219 {@ [ cons: 0 ; attrs: type ]
1220 [ Ucr ; call ] << aarch64_indirect_call_asm (operands[0]);
1221 [ Usf ; call ] bl\t%c0
1225 (define_expand "call_value"
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))])]
1235 aarch64_expand_call (operands[0], operands[1], operands[3], false);
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))]
1247 {@ [ cons: 1 ; attrs: type ]
1248 [ Ucr ; call ] << aarch64_indirect_call_asm (operands[1]);
1249 [ Usf ; call ] bl\t%c1
1253 (define_expand "sibcall"
1255 [(call (match_operand 0 "memory_operand")
1256 (match_operand 1 "general_operand"))
1257 (unspec:DI [(match_operand 2)] UNSPEC_CALLEE_ABI)
1261 aarch64_expand_call (NULL_RTX, operands[0], operands[2], true);
1266 (define_expand "sibcall_value"
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)
1275 aarch64_expand_call (operands[0], operands[1], operands[3], true);
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)
1285 "SIBLING_CALL_P (insn)"
1287 if (which_alternative == 0)
1289 output_asm_insn ("br\\t%0", operands);
1290 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1294 [(set_attr "type" "branch, branch")
1295 (set_attr "sls_length" "retbr,none")]
1298 (define_insn "*sibcall_value_insn"
1299 [(set (match_operand 0 "")
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)
1305 "SIBLING_CALL_P (insn)"
1307 if (which_alternative == 0)
1309 output_asm_insn ("br\\t%1", operands);
1310 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
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 "")
1323 (match_operand 1 "")
1324 (match_operand 2 "")])]
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++)
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));
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++)
1353 rtx set = XVECEXP (operands[2], 0, i);
1354 emit_move_insn (SET_DEST (set), SET_SRC (set));
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
1361 emit_insn (gen_blockage ());
1365 ;; -------------------------------------------------------------------
1367 ;; -------------------------------------------------------------------
1369 (define_expand "mov<mode>"
1370 [(set (match_operand:SHORT 0 "nonimmediate_operand")
1371 (match_operand:SHORT 1 "general_operand"))]
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)
1379 aarch64_expand_mov_immediate (operands[0], operands[1]);
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
1411 (define_expand "mov<mode>"
1412 [(set (match_operand:GPI 0 "nonimmediate_operand")
1413 (match_operand:GPI 1 "general_operand"))]
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]))
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])
1435 && !aarch64_mov_imm_operand (operands[1], <MODE>mode))
1436 : CONSTANT_P (operands[1]))
1438 aarch64_expand_mov_immediate (operands[0], operands[1]);
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);
1471 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1472 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1475 aarch64_expand_mov_immediate (operands[0], operands[1]);
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] #
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]))))"
1517 if (GP_REGNUM_P (REGNO (operands[0])))
1518 aarch64_expand_mov_immediate (operands[0], operands[1]);
1520 aarch64_maybe_generate_simd_constant (operands[0], operands[1], DImode);
1525 (define_insn "insv_imm<mode>"
1526 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
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"
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";
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"))]
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)
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);
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")
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))"
1585 mov\\t%0.16b, %1.16b
1592 [(set_attr "type" "multiple,neon_move,f_mcr,f_mcr,f_mrc,neon_logic_q,*,\
1593 load_16,store_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.
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])"
1608 aarch64_split_128bit_move (operands[0], operands[1]);
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"))]
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]));
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]);
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
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
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";
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])"
1710 unsigned HOST_WIDE_INT ival;
1711 if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
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));
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))"
1729 mov\\t%0.16b, %1.16b
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,*,*,*,*,*,*")]
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])"
1753 aarch64_split_128bit_move (operands[0], operands[1]);
1758 (define_expand "aarch64_cpymemdi"
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))])]
1768 operands[3] = XEXP (operands[0], 0);
1769 operands[4] = XEXP (operands[1], 0);
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))]
1781 "cpyfp\t[%x0]!, [%x1]!, %x2!\;cpyfm\t[%x0]!, [%x1]!, %x2!\;cpyfe\t[%x0]!, [%x1]!, %x2!"
1782 [(set_attr "length" "12")]
1787 ;; 2 is size of copy in bytes
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")]
1797 if (aarch64_expand_cpymem (operands, false))
1803 (define_expand "aarch64_movmemdi"
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))])]
1813 operands[3] = XEXP (operands[0], 0);
1814 operands[4] = XEXP (operands[1], 0);
1818 (define_insn "*aarch64_movmemdi"
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))])]
1827 "cpyp\t[%x0]!, [%x1]!, %x2!\;cpym\t[%x0]!, [%x1]!, %x2!\;cpye\t[%x0]!, [%x1]!, %x2!"
1828 [(set_attr "length" "12")]
1833 ;; 2 is size of copy in bytes
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")]
1843 if (aarch64_expand_cpymem (operands, true))
1849 (define_expand "aarch64_setmemdi"
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))])]
1859 operands[3] = XEXP (operands[0], 0);
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))]
1871 "setp\t[%x0]!, %x2!, %x1\;setm\t[%x0]!, %x2!, %x1\;sete\t[%x0]!, %x2!, %x1"
1872 [(set_attr "length" "12")]
1877 ;; 2 is size of copy in bytes
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
1886 if (aarch64_expand_setmem (operands))
1892 (define_insn "*load_pair_<ldst_sz>"
1893 [(set (match_operand:GPI 0 "aarch64_ldp_reg_operand")
1895 (match_operand:<VPAIR> 1 "aarch64_mem_pair_lanes_operand")
1897 (set (match_operand:GPI 2 "aarch64_ldp_reg_operand")
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
1906 [(set_attr "ldpstp" "ldp")]
1909 (define_insn "*load_pair_16"
1910 [(set (match_operand:TI 0 "aarch64_ldp_reg_operand" "=w")
1912 (match_operand:V2x16QI 1 "aarch64_mem_pair_lanes_operand" "Umn")
1914 (set (match_operand:TI 2 "aarch64_ldp_reg_operand" "=w")
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")
1928 [(match_operand:GPI 1 "aarch64_stp_reg_operand")
1929 (match_operand:GPI 2 "aarch64_stp_reg_operand")] UNSPEC_STP))]
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
1935 [(set_attr "ldpstp" "stp")]
1938 (define_insn "*store_pair_16"
1939 [(set (match_operand:V2x16QI 0 "aarch64_mem_pair_lanes_operand" "=Umn")
1941 [(match_operand:TI 1 "aarch64_ldp_reg_operand" "w")
1942 (match_operand:TI 2 "aarch64_ldp_reg_operand" "w")] UNSPEC_STP))]
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
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" [
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
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" [
1990 (const_int 16)])]))]
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" [
2009 (set (match_operand:GPI 3 "aarch64_ldp_reg_operand")
2010 (match_operator 7 "memory_operand" [
2011 (match_operator 10 "pmode_plus_operator" [
2013 (match_operand 5 "const_int_operand")
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]!
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" [
2036 (set (match_operand:TI 3 "aarch64_ldp_reg_operand" "=w")
2037 (match_operator 7 "memory_operand" [
2038 (match_operator 10 "pmode_plus_operator" [
2040 (match_operand 5 "const_int_operand")
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
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")
2057 (set (match_operator:GPI 7 "aarch64_mem_pair_operator" [
2058 (match_operator 8 "pmode_plus_operator" [
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" [
2066 (match_operand 5 "const_int_operand")
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]!
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")
2087 (set (match_operator:TI 7 "aarch64_mem_pair_operator" [
2088 (match_operator 8 "pmode_plus_operator" [
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" [
2096 (match_operand 5 "const_int_operand")
2098 (match_operand:TI 3 "aarch64_ldp_reg_operand" "w"))]
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")
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" [
2120 (const_int <ldst_sz>)
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
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")
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" [
2146 (match_operand:TI 3 "aarch64_ldp_reg_operand" "w"))]
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")))]
2165 (define_insn "*extendsidi2_aarch64"
2166 [(set (match_operand:DI 0 "register_operand")
2167 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
2169 {@ [ cons: =0 , 1 ; attrs: type ]
2170 [ r , r ; extend ] sxtw\t%0, %w1
2171 [ r , m ; load_4 ] ldrsw\t%0, %1
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")
2180 (set (match_operand:DI 2 "register_operand" "=r")
2181 (sign_extend:DI (unspec:SI [
2183 ] UNSPEC_LDP_SND)))]
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")))]
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
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")
2208 (set (match_operand:DI 2 "register_operand")
2209 (zero_extend:DI (unspec:SI [
2211 ] UNSPEC_LDP_SND)))]
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
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")))]
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")))]
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]
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")))]
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]
2248 (define_expand "<optab>qihi2"
2249 [(set (match_operand:HI 0 "register_operand")
2250 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
2254 (define_insn "*extendqihi2_aarch64"
2255 [(set (match_operand:HI 0 "register_operand")
2256 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand")))]
2258 {@ [ cons: =0 , 1 ; attrs: type ]
2259 [ r , r ; extend ] sxtb\t%w0, %w1
2260 [ r , m ; load_4 ] ldrsb\t%w0, %1
2264 (define_insn "*zero_extendqihi2_aarch64"
2265 [(set (match_operand:HI 0 "register_operand")
2266 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand")))]
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
2274 ;; -------------------------------------------------------------------
2275 ;; Simple arithmetic
2276 ;; -------------------------------------------------------------------
2278 (define_expand "add<mode>3"
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")))]
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 ()
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))
2309 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
2310 operands[2], NULL_RTX, NULL_RTX);
2315 (define_insn "*add<mode>3_aarch64"
2317 (match_operand:GPI 0 "register_operand")
2319 (match_operand:GPI 1 "register_operand")
2320 (match_operand:GPI 2 "aarch64_pluslong_operand")))]
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]);
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"
2338 (match_operand:DI 0 "register_operand")
2340 (plus:SI (match_operand:SI 1 "register_operand")
2341 (match_operand:SI 2 "aarch64_pluslong_operand"))))]
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 ] #
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.
2354 [(match_scratch:GPI 3 "r")
2355 (set (match_operand:GPI 0 "register_operand")
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)))]
2365 [(match_scratch:SI 3 "r")
2366 (set (match_operand:DI 0 "register_operand")
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.
2379 [(set (match_operand:GPI 0 "register_operand")
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)))]
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);
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
2409 (define_insn_and_split "*add<mode>3_poly_1"
2411 (match_operand:GPI 0 "register_operand")
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 ] #
2425 "&& epilogue_completed
2426 && !reg_overlap_mentioned_p (operands[0], operands[1])
2427 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)"
2430 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
2431 operands[2], operands[0], NULL_RTX);
2434 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
2438 [(set (match_operand:DI 0 "register_operand")
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))))]
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]);
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 "" ""))]
2462 if (CONST_INT_P (operands[2]))
2463 emit_insn (gen_add<mode>3_compareV_imm (operands[0], operands[1],
2466 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
2467 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
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 "" ""))]
2479 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
2480 aarch64_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
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")))]
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)
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));
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)));
2512 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2513 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
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 "" ""))]
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)
2534 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
2535 force_reg (DImode, op2_high)));
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)));
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]);
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 "" ""))]
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)
2568 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
2569 force_reg (DImode, op2_high)));
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)));
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]);
2586 (define_insn "add<mode>3_compare0"
2587 [(set (reg:CC_NZ CC_REGNUM)
2589 (plus:GPI (match_operand:GPI 1 "register_operand")
2590 (match_operand:GPI 2 "aarch64_plus_operand"))
2592 (set (match_operand:GPI 0 "register_operand")
2593 (plus:GPI (match_dup 1) (match_dup 2)))]
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
2602 ;; zero_extend version of above
2603 (define_insn "*addsi3_compare0_uxtw"
2604 [(set (reg:CC_NZ CC_REGNUM)
2606 (plus:SI (match_operand:SI 1 "register_operand")
2607 (match_operand:SI 2 "aarch64_plus_operand"))
2609 (set (match_operand:DI 0 "register_operand")
2610 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
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
2619 (define_insn "*add<mode>3_compareC_cconly"
2620 [(set (reg:CC_C CC_REGNUM)
2623 (match_operand:GPI 0 "register_operand")
2624 (match_operand:GPI 1 "aarch64_plus_operand"))
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
2634 (define_insn "add<mode>3_compareC"
2635 [(set (reg:CC_C CC_REGNUM)
2638 (match_operand:GPI 1 "register_operand")
2639 (match_operand:GPI 2 "aarch64_plus_operand"))
2641 (set (match_operand:GPI 0 "register_operand")
2642 (plus:GPI (match_dup 1) (match_dup 2)))]
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
2651 (define_insn "*add<mode>3_compareV_cconly_imm"
2652 [(set (reg:CC_V CC_REGNUM)
2655 (sign_extend:<DWI> (match_operand:GPI 0 "register_operand"))
2656 (match_operand:<DWI> 1 "const_scalar_int_operand"))
2660 (match_operand:GPI 2 "aarch64_plus_immediate")))))]
2661 "INTVAL (operands[1]) == INTVAL (operands[2])"
2663 [ r , I ] cmn\t%<w>0, %<w>1
2664 [ r , J ] cmp\t%<w>0, #%n1
2666 [(set_attr "type" "alus_imm")]
2669 (define_insn "*add<mode>3_compareV_cconly"
2670 [(set (reg:CC_V CC_REGNUM)
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)))))]
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)
2686 (match_operand:GPI 1 "register_operand"))
2687 (match_operand:GPI 2 "aarch64_plus_immediate"))
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)))]
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
2699 (define_insn "add<mode>3_compareV"
2700 [(set (reg:CC_V CC_REGNUM)
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)))]
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)
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"))
2721 (set (match_operand:GPI 0 "register_operand" "=r")
2722 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
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)
2732 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2734 (match_operand:GPI 2 "register_operand" "r")
2735 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
2737 (set (match_operand:GPI 0 "register_operand" "=r")
2738 (minus:GPI (match_dup 1)
2739 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
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)
2749 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2750 (match_operand:GPI 2 "register_operand" "rk"))
2752 (set (match_operand:GPI 0 "register_operand" "=r")
2753 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
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)
2762 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2764 (match_operand:ALLX 2 "register_operand" "r")))
2766 (set (match_operand:GPI 0 "register_operand" "=r")
2767 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
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)
2776 (plus:GPI (ashift:GPI
2778 (match_operand:ALLX 1 "register_operand" "r"))
2779 (match_operand 2 "aarch64_imm3" "Ui3"))
2780 (match_operand:GPI 3 "register_operand" "rk"))
2782 (set (match_operand:GPI 0 "register_operand" "=rk")
2783 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
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)
2794 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2797 (match_operand:ALLX 2 "register_operand" "r"))
2798 (match_operand 3 "aarch64_imm3" "Ui3")))
2800 (set (match_operand:GPI 0 "register_operand" "=rk")
2801 (minus:GPI (match_dup 1)
2802 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
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)
2812 (plus:GPI (match_operand:GPI 0 "register_operand")
2813 (match_operand:GPI 1 "aarch64_plus_operand"))
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
2823 (define_insn "aarch64_sub<mode>_compare0"
2824 [(set (reg:CC_NZ CC_REGNUM)
2826 (minus:GPI (match_operand:GPI 0 "register_operand" "r")
2827 (match_operand:GPI 1 "aarch64_plus_operand" "r"))
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)
2837 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2838 (match_operand:GPI 1 "register_operand" "r")))]
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")))]
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")
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"))))]
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")))]
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")
2879 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2880 (match_operand:GPI 2 "register_operand" "r"))))]
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")))]
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")
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"))))]
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")
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")))]
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")
2928 (match_operand:GPI 3 "aarch64_carry_operation" "")
2929 (match_operand:GPI 1 "register_operand" "r"))
2930 (match_operand:GPI 2 "register_operand" "r")))]
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")
2942 (match_operand:SI 3 "aarch64_carry_operation" "")
2943 (match_operand:SI 1 "register_operand" "r"))
2944 (match_operand:SI 2 "register_operand" "r"))))]
2946 "adc\\t%w0, %w1, %w2"
2947 [(set_attr "type" "adc_reg")]
2950 (define_expand "add<mode>3_carryinC"
2958 (match_operand:GPI 1 "register_operand")))
2960 (match_operand:GPI 2 "register_operand")))
2962 (set (match_operand:GPI 0 "register_operand")
2964 (plus:GPI (match_dup 5) (match_dup 1))
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),
2977 (define_insn "*add<mode>3_carryinC_zero"
2978 [(set (reg:CC_ADC CC_REGNUM)
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" "")
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)
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")
3004 (plus:GPI (match_operand:GPI 4 "aarch64_carry_operation" "")
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"
3015 [(set (reg:CC_V CC_REGNUM)
3021 (match_operand:GPI 1 "register_operand")))
3023 (match_operand:GPI 2 "register_operand")))
3026 (plus:GPI (match_dup 4) (match_dup 1))
3028 (set (match_operand:GPI 0 "register_operand")
3030 (plus:GPI (match_dup 4) (match_dup 1))
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)
3043 (match_operand:<DWI> 2 "aarch64_carry_operation" "")
3044 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
3047 (match_operand:GPI 3 "aarch64_carry_operation" "")
3049 (set (match_operand:GPI 0 "register_operand" "=r")
3050 (plus:GPI (match_dup 3) (match_dup 1)))]
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)
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")))
3067 (match_operand:GPI 4 "aarch64_carry_operation" "")
3070 (set (match_operand:GPI 0 "register_operand" "=r")
3072 (plus:GPI (match_dup 4) (match_dup 1))
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")
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"
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")
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"
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")))]
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")
3124 (minus:SI (match_operand:SI 1 "register_operand" "rk")
3125 (match_operand:SI 2 "register_operand" "r"))))]
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")))]
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
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 "" ""))]
3149 if (CONST_INT_P (operands[2]))
3150 emit_insn (gen_subv<mode>_imm (operands[0], operands[1], operands[2]));
3152 emit_insn (gen_subv<mode>_insn (operands[0], operands[1], operands[2]));
3153 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
3158 (define_insn "subv<GPI:mode>_insn"
3159 [(set (reg:CC_V CC_REGNUM)
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)))]
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)
3179 (match_operand:GPI 1 "register_operand")
3180 (match_operand:GPI 2 "aarch64_plus_immediate")))
3181 (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
3183 (set (match_operand:GPI 0 "register_operand")
3184 (minus:GPI (match_dup 1) (match_dup 2)))]
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
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 "" ""))]
3199 emit_insn (gen_negv<mode>_insn (operands[0], operands[1]));
3200 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
3206 (define_insn "negv<GPI:mode>_insn"
3207 [(set (reg:CC_V CC_REGNUM)
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)))]
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)
3223 (neg:GPI (match_operand:GPI 0 "register_operand" "r")))
3224 (neg:<DWI> (sign_extend:<DWI> (match_dup 0)))))]
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)
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)))))]
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
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 "" ""))]
3254 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
3255 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
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")))]
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);
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 "" ""))]
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]);
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 "" ""))]
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]);
3318 (define_expand "negvti3"
3319 [(match_operand:TI 0 "register_operand")
3320 (match_operand:TI 1 "register_operand")
3321 (label_ref (match_operand 2 "" ""))]
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]);
3334 (define_insn "negdi_carryout"
3335 [(set (reg:CC CC_REGNUM)
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)))]
3342 [(set_attr "type" "alus_sreg")]
3345 (define_insn "negvdi_carryinV"
3346 [(set (reg:CC_V CC_REGNUM)
3349 (ltu:TI (reg:CC CC_REGNUM) (const_int 0))
3350 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))))
3352 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
3354 (set (match_operand:DI 0 "register_operand" "=r")
3355 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
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"))
3367 (set (match_operand:GPI 0 "register_operand" "=r")
3368 (minus:GPI (match_dup 1) (match_dup 2)))]
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"))
3380 (set (match_operand:DI 0 "register_operand" "=r")
3381 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
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)
3390 (match_operand:GPI 1 "register_operand")
3391 (match_operand:GPI 2 "aarch64_plus_immediate")))
3392 (set (match_operand:GPI 0 "register_operand")
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
3401 [(set_attr "type" "alus_imm")]
3404 (define_insn "sub<mode>3_compare1"
3405 [(set (reg:CC CC_REGNUM)
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)))]
3412 "subs\\t%<w>0, %<w>1, %<w>2"
3413 [(set_attr "type" "alus_sreg")]
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)
3424 "!reg_overlap_mentioned_p (operands[0], operands[1])
3425 && !reg_overlap_mentioned_p (operands[0], operands[2])"
3428 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
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.
3438 [(set (reg:CC CC_REGNUM)
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)
3448 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
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)
3461 (match_operand:GPI 3 "const_int_operand")))]
3462 "!reg_overlap_mentioned_p (operands[0], operands[1])
3463 && INTVAL (operands[3]) == -INTVAL (operands[2])"
3466 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3467 operands[3], operands[2]));
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.
3476 [(set (reg:CC CC_REGNUM)
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])"
3486 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3487 operands[3], operands[2]));
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")
3496 (match_operand:GPI 1 "register_operand" "r")
3497 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
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")
3507 (minus:SI (match_operand:SI 3 "register_operand" "r")
3509 (match_operand:SI 1 "register_operand" "r")
3510 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
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")
3520 (match_operand:ALLX 2 "register_operand" "r"))))]
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")
3530 (minus:SI (match_operand:SI 1 "register_operand" "rk")
3532 (match_operand:SHORT 2 "register_operand" "r")))))]
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"))))]
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")
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")))))]
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")
3571 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3572 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
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")
3583 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3584 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
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")
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))))]
3601 (define_insn "*sub<mode>3_carryin"
3602 [(set (match_operand:GPI 0 "register_operand" "=r")
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" "")))]
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")
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" ""))))]
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")
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")))]
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")
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"))))]
3651 "sbc\\t%w0, %w1, %w2"
3652 [(set_attr "type" "adc_reg")]
3655 (define_expand "usub<GPI:mode>3_carryinC"
3657 [(set (reg:CC CC_REGNUM)
3660 (match_operand:GPI 1 "aarch64_reg_or_zero"))
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")
3667 (minus:GPI (match_dup 1) (match_dup 2))
3668 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3672 (define_insn "*usub<GPI:mode>3_carryinC_z1"
3673 [(set (reg:CC CC_REGNUM)
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")
3682 (neg:GPI (match_dup 1))
3683 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
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)
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")
3698 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
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)
3708 (match_operand:GPI 1 "register_operand" "r"))
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")
3715 (minus:GPI (match_dup 1) (match_dup 2))
3716 (match_operand:GPI 4 "aarch64_borrow_operation" "")))]
3718 "sbcs\\t%<w>0, %<w>1, %<w>2"
3719 [(set_attr "type" "adc_reg")]
3722 (define_expand "sub<GPI:mode>3_carryinV"
3724 [(set (reg:CC_V CC_REGNUM)
3728 (match_operand:GPI 1 "aarch64_reg_or_zero"))
3731 (match_operand:GPI 2 "register_operand"))
3732 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0))))
3734 (minus:GPI (match_dup 1)
3735 (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))
3737 (set (match_operand:GPI 0 "register_operand")
3739 (minus:GPI (match_dup 1) (match_dup 2))
3740 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3744 (define_insn "*sub<mode>3_carryinV_z2"
3745 [(set (reg:CC_V CC_REGNUM)
3748 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
3749 (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))
3751 (minus:GPI (match_dup 1)
3752 (match_operand:GPI 3 "aarch64_borrow_operation" "")))))
3753 (set (match_operand:GPI 0 "register_operand" "=r")
3755 (match_dup 1) (match_dup 3)))]
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)
3766 (match_operand:GPI 1 "register_operand" "r"))
3769 (match_operand:GPI 2 "register_operand" "r"))
3770 (match_operand:<DWI> 3 "aarch64_borrow_operation" "")))
3774 (plus:GPI (match_operand:GPI 4 "aarch64_borrow_operation" "")
3776 (set (match_operand:GPI 0 "register_operand" "=r")
3778 (minus:GPI (match_dup 1) (match_dup 2))
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")
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"
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")
3804 (minus:SI (match_operand:SI 4 "register_operand" "rk")
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"
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")))]
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")))]
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]));
3840 (define_insn "neg<mode>2"
3841 [(set (match_operand:GPI 0 "register_operand")
3842 (neg:GPI (match_operand:GPI 1 "register_operand")))]
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>
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"))))]
3856 [(set_attr "type" "alu_sreg")]
3859 (define_insn "*ngc<mode>"
3860 [(set (match_operand:GPI 0 "register_operand" "=r")
3862 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
3863 (match_operand:GPI 1 "register_operand" "r")))]
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")
3873 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
3874 (match_operand:SI 1 "register_operand" "r"))))]
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"))
3884 (set (match_operand:GPI 0 "register_operand" "=r")
3885 (neg:GPI (match_dup 1)))]
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"))
3896 (set (match_operand:DI 0 "register_operand" "=r")
3897 (zero_extend:DI (neg:SI (match_dup 1))))]
3900 [(set_attr "type" "alus_sreg")]
3903 (define_insn "*neg_<shift><mode>3_compare0"
3904 [(set (reg:CC_NZ CC_REGNUM)
3906 (neg:GPI (ASHIFT:GPI
3907 (match_operand:GPI 1 "register_operand" "r")
3908 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3910 (set (match_operand:GPI 0 "register_operand" "=r")
3911 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
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"))))]
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")
3932 (match_operand:SI 1 "register_operand" "r")
3933 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
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"
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")))]
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")
3964 (mult:SI (match_operand:SI 1 "register_operand" "r")
3965 (match_operand:SI 2 "register_operand" "r"))))]
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")))]
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")
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"))))]
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"))))]
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")
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")))))]
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")))]
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")
4031 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
4032 (match_operand:SI 2 "register_operand" "r"))))]
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"))))]
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")
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")))]
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")
4062 (match_operand:DI 3 "register_operand" "r")
4063 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
4065 (match_operand:SI 2 "register_operand" "r")))))]
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")
4074 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
4075 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
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"))))]
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);
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")))]
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);
4123 (define_insn "<su>muldi3_highpart"
4124 [(set (match_operand:DI 0 "register_operand" "=r")
4128 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
4129 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
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")))]
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")
4149 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
4150 (match_operand:SI 2 "register_operand" "r"))))]
4152 "<su>div\\t%w0, %w1, %w2"
4153 [(set_attr "type" "<su>div")]
4156 ;; -------------------------------------------------------------------
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")))]
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
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")))]
4178 [ w , Y ] fcmp\t%<s>0, #0.0
4179 [ w , w ] fcmp\t%<s>0, %<s>1
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")))]
4190 [ w , Y ] fcmpe\t%<s>0, #0.0
4191 [ w , w ] fcmpe\t%<s>0, %<s>1
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")))]
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")))]
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
4221 (match_operand:ALLX 0 "register_operand" "r"))
4222 (match_operand 1 "aarch64_imm3" "Ui3"))
4223 (match_operand:GPI 2 "register_operand" "r")))]
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")]))]
4240 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4242 operands[3] = const0_rtx;
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")]))]
4253 emit_insn (gen_rtx_SET (operands[0], operands[1]));
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")]))]
4265 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4267 operands[3] = const0_rtx;
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)]))]
4277 [(set_attr "type" "csel")]
4280 ;; For a 24-bit immediate CST we can optimize the compare for equality
4281 ;; and branch sequence from:
4283 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
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"
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));
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")
4319 (match_operator:SI 1 "aarch64_comparison_operator_mode"
4320 [(match_operand 2 "cc_register" "") (const_int 0)])))]
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)])))]
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")
4339 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
4340 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
4343 [(set_attr "type" "csel")]
4346 (define_expand "cmov<mode>6"
4347 [(set (match_operand:GPI 0 "register_operand")
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")))]
4356 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4358 operands[3] = const0_rtx;
4362 (define_expand "cmov<mode>6"
4363 [(set (match_operand:GPF 0 "register_operand")
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")))]
4372 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4374 operands[3] = const0_rtx;
4378 (define_insn "*cmov<mode>_insn"
4379 [(set (match_operand:ALLI 0 "register_operand")
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
4399 ;; zero_extend version of above
4400 (define_insn "*cmovsi_insn_uxtw"
4401 [(set (match_operand:DI 0 "register_operand")
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
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")
4429 (match_operator:GPI 1 "aarch64_comparison_operator"
4430 [(match_operand 2 "cc_register" "") (const_int 0)]))
4431 (match_operand 3 "register_operand" "r")))]
4436 (if_then_else:GPI (match_dup 1)
4440 [(set_attr "type" "csel")]
4443 (define_insn "*cmovdi_insn_uxtw"
4444 [(set (match_operand:DI 0 "register_operand" "=r")
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"))))]
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")
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")))]
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")))]
4475 enum rtx_code code = GET_CODE (operands[1]);
4477 if (code == UNEQ || code == LTGT)
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);
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")))]
4494 enum rtx_code code = GET_CODE (operands[1]);
4496 if (code == UNEQ || code == LTGT)
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);
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")))]
4513 enum rtx_code code = GET_CODE (operands[1]);
4515 if (code == UNEQ || code == LTGT)
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);
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")))]
4532 enum rtx_code code = GET_CODE (operands[1]);
4534 if (code == UNEQ || code == LTGT)
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);
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")]
4551 if (GET_MODE_BITSIZE (<crc_mode>mode) >= 64)
4552 return "<crc_variant>\\t%w0, %w1, %x2";
4554 return "<crc_variant>\\t%w0, %w1, %w2";
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")))]
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")
4571 (match_operand 1 "aarch64_comparison_operation" "")
4572 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
4574 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
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")
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")))]
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")
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"))))]
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")
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")))]
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")
4617 (match_operand 1 "aarch64_comparison_operation" "")
4619 (match_operand:SI 2 "register_operand" "r"))
4621 (NEG_NOT:SI (match_operand:SI 3 "register_operand" "r")))))]
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")
4630 (match_operand 1 "aarch64_comparison_operation" "")
4632 (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
4634 (match_operand:SI 3 "register_operand" "r"))))]
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")
4643 (match_operand 1 "aarch64_comparison_operation" "")
4645 (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
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")
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")))]
4668 (if_then_else:GPI (match_dup 1)
4669 (not:GPI (match_dup 3))
4672 /* After reload this will be a nop due to the constraint. */
4673 operands[3] = force_reg (<MODE>mode, operands[3]);
4675 [(set_attr "type" "csel")]
4678 (define_insn_and_split "*cmov_uxtw_insn_insv"
4679 [(set (match_operand:DI 0 "register_operand" "=r")
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"))))]
4690 (if_then_else:DI (match_dup 1)
4691 (zero_extend:DI (not:SI (match_dup 3)))
4692 (zero_extend:DI (match_dup 3))))]
4694 operands[3] = force_reg (SImode, operands[3]);
4696 [(set_attr "type" "csel")]
4699 ;; If X can be loaded by a single CNT[BHWD] instruction,
4703 ;; is equivalent to:
4705 ;; TMP = UQDEC[BHWD] (B, X)
4708 ;; Defining the pattern this way means that:
4710 ;; A = UMAX (B, X) - X
4714 ;; TMP1 = UQDEC[BHWD] (B, 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"
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))
4735 else if (TARGET_CSSC)
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],
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]));
4756 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4757 (define_insn "aarch64_uqdec<mode>"
4758 [(set (match_operand:GPI 0 "register_operand" "=r")
4760 (umax:GPI (match_operand:GPI 1 "register_operand" "0")
4761 (match_operand:GPI 2 "aarch64_sve_cnt_immediate" "Usv"))
4765 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>0", operands[2]);
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")
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)"
4783 [(set (reg:CC CC_REGNUM)
4784 (compare:CC (match_dup 1) (match_dup 4)))
4786 (plus:GPI (match_dup 1) (match_dup 3)))])
4788 (if_then_else:GPI (match_dup 5) (match_dup 6) (match_dup 7)))]
4790 if (!aarch64_maxmin_plus_const (<CODE>, operands, true))
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>")))]
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));
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")))]
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>
4833 ;; zero_extend version of above
4834 (define_insn "*<optab>si3_uxtw"
4835 [(set (match_operand:DI 0 "register_operand")
4837 (LOGICAL:SI (match_operand:SI 1 "register_operand")
4838 (match_operand:SI 2 "aarch64_logical_operand"))))]
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
4846 (define_insn "*and<mode>3_compare0"
4847 [(set (reg:CC_NZV CC_REGNUM)
4849 (and:GPI (match_operand:GPI 1 "register_operand")
4850 (match_operand:GPI 2 "aarch64_logical_operand"))
4852 (set (match_operand:GPI 0 "register_operand")
4853 (and:GPI (match_dup 1) (match_dup 2)))]
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
4861 ;; zero_extend version of above
4862 (define_insn "*andsi3_compare0_uxtw"
4863 [(set (reg:CC_NZV CC_REGNUM)
4865 (and:SI (match_operand:SI 1 "register_operand")
4866 (match_operand:SI 2 "aarch64_logical_operand"))
4868 (set (match_operand:DI 0 "register_operand")
4869 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
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
4877 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
4878 [(set (reg:CC_NZV CC_REGNUM)
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"))
4885 (set (match_operand:GPI 0 "register_operand" "=r")
4886 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
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)
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"))
4905 (set (match_operand:DI 0 "register_operand" "=r")
4906 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
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")))]
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")]
4933 [(set (match_operand:GPI 0 "register_operand")
4934 (LOGICAL_OR_PLUS: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]),
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))
4948 operands[5] = gen_reg_rtx (<MODE>mode);
4950 = gen_int_mode (UINTVAL (operands[3]) << UINTVAL (operands[2]),
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]))
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))]
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]);
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]))
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))]
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]);
5009 [(set (match_operand:GPI 0 "register_operand")
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))
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")
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"))))]
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")))]
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
5048 (define_insn "*one_cmpl_zero_extend"
5049 [(set (match_operand:DI 0 "register_operand" "=r")
5051 (not:SI (match_operand:SI 1 "register_operand" "r"))))]
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"))))]
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")))]
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>
5083 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
5084 [(set (match_operand:DI 0 "register_operand" "=r")
5086 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
5087 (match_operand:SI 2 "register_operand" "r"))))]
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")
5096 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
5097 (match_operand:SI 2 "register_operand" "r")))))]
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"))))]
5111 eon\\t%<w>0, %<w>1, %<w>2
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)))]
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)
5127 (match_operand:GPI 1 "register_operand" "r"))
5128 (match_operand:GPI 2 "register_operand" "r"))
5130 (set (match_operand:GPI 0 "register_operand" "=r")
5131 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
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)
5142 (match_operand:SI 1 "register_operand" "r"))
5143 (match_operand:SI 2 "register_operand" "r"))
5145 (set (match_operand:DI 0 "register_operand" "=r")
5146 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
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)
5156 (match_operand:GPI 0 "register_operand" "r"))
5157 (match_operand:GPI 1 "register_operand" "r"))
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
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")))]
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
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"))))]
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")
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"))))]
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")
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")))))]
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)
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"))
5240 (set (match_operand:GPI 0 "register_operand" "=r")
5243 (match_dup 1) (match_dup 2))) (match_dup 3)))]
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)
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"))
5263 (set (match_operand:DI 0 "register_operand" "=r")
5264 (zero_extend:DI (and:SI
5266 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
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)
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"))
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")))]
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")]
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));
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")))]
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
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"
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)
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));
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));
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")))]
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")))]
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")))]
5385 { return TARGET_CSSC ? "ctz\\t%<w>0, %<w>1" : "#"; }
5386 "reload_completed && !TARGET_CSSC"
5389 emit_insn (gen_aarch64_rbit (<MODE>mode, operands[0], operands[1]));
5390 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
5394 (define_insn "*and<mode>_compare0"
5395 [(set (reg:CC_Z CC_REGNUM)
5397 (match_operand:SHORT 0 "register_operand" "r")
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)
5407 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
5409 (set (match_operand:GPI 0 "register_operand" "=r")
5410 (zero_extend:GPI (match_dup 1)))]
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)
5419 (and:GPI (match_operand:GPI 0 "register_operand")
5420 (match_operand:GPI 1 "aarch64_logical_operand"))
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
5430 [(set (reg:CC_NZV CC_REGNUM)
5432 (and:GPI (match_operand:GPI 0 "register_operand")
5433 (match_operand:GPI 1 "aarch64_mov_imm_operand"))
5435 (clobber (match_operand:SI 2 "register_operand"))]
5437 [(set (match_dup 2) (match_dup 1))
5438 (set (reg:CC_NZV CC_REGNUM)
5440 (and:GPI (match_dup 0)
5445 (define_insn "*and<mode>3nr_compare0_zextract"
5446 [(set (reg:CC_Z CC_REGNUM)
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"))
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],
5461 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
5462 return "tst\\t%<w>0, %1";
5464 [(set_attr "type" "logics_shift_imm")]
5467 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
5468 [(set (reg:CC_NZV CC_REGNUM)
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"))
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")]
5485 [(set (reg:CC_NZV CC_REGNUM)
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"))
5492 (clobber (match_operand:SI 3 "register_operand"))]
5494 [(set (match_dup 3) (match_dup 2))
5495 (set (reg:CC_NZV CC_REGNUM)
5504 ;; -------------------------------------------------------------------
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")))]
5514 if (CONST_INT_P (operands[2]))
5516 operands[2] = GEN_INT (INTVAL (operands[2])
5517 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
5519 if (operands[2] == const0_rtx)
5521 emit_insn (gen_mov<mode> (operands[0], operands[1]));
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")))]
5534 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
5536 if (operands[2] == const0_rtx)
5538 emit_insn (gen_mov<mode> (operands[0], operands[1]));
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")))]
5550 if (CONST_INT_P (operands[2]))
5552 operands[2] = GEN_INT (INTVAL (operands[2])
5553 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
5555 if (operands[2] == const0_rtx)
5557 emit_insn (gen_mov<mode> (operands[0], operands[1]));
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")))]
5570 /* (SZ - cnt) % SZ == -cnt % SZ */
5571 if (CONST_INT_P (operands[2]))
5573 operands[2] = GEN_INT ((-UINTVAL (operands[2]))
5574 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
5575 if (operands[2] == const0_rtx)
5577 emit_insn (gen_mov<mode> (operands[0], operands[1]));
5582 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
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")
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")
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)"
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));
5631 (define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask"
5632 [(set (match_operand:GPI 0 "register_operand" "=&r")
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)"
5645 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
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));
5659 (define_insn "*aarch64_<optab>_reg_di3_mask2"
5660 [(set (match_operand:DI 0 "register_operand" "=r")
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)"
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);
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")
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)"
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));
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")
5711 (match_operand:GPI 1 "register_operand")
5712 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>")))]
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>
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")
5726 (match_operand:GPI 1 "register_operand")
5727 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>")))]
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 ] #
5739 [(set (match_operand:DI 0 "aarch64_simd_register")
5741 (match_operand:DI 1 "aarch64_simd_register")
5742 (match_operand:QI 2 "aarch64_simd_register")))]
5743 "TARGET_SIMD && reload_completed"
5745 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5747 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
5749 operands[3] = gen_lowpart (QImode, operands[0]);
5754 [(set (match_operand:SI 0 "aarch64_simd_register")
5756 (match_operand:SI 1 "aarch64_simd_register")
5757 (match_operand:QI 2 "aarch64_simd_register")))]
5758 "TARGET_SIMD && reload_completed"
5760 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5762 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
5764 operands[3] = gen_lowpart (QImode, operands[0]);
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")
5772 (match_operand:GPI 1 "register_operand")
5773 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di")))]
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 ] #
5785 [(set (match_operand:DI 0 "aarch64_simd_register")
5787 (match_operand:DI 1 "aarch64_simd_register")
5788 (match_operand:QI 2 "aarch64_simd_register")))]
5789 "TARGET_SIMD && reload_completed"
5791 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5793 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
5795 operands[3] = gen_lowpart (QImode, operands[0]);
5800 [(set (match_operand:SI 0 "aarch64_simd_register")
5802 (match_operand:SI 1 "aarch64_simd_register")
5803 (match_operand:QI 2 "aarch64_simd_register")))]
5804 "TARGET_SIMD && reload_completed"
5806 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
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")]
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")]
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")]
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")]
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")]
5860 [(set_attr "type" "neon_neg")]
5864 (define_insn "*ror<mode>3_insn"
5865 [(set (match_operand:GPI 0 "register_operand")
5867 (match_operand:GPI 1 "register_operand")
5868 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>")))]
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
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"))))]
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
5901 ;; zero_extend version of rotate right
5902 (define_insn "*rorsi3_insn_uxtw"
5903 [(set (match_operand:DI 0 "register_operand" "=r")
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")
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")
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")
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"
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")
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")
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")
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 ;; -------------------------------------------------------------------
6049 ;; -------------------------------------------------------------------
6051 (define_expand "<optab>"
6052 [(set (match_operand:DI 0 "register_operand")
6053 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
6055 "aarch64_simd_shift_imm_offset_di")
6056 (match_operand 3 "aarch64_simd_shift_imm_di")))]
6059 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
6060 1, GET_MODE_BITSIZE (DImode) - 1))
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")
6070 "aarch64_simd_shift_imm_offset_<mode>" "n")
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.
6082 [(set (match_operand:DI 0 "register_operand")
6083 (zero_extract:DI (match_operand:DI 1 "register_operand")
6085 "aarch64_simd_shift_imm_offset_di")
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)"
6093 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
6095 operands[4] = gen_lowpart (SImode, operands[1]);
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"))]
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))
6114 if (CONST_INT_P (value))
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)
6123 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
6124 if (width == 16 && (pos % 16) == 0)
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>"
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";
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>"
6171 [(set (zero_extract:GPI (match_dup 0)
6172 (const_int SUBDI_BITS)
6176 operands[2] = lowpart_subreg (<GPI:MODE>mode, operands[2],
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"
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"
6204 [(set (zero_extract:DI (match_dup 0)
6205 (const_int SUBDI_BITS)
6209 operands[2] = lowpart_subreg (DImode, operands[3], <ALLX:MODE>mode);
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"))
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"))
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"
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")
6351 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
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")
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")
6405 (match_operator:SI 4 "subreg_lowpart_operator"
6407 (match_operand:DI 1 "register_operand" "r")
6408 (match_operand 2 "aarch64_simd_shift_imm_offset_si")
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.
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)"
6429 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
6431 operands[4] = gen_lowpart (SImode, operands[1]);
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")))]
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")))]
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])))"
6461 switch (which_alternative)
6464 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
6465 return "bfxil\\t%<w>0, %<w>1, 0, %3";
6467 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
6468 return "bfxil\\t%<w>0, %<w>2, 0, %3";
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"
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])))"
6488 switch (which_alternative)
6491 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
6492 return "bfxil\\t%w0, %w1, 0, %3";
6494 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
6495 return "bfxil\\t%w0, %w2, 0, %3";
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")
6511 (match_operand:GPI 3 "const_int_operand" "n"))
6512 (and:GPI (lshiftrt:GPI (match_dup 1)
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")
6525 (match_operand:GPI 2 "const_int_operand" "n"))
6526 (and:GPI (ashift:GPI (match_dup 1)
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"))
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"))))]
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")]
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],
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")]
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")
6590 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
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")
6601 (match_operand:GPF 1 "register_operand" "w")
6602 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
6604 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
6605 GET_MODE_BITSIZE (<GPI:MODE>mode))"
6607 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
6609 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
6610 output_asm_insn (buf, operands);
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")))]
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")))]
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")
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")))]
6648 (define_insn "*aarch64_fnma<mode>4"
6649 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
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")))]
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"))))]
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"))))]
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"))))]
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"))))]
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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
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")))]
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")))]
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")
6797 (match_operand:GPF 1 "register_operand" "w"))))]
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")))]
6811 operands[2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[2]));
6812 switch (which_alternative)
6815 return "<su_optab>cvtf\t%<GPF:s>0, %<s>1, #%2";
6817 return "<su_optab>cvtf\t%<GPF:s>0, %<w1>1, #%2";
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")))]
6834 operands[2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[2]));
6835 return "<su_optab>cvtf\t%<GPF:s>0, %<w2>1, #%2";
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")))]
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
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")))]
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")))]
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")))]
6880 if (TARGET_FP_F16INST)
6881 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
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));
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
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]));
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));
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")]
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
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")]
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
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")]
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")]
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")]
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")]
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")
6995 (match_operand:GPF_F16 1 "register_operand" "w")
6996 (match_operand:GPF_F16 2 "register_operand" "w")))]
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")
7005 (match_operand:GPF_F16 1 "register_operand" "w")
7006 (match_operand:GPF_F16 2 "register_operand" "w")))]
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")
7015 (match_operand:GPF_F16 1 "register_operand" "w")
7016 (match_operand:GPF_F16 2 "register_operand" "w")))]
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")
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")
7035 (match_operand:GPF 1 "register_operand" "w")
7036 (match_operand:GPF 2 "register_operand" "w"))))]
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")))]
7048 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
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")))]
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")))]
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")))]
7076 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
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")))]
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")))]
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")
7104 (match_operand:GPI 1 "register_operand")
7105 (match_operand:GPI 2 "aarch64_<su>minmax_operand")))]
7110 if (operands[2] != CONST0_RTX (<MODE>mode)
7111 || !(<CODE> == SMAX || <CODE> == SMIN))
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")))]
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
7128 (define_insn "*aarch64_<optab><mode>3_zero"
7129 [(set (match_operand:GPI 0 "register_operand" "=r")
7131 (match_operand:GPI 1 "register_operand" "r")
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
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")))]
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")))]
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")]
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")]
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));
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")]
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
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)))
7217 = force_reg (V2<V_INT_EQUIV>mode,
7218 gen_const_vec_duplicate (V2<V_INT_EQUIV>mode,
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),
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],
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")]
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>
7254 ;; For xorsign (x, y), we want to generate:
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")]
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));
7277 ;; -------------------------------------------------------------------
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"))]
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]));
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"))]
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]));
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"))
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]);
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)"
7334 [(set_attr "type" "f_mrc")
7335 (set_attr "length" "4")
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")
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")
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)"
7363 [(set_attr "type" "f_mcr")
7364 (set_attr "length" "4")
7367 (define_insn "aarch64_movtilow_tilow"
7368 [(set (match_operand:TI 0 "register_operand" "=w")
7370 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
7371 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
7373 [(set_attr "type" "fmov")
7374 (set_attr "length" "4")
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
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")))]
7388 machine_mode mode = GET_MODE (operands[0]);
7390 emit_insn ((mode == DImode
7392 : gen_add_losym_si) (operands[0],
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")))]
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))]
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")
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)))]
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))]
7436 [(set_attr "type" "load_<ldst_sz>")]
7439 (define_insn "ldr_got_tiny_sidi"
7440 [(set (match_operand:DI 0 "register_operand" "=r")
7442 (unspec:SI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
7443 UNSPEC_GOTTINYPIC)))]
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))]
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))])]
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))
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))]
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")
7496 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
7497 UNSPEC_GOTSMALLTLS)))]
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))]
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")
7518 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
7519 (match_operand:DI 2 "register_operand" "r")
7521 UNSPEC_GOTTINYTLS)))]
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")]
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")]
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")]
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")]
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)]
7576 rtx abi = aarch64_gen_callee_cookie (AARCH64_ISA_MODE,
7577 aarch64_tlsdesc_abi_id ());
7579 = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[0], abi));
7580 RTL_CONST_CALL_P (call) = 1;
7583 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
7588 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
7590 (define_insn "tlsdesc_small_advsimd_<mode>"
7591 [(set (reg:PTR R0_REGNUM)
7592 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
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")]
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")]
7625 "REGNO (operands[0]) == INTVAL (operands[1])"
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")]
7634 (clobber (reg:CC CC_REGNUM))]
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
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))]
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))]
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))]
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)]
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))]
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))]
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")]
7730 rtx tmp = aarch64_load_tp (operands[0]);
7731 if (tmp != operands[0])
7732 emit_move_insn (operands[0], tmp);
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 "")]
7744 emit_insn (gen_stack_protect_combined_set (operands[0], operands[1]));
7748 (define_expand "stack_protect_combined_set"
7749 [(match_operand 0 "memory_operand")
7750 (match_operand 1 "")]
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]));
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"
7770 snprintf (buf, 150, "mrs\\t%%<w>0, %s",
7771 aarch64_stack_protector_guard_reg_str);
7772 output_asm_insn (buf, operands);
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")]
7783 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
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 "")
7798 emit_insn (gen_stack_protect_combined_test (operands[0], operands[1],
7803 (define_expand "stack_protect_combined_test"
7804 [(match_operand 0 "memory_operand")
7805 (match_operand 1 "")
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]));
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")]
7829 (clobber (match_scratch:PTR 2 "=&r"))
7830 (clobber (match_scratch:PTR 3 "=&r"))]
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)]
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))]
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"
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)
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,
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))]
7896 operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7897 output_asm_insn ("csel\\t%1, %1, xzr, %m0", operands);
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))]
7910 operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7911 output_asm_insn ("csel\\t%1, %1, xzr, %M0", operands);
7914 [(set_attr "type" "csel")]
7917 ;; BTI <target> instructions
7918 (define_insn "bti_noarg"
7919 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_NOARG)]
7922 [(set_attr "type" "no_insn")]
7925 (define_insn "bti_c"
7926 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_C)]
7929 [(set_attr "type" "no_insn")]
7932 (define_insn "bti_j"
7933 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_J)]
7936 [(set_attr "type" "no_insn")]
7939 (define_insn "bti_jc"
7940 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_JC)]
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)]
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))]
7969 if (operands[2] == const0_rtx)
7972 if (<MODE>mode == TImode)
7973 tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7975 tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
7977 emit_insn (gen_despeculate_simple<mode> (operands[0], operands[1],
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))]
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",
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")
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))]
8016 operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
8018 ("cmp\\t%3, #0\;csel\\t%0, %1, %2, ne\;csel\\t%H0, %H1, %H2, ne\;hint\t0x14 // csdb",
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))]
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")
8043 [(match_operand:TI 1 "register_operand" "r")
8044 (use (match_operand:DI 2 "register_operand" ""))]
8045 UNSPECV_SPECULATION_BARRIER))]
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")]
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)))]
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)))]
8080 [(set_attr "type" "tme")]
8083 (define_insn "tcommit"
8084 [(unspec_volatile:BLK [(const_int 0)] UNSPECV_TCOMMIT)
8085 (clobber (mem:BLK (scratch)))]
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)"
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))]
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))]
8117 [(set_attr "type" "mrs")]
8120 ;; Memory Tagging Extension (MTE) instructions.
8123 [(set (match_operand:DI 0 "register_operand" "=rk")
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")]
8132 [(set_attr "type" "memtag")]
8136 [(set (match_operand:DI 0 "register_operand" "=r")
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")))]
8145 [(set_attr "type" "memtag")]
8149 [(set (match_operand:DI 0 "register_operand" "=rk")
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...
8156 [(and:QI (lshiftrt:DI (match_dup 1) (const_int 56)) (const_int 15))
8157 (match_operand:QI 3 "aarch64_memtag_tag_offset" "i")]
8161 "addg\\t%0, %1, #%2, #%3"
8162 [(set_attr "type" "memtag")]
8166 [(set (match_operand:DI 0 "register_operand" "=r")
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...
8174 [(set_attr "type" "memtag")]
8177 ;; LDG will use the 16-byte aligned value of the address.
8179 [(set (match_operand:DI 0 "register_operand" "+r")
8181 (and:DI (match_dup 0) (const_int -1080863910568919041)) ;; 0xf0ff...
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))
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.
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"))]
8200 (and:QI (lshiftrt:DI (match_operand:DI 0 "register_operand" "rk")
8201 (const_int 56)) (const_int 15)))]
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"))]
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")]
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")]
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")]
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)]
8259 aarch64_output_patchable_area (INTVAL (operands[0]),
8260 INTVAL (operands[1]) != 0);
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))]
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))]
8282 (include "aarch64-simd.md")
8284 ;; Atomic Operations
8285 (include "atomics.md")
8287 ;; ldp/stp peephole patterns
8288 (include "aarch64-ldpstp.md")
8291 (include "aarch64-sve.md")
8294 (include "aarch64-sve2.md")
8296 ;; SME and extensions
8297 (include "aarch64-sme.md")