1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2021 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.
114 ;; The pair of scratch registers used for stack probing with -fstack-check.
115 ;; Leave R9 alone as a possible choice for the static chain.
116 ;; Note that the use of these registers is mutually exclusive with the use
117 ;; of STACK_CLASH_SVE_CFA_REGNUM, which is for -fstack-clash-protection
118 ;; rather than -fstack-check.
119 (PROBE_STACK_FIRST_REGNUM 10)
120 (PROBE_STACK_SECOND_REGNUM 11)
121 ;; Scratch register used by stack clash protection to calculate
122 ;; SVE CFA offsets during probing.
123 (STACK_CLASH_SVE_CFA_REGNUM 11)
124 ;; Scratch registers for prologue/epilogue use.
127 ;; A couple of call-clobbered registers that we need to reserve when
128 ;; tracking speculation this is not ABI, so is subject to change.
129 (SPECULATION_SCRATCH_REGNUM 14)
130 (SPECULATION_TRACKER_REGNUM 15)
131 ;; Scratch registers used in frame layout.
139 (define_c_enum "unspec" [
173 UNSPEC_GOTSMALLPIC28K
271 UNSPEC_SPECULATION_TRACKER
272 UNSPEC_SPECULATION_TRACKER_REV
274 UNSPEC_TTEST ; Represent transaction test.
279 ;; Represents an SVE-style lane index, in which the indexing applies
280 ;; within the containing 128-bit block.
281 UNSPEC_SVE_LANE_SELECT
284 UNSPEC_SVE_PREFETCH_GATHER
287 UNSPEC_GEN_TAG ; Generate a 4-bit MTE tag.
288 UNSPEC_GEN_TAG_RND ; Generate a random 4-bit MTE tag.
289 UNSPEC_TAG_SPACE ; Translate address to MTE tag address space.
294 (define_c_enum "unspecv" [
295 UNSPECV_EH_RETURN ; Represent EH_RETURN
296 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
297 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
298 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
299 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
300 UNSPECV_BLOCKAGE ; Represent a blockage
301 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
302 UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
303 UNSPECV_BTI_NOARG ; Represent BTI.
304 UNSPECV_BTI_C ; Represent BTI c.
305 UNSPECV_BTI_J ; Represent BTI j.
306 UNSPECV_BTI_JC ; Represent BTI jc.
307 UNSPECV_TSTART ; Represent transaction start.
308 UNSPECV_TCOMMIT ; Represent transaction commit.
309 UNSPECV_TCANCEL ; Represent transaction cancel.
310 UNSPEC_RNDR ; Represent RNDR
311 UNSPEC_RNDRRS ; Represent RNDRRS
315 ;; These constants are used as a const_int in various SVE unspecs
316 ;; to indicate whether the governing predicate is known to be a PTRUE.
318 [; Indicates that the predicate might not be a PTRUE.
319 (SVE_MAYBE_NOT_PTRUE 0)
321 ; Indicates that the predicate is known to be a PTRUE.
322 (SVE_KNOWN_PTRUE 1)])
324 ;; These constants are used as a const_int in predicated SVE FP arithmetic
325 ;; to indicate whether the operation is allowed to make additional lanes
326 ;; active without worrying about the effect on faulting behavior.
328 [; Indicates either that all lanes are active or that the instruction may
329 ; operate on inactive inputs even if doing so could induce a fault.
332 ; Indicates that some lanes might be inactive and that the instruction
333 ; must not operate on inactive inputs if doing so could induce a fault.
336 ;; If further include files are added the defintion of MD_INCLUDES
339 (include "constraints.md")
340 (include "predicates.md")
341 (include "iterators.md")
343 ;; -------------------------------------------------------------------
344 ;; Instruction types and attributes
345 ;; -------------------------------------------------------------------
347 ; The "type" attribute is included here from AArch32 backend to be able
348 ; to share pipeline descriptions.
349 (include "../arm/types.md")
351 ;; It is important to set the fp or simd attributes to yes when a pattern
352 ;; alternative uses the FP or SIMD register files, usually signified by use of
353 ;; the 'w' constraint. This will ensure that the alternative will be
354 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
355 ;; architecture extensions. If all the alternatives in a pattern use the
356 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
359 ;; Attributes of the architecture required to support the instruction (or
360 ;; alternative). This attribute is used to compute attribute "enabled", use type
361 ;; "any" to enable an alternative in all cases.
363 (define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
365 (define_enum_attr "arch" "arches" (const_string "any"))
367 ;; [For compatibility with Arm in pipeline models]
368 ;; Attribute that specifies whether or not the instruction touches fp
370 ;; Note that this attribute is not used anywhere in either the arm or aarch64
371 ;; backends except in the scheduling description for xgene1. In that
372 ;; scheduling description this attribute is used to subclass the load_4 and
374 (define_attr "fp" "no,yes"
376 (eq_attr "arch" "fp")
378 (const_string "no")))
380 (define_attr "arch_enabled" "no,yes"
383 (eq_attr "arch" "any")
385 (and (eq_attr "arch" "rcpc8_4")
386 (match_test "AARCH64_ISA_RCPC8_4"))
388 (and (eq_attr "arch" "fp")
389 (match_test "TARGET_FLOAT"))
391 (and (eq_attr "arch" "simd")
392 (match_test "TARGET_SIMD"))
394 (and (eq_attr "arch" "fp16")
395 (match_test "TARGET_FP_F16INST"))
397 (and (eq_attr "arch" "sve")
398 (match_test "TARGET_SVE")))
400 (const_string "no")))
402 ;; Attribute that controls whether an alternative is enabled or not.
403 ;; Currently it is only used to disable alternatives which touch fp or simd
404 ;; registers when -mgeneral-regs-only is specified or to require a special
405 ;; architecture support.
406 (define_attr "enabled" "no,yes" (attr "arch_enabled"))
408 ;; Attribute that specifies whether we are dealing with a branch to a
409 ;; label that is far away, i.e. further away than the maximum/minimum
410 ;; representable in a signed 21-bits number.
413 (define_attr "far_branch" "" (const_int 0))
415 ;; Attribute that specifies whether the alternative uses MOVPRFX.
416 (define_attr "movprfx" "no,yes" (const_string "no"))
418 ;; Attribute to specify that an alternative has the length of a single
419 ;; instruction plus a speculation barrier.
420 (define_attr "sls_length" "none,retbr,casesi" (const_string "none"))
422 (define_attr "length" ""
423 (cond [(eq_attr "movprfx" "yes")
426 (eq_attr "sls_length" "retbr")
427 (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 4)
428 (match_test "TARGET_SB") (const_int 8)]
431 (eq_attr "sls_length" "casesi")
432 (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 16)
433 (match_test "TARGET_SB") (const_int 20)]
438 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
439 ;; no predicated insns.
440 (define_attr "predicated" "yes,no" (const_string "no"))
442 ;; Set to true on an insn that requires the speculation tracking state to be
443 ;; in the tracking register before the insn issues. Otherwise the compiler
444 ;; may chose to hold the tracking state encoded in SP.
445 (define_attr "speculation_barrier" "true,false" (const_string "false"))
447 ;; -------------------------------------------------------------------
448 ;; Pipeline descriptions and scheduling
449 ;; -------------------------------------------------------------------
452 (include "aarch64-tune.md")
455 (include "../arm/cortex-a53.md")
456 (include "../arm/cortex-a57.md")
457 (include "../arm/exynos-m1.md")
458 (include "falkor.md")
459 (include "saphira.md")
460 (include "thunderx.md")
461 (include "../arm/xgene1.md")
462 (include "thunderx2t99.md")
463 (include "tsv110.md")
464 (include "thunderx3t110.md")
466 ;; -------------------------------------------------------------------
467 ;; Jumps and other miscellaneous insns
468 ;; -------------------------------------------------------------------
470 (define_insn "indirect_jump"
471 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
474 output_asm_insn ("br\\t%0", operands);
475 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
477 [(set_attr "type" "branch")
478 (set_attr "sls_length" "retbr")]
482 [(set (pc) (label_ref (match_operand 0 "" "")))]
485 [(set_attr "type" "branch")]
488 (define_expand "cbranch<mode>4"
489 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
490 [(match_operand:GPI 1 "register_operand")
491 (match_operand:GPI 2 "aarch64_plus_operand")])
492 (label_ref (match_operand 3 "" ""))
496 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
498 operands[2] = const0_rtx;
502 (define_expand "cbranch<mode>4"
503 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
504 [(match_operand:GPF 1 "register_operand")
505 (match_operand:GPF 2 "aarch64_fp_compare_operand")])
506 (label_ref (match_operand 3 "" ""))
510 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
512 operands[2] = const0_rtx;
516 (define_expand "cbranchcc4"
517 [(set (pc) (if_then_else
518 (match_operator 0 "aarch64_comparison_operator"
519 [(match_operand 1 "cc_register")
520 (match_operand 2 "const0_operand")])
521 (label_ref (match_operand 3 "" ""))
526 (define_insn "@ccmp<CC_ONLY:mode><GPI:mode>"
527 [(set (match_operand:CC_ONLY 1 "cc_register" "")
528 (if_then_else:CC_ONLY
529 (match_operator 4 "aarch64_comparison_operator"
530 [(match_operand 0 "cc_register" "")
533 (match_operand:GPI 2 "register_operand" "r,r,r")
534 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
536 [(match_operand 5 "immediate_operand")]
540 ccmp\\t%<w>2, %<w>3, %k5, %m4
541 ccmp\\t%<w>2, %3, %k5, %m4
542 ccmn\\t%<w>2, #%n3, %k5, %m4"
543 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
546 (define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>"
547 [(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
548 (if_then_else:CCFP_CCFPE
549 (match_operator 4 "aarch64_comparison_operator"
550 [(match_operand 0 "cc_register" "")
553 (match_operand:GPF 2 "register_operand" "w")
554 (match_operand:GPF 3 "register_operand" "w"))
556 [(match_operand 5 "immediate_operand")]
559 "fccmp<e>\\t%<s>2, %<s>3, %k5, %m4"
560 [(set_attr "type" "fccmp<s>")]
563 (define_insn "@ccmp<CC_ONLY:mode><GPI:mode>_rev"
564 [(set (match_operand:CC_ONLY 1 "cc_register" "")
565 (if_then_else:CC_ONLY
566 (match_operator 4 "aarch64_comparison_operator"
567 [(match_operand 0 "cc_register" "")
570 [(match_operand 5 "immediate_operand")]
573 (match_operand:GPI 2 "register_operand" "r,r,r")
574 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))))]
577 ccmp\\t%<w>2, %<w>3, %k5, %M4
578 ccmp\\t%<w>2, %3, %k5, %M4
579 ccmn\\t%<w>2, #%n3, %k5, %M4"
580 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
583 (define_insn "@ccmp<CCFP_CCFPE:mode><GPF:mode>_rev"
584 [(set (match_operand:CCFP_CCFPE 1 "cc_register" "")
585 (if_then_else:CCFP_CCFPE
586 (match_operator 4 "aarch64_comparison_operator"
587 [(match_operand 0 "cc_register" "")
590 [(match_operand 5 "immediate_operand")]
593 (match_operand:GPF 2 "register_operand" "w")
594 (match_operand:GPF 3 "register_operand" "w"))))]
596 "fccmp<e>\\t%<s>2, %<s>3, %k5, %M4"
597 [(set_attr "type" "fccmp<s>")]
600 ;; Expansion of signed mod by a power of 2 using CSNEG.
601 ;; For x0 % n where n is a power of 2 produce:
603 ;; and x0, x0, #(n - 1)
604 ;; and x1, x1, #(n - 1)
605 ;; csneg x0, x0, x1, mi
607 (define_expand "mod<mode>3"
608 [(match_operand:GPI 0 "register_operand")
609 (match_operand:GPI 1 "register_operand")
610 (match_operand:GPI 2 "const_int_operand")]
613 HOST_WIDE_INT val = INTVAL (operands[2]);
616 || exact_log2 (val) <= 0
617 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
620 rtx mask = GEN_INT (val - 1);
622 /* In the special case of x0 % 2 we can do the even shorter:
628 rtx masked = gen_reg_rtx (<MODE>mode);
629 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
630 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
631 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
632 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
636 rtx neg_op = gen_reg_rtx (<MODE>mode);
637 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
639 /* Extract the condition register and mode. */
640 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
641 rtx cc_reg = SET_DEST (cmp);
642 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
644 rtx masked_pos = gen_reg_rtx (<MODE>mode);
645 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
647 rtx masked_neg = gen_reg_rtx (<MODE>mode);
648 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
650 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
651 masked_neg, masked_pos));
656 (define_insn "condjump"
657 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
658 [(match_operand 1 "cc_register" "") (const_int 0)])
659 (label_ref (match_operand 2 "" ""))
663 /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
664 but the "." is required for SVE conditions. */
665 bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
666 if (get_attr_length (insn) == 8)
667 return aarch64_gen_far_branch (operands, 2, "Lbcond",
668 use_dot_p ? "b.%M0\\t" : "b%M0\\t");
670 return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
672 [(set_attr "type" "branch")
674 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
675 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
678 (set (attr "far_branch")
679 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
680 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
685 ;; For a 24-bit immediate CST we can optimize the compare for equality
686 ;; and branch sequence from:
688 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
692 ;; sub x0, x1, #(CST & 0xfff000)
693 ;; subs x0, x0, #(CST & 0x000fff)
695 (define_insn_and_split "*compare_condjump<GPI:mode>"
696 [(set (pc) (if_then_else (EQL
697 (match_operand:GPI 0 "register_operand" "r")
698 (match_operand:GPI 1 "aarch64_imm24" "n"))
699 (label_ref:P (match_operand 2 "" ""))
701 "!aarch64_move_imm (INTVAL (operands[1]), <GPI:MODE>mode)
702 && !aarch64_plus_operand (operands[1], <GPI:MODE>mode)
703 && !reload_completed"
708 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
709 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
710 rtx tmp = gen_reg_rtx (<GPI:MODE>mode);
711 emit_insn (gen_add<GPI:mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
712 emit_insn (gen_add<GPI:mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
713 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
714 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <GPI:MODE>mode,
716 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
721 (define_expand "casesi"
722 [(match_operand:SI 0 "register_operand") ; Index
723 (match_operand:SI 1 "const_int_operand") ; Lower bound
724 (match_operand:SI 2 "const_int_operand") ; Total range
725 (match_operand:DI 3 "" "") ; Table label
726 (match_operand:DI 4 "" "")] ; Out of range label
729 if (operands[1] != const0_rtx)
731 rtx reg = gen_reg_rtx (SImode);
733 /* Canonical RTL says that if you have:
737 then this should be emitted as:
741 The use of trunc_int_for_mode ensures that the resulting
742 constant can be represented in SImode, this is important
743 for the corner case where operand[1] is INT_MIN. */
745 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
747 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
748 (operands[1], SImode))
749 operands[1] = force_reg (SImode, operands[1]);
750 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
754 if (!aarch64_plus_operand (operands[2], SImode))
755 operands[2] = force_reg (SImode, operands[2]);
756 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
758 operands[0], operands[2], operands[4]));
760 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3]));
762 = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], operands[0]),
764 operands[2] = gen_rtx_MEM (DImode, operands[2]);
765 MEM_READONLY_P (operands[2]) = 1;
766 MEM_NOTRAP_P (operands[2]) = 1;
767 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[3]));
772 (define_expand "casesi_dispatch"
774 [(set (pc) (match_operand:DI 0 ""))
775 (clobber (reg:CC CC_REGNUM))
776 (clobber (match_scratch:DI 2))
777 (clobber (match_scratch:DI 3))
778 (use (label_ref:DI (match_operand 1 "")))])]
781 (define_insn "*casesi_dispatch"
784 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
785 (match_operand:SI 1 "register_operand" "r")]
787 (clobber (reg:CC CC_REGNUM))
788 (clobber (match_scratch:DI 3 "=r"))
789 (clobber (match_scratch:DI 4 "=r"))
790 (use (label_ref:DI (match_operand 2 "" "")))])]
793 return aarch64_output_casesi (operands);
795 [(set_attr "sls_length" "casesi")
796 (set_attr "type" "branch")]
800 [(unspec[(const_int 0)] UNSPEC_NOP)]
803 [(set_attr "type" "no_insn")]
806 (define_insn "prefetch"
807 [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
808 (match_operand:QI 1 "const_int_operand" "")
809 (match_operand:QI 2 "const_int_operand" ""))]
812 const char * pftype[2][4] =
814 {"prfm\\tPLDL1STRM, %0",
815 "prfm\\tPLDL3KEEP, %0",
816 "prfm\\tPLDL2KEEP, %0",
817 "prfm\\tPLDL1KEEP, %0"},
818 {"prfm\\tPSTL1STRM, %0",
819 "prfm\\tPSTL3KEEP, %0",
820 "prfm\\tPSTL2KEEP, %0",
821 "prfm\\tPSTL1KEEP, %0"},
824 int locality = INTVAL (operands[2]);
826 gcc_assert (IN_RANGE (locality, 0, 3));
828 /* PRFM accepts the same addresses as a 64-bit LDR so wrap
829 the address into a DImode MEM so that aarch64_print_operand knows
831 operands[0] = gen_rtx_MEM (DImode, operands[0]);
832 return pftype[INTVAL(operands[1])][locality];
834 [(set_attr "type" "load_4")]
838 [(trap_if (const_int 1) (const_int 8))]
841 [(set_attr "type" "trap")])
843 (define_expand "prologue"
844 [(clobber (const_int 0))]
847 aarch64_expand_prologue ();
852 (define_expand "epilogue"
853 [(clobber (const_int 0))]
856 aarch64_expand_epilogue (false);
861 (define_expand "sibcall_epilogue"
862 [(clobber (const_int 0))]
865 aarch64_expand_epilogue (true);
870 (define_insn "*do_return"
874 const char *ret = NULL;
875 if (aarch64_return_address_signing_enabled ()
877 && !crtl->calls_eh_return)
879 if (aarch64_ra_sign_key == AARCH64_KEY_B)
886 output_asm_insn (ret, operands);
887 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
889 [(set_attr "type" "branch")
890 (set_attr "sls_length" "retbr")]
893 (define_expand "return"
895 "aarch64_use_return_insn_p ()"
899 (define_insn "simple_return"
903 output_asm_insn ("ret", operands);
904 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
906 [(set_attr "type" "branch")
907 (set_attr "sls_length" "retbr")]
910 (define_insn "*cb<optab><mode>1"
911 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
913 (label_ref (match_operand 1 "" ""))
915 "!aarch64_track_speculation"
917 if (get_attr_length (insn) == 8)
918 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
920 return "<cbz>\\t%<w>0, %l1";
922 [(set_attr "type" "branch")
924 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
925 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
928 (set (attr "far_branch")
929 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
930 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
935 (define_insn "*tb<optab><mode>1"
936 [(set (pc) (if_then_else
937 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
940 "aarch64_simd_shift_imm_<mode>" "n"))
942 (label_ref (match_operand 2 "" ""))
944 (clobber (reg:CC CC_REGNUM))]
945 "!aarch64_track_speculation"
947 if (get_attr_length (insn) == 8)
949 if (get_attr_far_branch (insn) == 1)
950 return aarch64_gen_far_branch (operands, 2, "Ltb",
951 "<inv_tb>\\t%<w>0, %1, ");
954 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
955 return "tst\t%<w>0, %1\;<bcond>\t%l2";
959 return "<tbz>\t%<w>0, %1, %l2";
961 [(set_attr "type" "branch")
963 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
964 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
967 (set (attr "far_branch")
968 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
969 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
975 (define_insn "*cb<optab><mode>1"
976 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
978 (label_ref (match_operand 1 "" ""))
980 (clobber (reg:CC CC_REGNUM))]
981 "!aarch64_track_speculation"
983 if (get_attr_length (insn) == 8)
985 if (get_attr_far_branch (insn) == 1)
986 return aarch64_gen_far_branch (operands, 1, "Ltb",
987 "<inv_tb>\\t%<w>0, <sizem1>, ");
991 uint64_t val = ((uint64_t) 1)
992 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
993 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
994 output_asm_insn (buf, operands);
995 return "<bcond>\t%l1";
999 return "<tbz>\t%<w>0, <sizem1>, %l1";
1001 [(set_attr "type" "branch")
1002 (set (attr "length")
1003 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
1004 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
1007 (set (attr "far_branch")
1008 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
1009 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
1014 ;; -------------------------------------------------------------------
1015 ;; Subroutine calls and sibcalls
1016 ;; -------------------------------------------------------------------
1018 (define_expand "call"
1020 [(call (match_operand 0 "memory_operand")
1021 (match_operand 1 "general_operand"))
1022 (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1023 (clobber (reg:DI LR_REGNUM))])]
1027 aarch64_expand_call (NULL_RTX, operands[0], operands[2], false);
1032 (define_insn "*call_insn"
1033 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucr, Usf"))
1034 (match_operand 1 "" ""))
1035 (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1036 (clobber (reg:DI LR_REGNUM))]
1039 * return aarch64_indirect_call_asm (operands[0]);
1041 [(set_attr "type" "call, call")])
1043 (define_expand "call_value"
1045 [(set (match_operand 0 "")
1046 (call (match_operand 1 "memory_operand")
1047 (match_operand 2 "general_operand")))
1048 (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1049 (clobber (reg:DI LR_REGNUM))])]
1053 aarch64_expand_call (operands[0], operands[1], operands[3], false);
1058 (define_insn "*call_value_insn"
1059 [(set (match_operand 0 "" "")
1060 (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "Ucr, Usf"))
1061 (match_operand 2 "" "")))
1062 (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1063 (clobber (reg:DI LR_REGNUM))]
1066 * return aarch64_indirect_call_asm (operands[1]);
1068 [(set_attr "type" "call, call")]
1071 (define_expand "sibcall"
1073 [(call (match_operand 0 "memory_operand")
1074 (match_operand 1 "general_operand"))
1075 (unspec:DI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1079 aarch64_expand_call (NULL_RTX, operands[0], operands[2], true);
1084 (define_expand "sibcall_value"
1086 [(set (match_operand 0 "")
1087 (call (match_operand 1 "memory_operand")
1088 (match_operand 2 "general_operand")))
1089 (unspec:DI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1093 aarch64_expand_call (operands[0], operands[1], operands[3], true);
1098 (define_insn "*sibcall_insn"
1099 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
1100 (match_operand 1 ""))
1101 (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
1103 "SIBLING_CALL_P (insn)"
1105 if (which_alternative == 0)
1107 output_asm_insn ("br\\t%0", operands);
1108 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1112 [(set_attr "type" "branch, branch")
1113 (set_attr "sls_length" "retbr,none")]
1116 (define_insn "*sibcall_value_insn"
1117 [(set (match_operand 0 "")
1119 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
1120 (match_operand 2 "")))
1121 (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
1123 "SIBLING_CALL_P (insn)"
1125 if (which_alternative == 0)
1127 output_asm_insn ("br\\t%1", operands);
1128 return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
1132 [(set_attr "type" "branch, branch")
1133 (set_attr "sls_length" "retbr,none")]
1136 ;; Call subroutine returning any type.
1138 (define_expand "untyped_call"
1139 [(parallel [(call (match_operand 0 "")
1141 (match_operand 1 "")
1142 (match_operand 2 "")])]
1147 /* Untyped calls always use the default ABI. It's only possible to use
1148 ABI variants if we know the type of the target function. */
1149 emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
1151 for (i = 0; i < XVECLEN (operands[2], 0); i++)
1153 rtx set = XVECEXP (operands[2], 0, i);
1154 emit_move_insn (SET_DEST (set), SET_SRC (set));
1157 /* The optimizer does not know that the call sets the function value
1158 registers we stored in the result block. We avoid problems by
1159 claiming that all hard registers are used and clobbered at this
1161 emit_insn (gen_blockage ());
1165 ;; -------------------------------------------------------------------
1167 ;; -------------------------------------------------------------------
1169 (define_expand "mov<mode>"
1170 [(set (match_operand:SHORT 0 "nonimmediate_operand")
1171 (match_operand:SHORT 1 "general_operand"))]
1174 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1175 operands[1] = force_reg (<MODE>mode, operands[1]);
1177 if (GET_CODE (operands[1]) == CONST_POLY_INT)
1179 aarch64_expand_mov_immediate (operands[0], operands[1]);
1185 (define_insn "*mov<mode>_aarch64"
1186 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
1187 (match_operand:SHORT 1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
1188 "(register_operand (operands[0], <MODE>mode)
1189 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
1191 switch (which_alternative)
1194 return "mov\t%w0, %w1";
1196 return "mov\t%w0, %1";
1198 return aarch64_output_scalar_simd_mov_immediate (operands[1],
1201 return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1203 return "ldr<size>\t%w0, %1";
1205 return "ldr\t%<size>0, %1";
1207 return "str<size>\t%w1, %0";
1209 return "str\t%<size>1, %0";
1211 return "umov\t%w0, %1.<v>[0]";
1213 return "dup\t%0.<Vallxd>, %w1";
1215 return "dup\t%<Vetype>0, %1.<v>[0]";
1220 ;; The "mov_imm" type for CNT is just a placeholder.
1221 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
1222 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1223 (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
1226 (define_expand "mov<mode>"
1227 [(set (match_operand:GPI 0 "nonimmediate_operand")
1228 (match_operand:GPI 1 "general_operand"))]
1231 if (MEM_P (operands[0]) && !MEM_VOLATILE_P (operands[0])
1232 && CONST_INT_P (operands[1]) && <MODE>mode == DImode
1233 && aarch64_split_dimode_const_store (operands[0], operands[1]))
1236 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1237 operands[1] = force_reg (<MODE>mode, operands[1]);
1239 /* FIXME: RR we still need to fix up what we are doing with
1240 symbol_refs and other types of constants. */
1241 if (CONSTANT_P (operands[1])
1242 && !CONST_INT_P (operands[1]))
1244 aarch64_expand_mov_immediate (operands[0], operands[1]);
1250 (define_insn_and_split "*movsi_aarch64"
1251 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1252 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1253 "(register_operand (operands[0], SImode)
1254 || aarch64_reg_or_zero (operands[1], SImode))"
1261 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1271 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
1272 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1273 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1276 aarch64_expand_mov_immediate (operands[0], operands[1]);
1279 ;; The "mov_imm" type for CNT is just a placeholder.
1280 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1281 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1282 (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1285 (define_insn_and_split "*movdi_aarch64"
1286 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1287 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1288 "(register_operand (operands[0], DImode)
1289 || aarch64_reg_or_zero (operands[1], DImode))"
1297 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1307 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
1308 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1309 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1312 aarch64_expand_mov_immediate (operands[0], operands[1]);
1315 ;; The "mov_imm" type for CNTD is just a placeholder.
1316 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1317 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1319 (set_attr "arch" "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1322 (define_insn "insv_imm<mode>"
1323 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1325 (match_operand:GPI 1 "const_int_operand" "n"))
1326 (match_operand:GPI 2 "const_int_operand" "n"))]
1327 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1328 && UINTVAL (operands[1]) % 16 == 0"
1329 "movk\\t%<w>0, %X2, lsl %1"
1330 [(set_attr "type" "mov_imm")]
1333 ;; Match MOVK as a normal AND and IOR operation.
1334 (define_insn "aarch64_movk<mode>"
1335 [(set (match_operand:GPI 0 "register_operand" "=r")
1336 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
1337 (match_operand:GPI 2 "const_int_operand"))
1338 (match_operand:GPI 3 "const_int_operand")))]
1339 "aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
1340 rtx_mode_t (operands[3], <MODE>mode)) >= 0"
1342 int shift = aarch64_movk_shift (rtx_mode_t (operands[2], <MODE>mode),
1343 rtx_mode_t (operands[3], <MODE>mode));
1344 operands[2] = gen_int_mode (UINTVAL (operands[3]) >> shift, SImode);
1345 operands[3] = gen_int_mode (shift, SImode);
1346 return "movk\\t%<w>0, #%X2, lsl %3";
1348 [(set_attr "type" "mov_imm")]
1351 (define_expand "movti"
1352 [(set (match_operand:TI 0 "nonimmediate_operand")
1353 (match_operand:TI 1 "general_operand"))]
1356 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1357 operands[1] = force_reg (TImode, operands[1]);
1359 if (GET_CODE (operands[1]) == CONST_POLY_INT)
1361 emit_move_insn (gen_lowpart (DImode, operands[0]),
1362 gen_lowpart (DImode, operands[1]));
1363 emit_move_insn (gen_highpart (DImode, operands[0]), const0_rtx);
1369 (define_insn "*movti_aarch64"
1370 [(set (match_operand:TI 0
1371 "nonimmediate_operand" "= r,w,w, r,w,r,m,m,w,m")
1373 "aarch64_movti_operand" " rUti,Z,r, w,w,m,r,Z,m,w"))]
1374 "(register_operand (operands[0], TImode)
1375 || aarch64_reg_or_zero (operands[1], TImode))"
1381 mov\\t%0.16b, %1.16b
1387 [(set_attr "type" "multiple,neon_move,f_mcr,f_mrc,neon_logic_q, \
1388 load_16,store_16,store_16,\
1390 (set_attr "length" "8,4,8,8,4,4,4,4,4,4")
1391 (set_attr "arch" "*,simd,*,*,simd,*,*,*,fp,fp")]
1394 ;; Split a TImode register-register or register-immediate move into
1395 ;; its component DImode pieces, taking care to handle overlapping
1396 ;; source and dest registers.
1398 [(set (match_operand:TI 0 "register_operand" "")
1399 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1400 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1403 aarch64_split_128bit_move (operands[0], operands[1]);
1407 (define_expand "mov<mode>"
1408 [(set (match_operand:GPF_TF_F16_MOV 0 "nonimmediate_operand")
1409 (match_operand:GPF_TF_F16_MOV 1 "general_operand"))]
1414 aarch64_err_no_fpadvsimd (<MODE>mode);
1415 machine_mode intmode
1416 = int_mode_for_size (GET_MODE_BITSIZE (<MODE>mode), 0).require ();
1417 emit_move_insn (gen_lowpart (intmode, operands[0]),
1418 gen_lowpart (intmode, operands[1]));
1422 if (GET_CODE (operands[0]) == MEM
1423 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1424 && aarch64_float_const_zero_rtx_p (operands[1])))
1425 operands[1] = force_reg (<MODE>mode, operands[1]);
1429 (define_insn "*mov<mode>_aarch64"
1430 [(set (match_operand:HFBF 0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
1431 (match_operand:HFBF 1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1432 "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
1433 || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
1439 mov\\t%0.h[0], %1.h[0]
1441 * return aarch64_output_scalar_simd_mov_immediate (operands[1], HImode);
1447 [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
1448 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1449 (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
1452 (define_insn "*movsf_aarch64"
1453 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1454 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1455 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1456 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1463 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1470 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1471 f_loads,f_stores,load_4,store_4,mov_reg,\
1473 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1476 (define_insn "*movdf_aarch64"
1477 [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1478 (match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1479 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1480 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1487 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1494 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1495 f_loadd,f_stored,load_8,store_8,mov_reg,\
1497 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1501 [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
1502 (match_operand:GPF_HF 1 "general_operand"))]
1503 "can_create_pseudo_p ()
1504 && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
1505 && !aarch64_float_const_representable_p (operands[1])
1506 && aarch64_float_const_rtx_p (operands[1])"
1509 unsigned HOST_WIDE_INT ival;
1510 if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
1513 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1514 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1515 emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
1520 (define_insn "*movtf_aarch64"
1521 [(set (match_operand:TF 0
1522 "nonimmediate_operand" "=w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
1524 "general_operand" " w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1525 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1526 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1528 mov\\t%0.16b, %1.16b
1539 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1540 f_loadd,f_stored,load_16,store_16,store_16")
1541 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1542 (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
1546 [(set (match_operand:TF 0 "register_operand" "")
1547 (match_operand:TF 1 "nonmemory_operand" ""))]
1548 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1551 aarch64_split_128bit_move (operands[0], operands[1]);
1558 ;; 2 is size of copy in bytes
1561 (define_expand "cpymemdi"
1562 [(match_operand:BLK 0 "memory_operand")
1563 (match_operand:BLK 1 "memory_operand")
1564 (match_operand:DI 2 "immediate_operand")
1565 (match_operand:DI 3 "immediate_operand")]
1568 if (aarch64_expand_cpymem (operands))
1576 ;; 2 is size of copy in bytes
1579 (define_expand "setmemdi"
1580 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
1581 (match_operand:QI 2 "nonmemory_operand")) ;; Value
1582 (use (match_operand:DI 1 "immediate_operand")) ;; Length
1583 (match_operand 3 "immediate_operand")] ;; Align
1586 if (aarch64_expand_setmem (operands))
1592 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1593 ;; fairly lax checking on the second memory operation.
1594 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1595 [(set (match_operand:SX 0 "register_operand" "=r,w")
1596 (match_operand:SX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1597 (set (match_operand:SX2 2 "register_operand" "=r,w")
1598 (match_operand:SX2 3 "memory_operand" "m,m"))]
1599 "rtx_equal_p (XEXP (operands[3], 0),
1600 plus_constant (Pmode,
1601 XEXP (operands[1], 0),
1602 GET_MODE_SIZE (<SX:MODE>mode)))"
1605 ldp\\t%s0, %s2, %z1"
1606 [(set_attr "type" "load_8,neon_load1_2reg")
1607 (set_attr "arch" "*,fp")]
1610 ;; Storing different modes that can still be merged
1611 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1612 [(set (match_operand:DX 0 "register_operand" "=r,w")
1613 (match_operand:DX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1614 (set (match_operand:DX2 2 "register_operand" "=r,w")
1615 (match_operand:DX2 3 "memory_operand" "m,m"))]
1616 "rtx_equal_p (XEXP (operands[3], 0),
1617 plus_constant (Pmode,
1618 XEXP (operands[1], 0),
1619 GET_MODE_SIZE (<DX:MODE>mode)))"
1622 ldp\\t%d0, %d2, %z1"
1623 [(set_attr "type" "load_16,neon_load1_2reg")
1624 (set_attr "arch" "*,fp")]
1627 (define_insn "load_pair_dw_tftf"
1628 [(set (match_operand:TF 0 "register_operand" "=w")
1629 (match_operand:TF 1 "aarch64_mem_pair_operand" "Ump"))
1630 (set (match_operand:TF 2 "register_operand" "=w")
1631 (match_operand:TF 3 "memory_operand" "m"))]
1633 && rtx_equal_p (XEXP (operands[3], 0),
1634 plus_constant (Pmode,
1635 XEXP (operands[1], 0),
1636 GET_MODE_SIZE (TFmode)))"
1637 "ldp\\t%q0, %q2, %z1"
1638 [(set_attr "type" "neon_ldp_q")
1639 (set_attr "fp" "yes")]
1642 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1643 ;; fairly lax checking on the second memory operation.
1644 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1645 [(set (match_operand:SX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1646 (match_operand:SX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1647 (set (match_operand:SX2 2 "memory_operand" "=m,m")
1648 (match_operand:SX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1649 "rtx_equal_p (XEXP (operands[2], 0),
1650 plus_constant (Pmode,
1651 XEXP (operands[0], 0),
1652 GET_MODE_SIZE (<SX:MODE>mode)))"
1655 stp\\t%s1, %s3, %z0"
1656 [(set_attr "type" "store_8,neon_store1_2reg")
1657 (set_attr "arch" "*,fp")]
1660 ;; Storing different modes that can still be merged
1661 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1662 [(set (match_operand:DX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1663 (match_operand:DX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1664 (set (match_operand:DX2 2 "memory_operand" "=m,m")
1665 (match_operand:DX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1666 "rtx_equal_p (XEXP (operands[2], 0),
1667 plus_constant (Pmode,
1668 XEXP (operands[0], 0),
1669 GET_MODE_SIZE (<DX:MODE>mode)))"
1672 stp\\t%d1, %d3, %z0"
1673 [(set_attr "type" "store_16,neon_store1_2reg")
1674 (set_attr "arch" "*,fp")]
1677 (define_insn "store_pair_dw_tftf"
1678 [(set (match_operand:TF 0 "aarch64_mem_pair_operand" "=Ump")
1679 (match_operand:TF 1 "register_operand" "w"))
1680 (set (match_operand:TF 2 "memory_operand" "=m")
1681 (match_operand:TF 3 "register_operand" "w"))]
1683 rtx_equal_p (XEXP (operands[2], 0),
1684 plus_constant (Pmode,
1685 XEXP (operands[0], 0),
1686 GET_MODE_SIZE (TFmode)))"
1687 "stp\\t%q1, %q3, %z0"
1688 [(set_attr "type" "neon_stp_q")
1689 (set_attr "fp" "yes")]
1692 ;; Load pair with post-index writeback. This is primarily used in function
1694 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1696 [(set (match_operand:P 0 "register_operand" "=k")
1697 (plus:P (match_operand:P 1 "register_operand" "0")
1698 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1699 (set (match_operand:GPI 2 "register_operand" "=r")
1700 (mem:GPI (match_dup 1)))
1701 (set (match_operand:GPI 3 "register_operand" "=r")
1702 (mem:GPI (plus:P (match_dup 1)
1703 (match_operand:P 5 "const_int_operand" "n"))))])]
1704 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1705 "ldp\\t%<GPI:w>2, %<GPI:w>3, [%1], %4"
1706 [(set_attr "type" "load_<GPI:ldpstp_sz>")]
1709 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1711 [(set (match_operand:P 0 "register_operand" "=k")
1712 (plus:P (match_operand:P 1 "register_operand" "0")
1713 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1714 (set (match_operand:GPF 2 "register_operand" "=w")
1715 (mem:GPF (match_dup 1)))
1716 (set (match_operand:GPF 3 "register_operand" "=w")
1717 (mem:GPF (plus:P (match_dup 1)
1718 (match_operand:P 5 "const_int_operand" "n"))))])]
1719 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1720 "ldp\\t%<GPF:w>2, %<GPF:w>3, [%1], %4"
1721 [(set_attr "type" "neon_load1_2reg")]
1724 (define_insn "loadwb_pair<TX:mode>_<P:mode>"
1726 [(set (match_operand:P 0 "register_operand" "=k")
1727 (plus:P (match_operand:P 1 "register_operand" "0")
1728 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1729 (set (match_operand:TX 2 "register_operand" "=w")
1730 (mem:TX (match_dup 1)))
1731 (set (match_operand:TX 3 "register_operand" "=w")
1732 (mem:TX (plus:P (match_dup 1)
1733 (match_operand:P 5 "const_int_operand" "n"))))])]
1734 "TARGET_SIMD && INTVAL (operands[5]) == GET_MODE_SIZE (<TX:MODE>mode)"
1735 "ldp\\t%q2, %q3, [%1], %4"
1736 [(set_attr "type" "neon_ldp_q")]
1739 ;; Store pair with pre-index writeback. This is primarily used in function
1741 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1743 [(set (match_operand:P 0 "register_operand" "=&k")
1744 (plus:P (match_operand:P 1 "register_operand" "0")
1745 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1746 (set (mem:GPI (plus:P (match_dup 0)
1748 (match_operand:GPI 2 "register_operand" "r"))
1749 (set (mem:GPI (plus:P (match_dup 0)
1750 (match_operand:P 5 "const_int_operand" "n")))
1751 (match_operand:GPI 3 "register_operand" "r"))])]
1752 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1753 "stp\\t%<GPI:w>2, %<GPI:w>3, [%0, %4]!"
1754 [(set_attr "type" "store_<GPI:ldpstp_sz>")]
1757 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1759 [(set (match_operand:P 0 "register_operand" "=&k")
1760 (plus:P (match_operand:P 1 "register_operand" "0")
1761 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1762 (set (mem:GPF (plus:P (match_dup 0)
1764 (match_operand:GPF 2 "register_operand" "w"))
1765 (set (mem:GPF (plus:P (match_dup 0)
1766 (match_operand:P 5 "const_int_operand" "n")))
1767 (match_operand:GPF 3 "register_operand" "w"))])]
1768 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1769 "stp\\t%<GPF:w>2, %<GPF:w>3, [%0, %4]!"
1770 [(set_attr "type" "neon_store1_2reg<q>")]
1773 (define_insn "storewb_pair<TX:mode>_<P:mode>"
1775 [(set (match_operand:P 0 "register_operand" "=&k")
1776 (plus:P (match_operand:P 1 "register_operand" "0")
1777 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1778 (set (mem:TX (plus:P (match_dup 0)
1780 (match_operand:TX 2 "register_operand" "w"))
1781 (set (mem:TX (plus:P (match_dup 0)
1782 (match_operand:P 5 "const_int_operand" "n")))
1783 (match_operand:TX 3 "register_operand" "w"))])]
1785 && INTVAL (operands[5])
1786 == INTVAL (operands[4]) + GET_MODE_SIZE (<TX:MODE>mode)"
1787 "stp\\t%q2, %q3, [%0, %4]!"
1788 [(set_attr "type" "neon_stp_q")]
1791 ;; -------------------------------------------------------------------
1792 ;; Sign/Zero extension
1793 ;; -------------------------------------------------------------------
1795 (define_expand "<optab>sidi2"
1796 [(set (match_operand:DI 0 "register_operand")
1797 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1801 (define_insn "*extendsidi2_aarch64"
1802 [(set (match_operand:DI 0 "register_operand" "=r,r")
1803 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1808 [(set_attr "type" "extend,load_4")]
1811 (define_insn "*load_pair_extendsidi2_aarch64"
1812 [(set (match_operand:DI 0 "register_operand" "=r")
1813 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1814 (set (match_operand:DI 2 "register_operand" "=r")
1815 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1816 "rtx_equal_p (XEXP (operands[3], 0),
1817 plus_constant (Pmode,
1818 XEXP (operands[1], 0),
1819 GET_MODE_SIZE (SImode)))"
1820 "ldpsw\\t%0, %2, %z1"
1821 [(set_attr "type" "load_8")]
1824 (define_insn "*zero_extendsidi2_aarch64"
1825 [(set (match_operand:DI 0 "register_operand" "=r,r,w,w,r,w")
1826 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,r,m,w,w")))]
1835 [(set_attr "type" "mov_reg,load_4,f_mcr,f_loads,f_mrc,fmov")
1836 (set_attr "arch" "*,*,fp,fp,fp,fp")]
1839 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1840 [(set (match_operand:DI 0 "register_operand" "=r,w")
1841 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump")))
1842 (set (match_operand:DI 2 "register_operand" "=r,w")
1843 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m,m")))]
1844 "rtx_equal_p (XEXP (operands[3], 0),
1845 plus_constant (Pmode,
1846 XEXP (operands[1], 0),
1847 GET_MODE_SIZE (SImode)))"
1851 [(set_attr "type" "load_8,neon_load1_2reg")
1852 (set_attr "arch" "*,fp")]
1855 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1856 [(set (match_operand:GPI 0 "register_operand")
1857 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1861 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1862 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1863 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1866 sxt<SHORT:size>\t%<GPI:w>0, %w1
1867 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1868 [(set_attr "type" "extend,load_4")]
1871 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1872 [(set (match_operand:GPI 0 "register_operand" "=r,r,w")
1873 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1876 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1877 ldr<SHORT:size>\t%w0, %1
1878 ldr\t%<SHORT:size>0, %1"
1879 [(set_attr "type" "logic_imm,load_4,f_loads")
1880 (set_attr "arch" "*,*,fp")]
1883 (define_expand "<optab>qihi2"
1884 [(set (match_operand:HI 0 "register_operand")
1885 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1889 (define_insn "*extendqihi2_aarch64"
1890 [(set (match_operand:HI 0 "register_operand" "=r,r")
1891 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1896 [(set_attr "type" "extend,load_4")]
1899 (define_insn "*zero_extendqihi2_aarch64"
1900 [(set (match_operand:HI 0 "register_operand" "=r,r")
1901 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1906 [(set_attr "type" "logic_imm,load_4")]
1909 ;; -------------------------------------------------------------------
1910 ;; Simple arithmetic
1911 ;; -------------------------------------------------------------------
1913 (define_expand "add<mode>3"
1915 (match_operand:GPI 0 "register_operand")
1916 (plus:GPI (match_operand:GPI 1 "register_operand")
1917 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand")))]
1920 /* If operands[1] is a subreg extract the inner RTX. */
1921 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1923 /* If the constant is too large for a single instruction and isn't frame
1924 based, split off the immediate so it is available for CSE. */
1925 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1926 && !(TARGET_SVE && aarch64_sve_plus_immediate (operands[2], <MODE>mode))
1927 && can_create_pseudo_p ()
1929 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1930 operands[2] = force_reg (<MODE>mode, operands[2]);
1931 /* Expand polynomial additions now if the destination is the stack
1932 pointer, since we don't want to use that as a temporary. */
1933 else if (operands[0] == stack_pointer_rtx
1934 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode))
1936 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
1937 operands[2], NULL_RTX, NULL_RTX);
1942 (define_insn "*add<mode>3_aarch64"
1944 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,r,rk")
1946 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,0,rk")
1947 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uai,Uav")))]
1950 add\\t%<w>0, %<w>1, %2
1951 add\\t%<w>0, %<w>1, %<w>2
1952 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1953 sub\\t%<w>0, %<w>1, #%n2
1955 * return aarch64_output_sve_scalar_inc_dec (operands[2]);
1956 * return aarch64_output_sve_addvl_addpl (operands[2]);"
1957 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
1958 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm,alu_imm")
1959 (set_attr "arch" "*,*,simd,*,*,sve,sve")]
1962 ;; zero_extend version of above
1963 (define_insn "*addsi3_aarch64_uxtw"
1965 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1967 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1968 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1973 sub\\t%w0, %w1, #%n2
1975 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1978 ;; If there's a free register, and we can load the constant with a
1979 ;; single instruction, do so. This has a chance to improve scheduling.
1981 [(match_scratch:GPI 3 "r")
1982 (set (match_operand:GPI 0 "register_operand")
1984 (match_operand:GPI 1 "register_operand")
1985 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1986 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1987 [(set (match_dup 3) (match_dup 2))
1988 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1992 [(match_scratch:SI 3 "r")
1993 (set (match_operand:DI 0 "register_operand")
1996 (match_operand:SI 1 "register_operand")
1997 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1998 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1999 [(set (match_dup 3) (match_dup 2))
2000 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
2003 ;; After peephole2 has had a chance to run, split any remaining long
2004 ;; additions into two add immediates.
2006 [(set (match_operand:GPI 0 "register_operand")
2008 (match_operand:GPI 1 "register_operand")
2009 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
2010 "epilogue_completed"
2011 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
2012 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
2014 HOST_WIDE_INT i = INTVAL (operands[2]);
2015 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
2016 operands[3] = GEN_INT (i - s);
2017 operands[4] = GEN_INT (s);
2021 ;; Match addition of polynomial offsets that require one temporary, for which
2022 ;; we can use the early-clobbered destination register. This is a separate
2023 ;; pattern so that the early clobber doesn't affect register allocation
2024 ;; for other forms of addition. However, we still need to provide an
2025 ;; all-register alternative, in case the offset goes out of range after
2026 ;; elimination. For completeness we might as well provide all GPR-based
2027 ;; alternatives from the main pattern.
2029 ;; We don't have a pattern for additions requiring two temporaries since at
2030 ;; present LRA doesn't allow new scratches to be added during elimination.
2031 ;; Such offsets should be rare anyway.
2033 ;; ??? But if we added LRA support for new scratches, much of the ugliness
2034 ;; here would go away. We could just handle all polynomial constants in
2036 (define_insn_and_split "*add<mode>3_poly_1"
2038 (match_operand:GPI 0 "register_operand" "=r,r,r,r,r,r,&r")
2040 (match_operand:GPI 1 "register_operand" "%rk,rk,rk,rk,rk,0,rk")
2041 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uai,Uat")))]
2042 "TARGET_SVE && operands[0] != stack_pointer_rtx"
2044 add\\t%<w>0, %<w>1, %2
2045 add\\t%<w>0, %<w>1, %<w>2
2046 sub\\t%<w>0, %<w>1, #%n2
2048 * return aarch64_output_sve_scalar_inc_dec (operands[2]);
2049 * return aarch64_output_sve_addvl_addpl (operands[2]);
2051 "&& epilogue_completed
2052 && !reg_overlap_mentioned_p (operands[0], operands[1])
2053 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)"
2056 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
2057 operands[2], operands[0], NULL_RTX);
2060 ;; The "alu_imm" types for INC/DEC and ADDVL/ADDPL are just placeholders.
2061 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,alu_imm,multiple")]
2065 [(set (match_operand:DI 0 "register_operand")
2068 (match_operand:SI 1 "register_operand")
2069 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
2070 "epilogue_completed"
2071 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
2072 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
2074 HOST_WIDE_INT i = INTVAL (operands[2]);
2075 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
2076 operands[3] = GEN_INT (i - s);
2077 operands[4] = GEN_INT (s);
2078 operands[5] = gen_lowpart (SImode, operands[0]);
2082 (define_expand "addv<mode>4"
2083 [(match_operand:GPI 0 "register_operand")
2084 (match_operand:GPI 1 "register_operand")
2085 (match_operand:GPI 2 "aarch64_plus_operand")
2086 (label_ref (match_operand 3 "" ""))]
2089 if (CONST_INT_P (operands[2]))
2090 emit_insn (gen_add<mode>3_compareV_imm (operands[0], operands[1],
2093 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
2094 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2099 (define_expand "uaddv<mode>4"
2100 [(match_operand:GPI 0 "register_operand")
2101 (match_operand:GPI 1 "register_operand")
2102 (match_operand:GPI 2 "register_operand")
2103 (label_ref (match_operand 3 "" ""))]
2106 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
2107 aarch64_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
2112 (define_expand "addti3"
2113 [(set (match_operand:TI 0 "register_operand")
2114 (plus:TI (match_operand:TI 1 "register_operand")
2115 (match_operand:TI 2 "aarch64_reg_or_imm")))]
2118 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2120 aarch64_addti_scratch_regs (operands[1], operands[2],
2121 &low_dest, &op1_low, &op2_low,
2122 &high_dest, &op1_high, &op2_high);
2124 if (op2_low == const0_rtx)
2127 if (!aarch64_pluslong_operand (op2_high, DImode))
2128 op2_high = force_reg (DImode, op2_high);
2129 emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
2133 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2134 force_reg (DImode, op2_low)));
2135 emit_insn (gen_adddi3_carryin (high_dest, op1_high,
2136 force_reg (DImode, op2_high)));
2139 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2140 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2145 (define_expand "addvti4"
2146 [(match_operand:TI 0 "register_operand")
2147 (match_operand:TI 1 "register_operand")
2148 (match_operand:TI 2 "aarch64_reg_or_imm")
2149 (label_ref (match_operand 3 "" ""))]
2152 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2154 aarch64_addti_scratch_regs (operands[1], operands[2],
2155 &low_dest, &op1_low, &op2_low,
2156 &high_dest, &op1_high, &op2_high);
2158 if (op2_low == const0_rtx)
2161 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
2162 force_reg (DImode, op2_high)));
2166 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2167 force_reg (DImode, op2_low)));
2168 emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
2169 force_reg (DImode, op2_high)));
2172 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2173 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2175 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2179 (define_expand "uaddvti4"
2180 [(match_operand:TI 0 "register_operand")
2181 (match_operand:TI 1 "register_operand")
2182 (match_operand:TI 2 "aarch64_reg_or_imm")
2183 (label_ref (match_operand 3 "" ""))]
2186 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2188 aarch64_addti_scratch_regs (operands[1], operands[2],
2189 &low_dest, &op1_low, &op2_low,
2190 &high_dest, &op1_high, &op2_high);
2192 if (op2_low == const0_rtx)
2195 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
2196 force_reg (DImode, op2_high)));
2200 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2201 force_reg (DImode, op2_low)));
2202 emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
2203 force_reg (DImode, op2_high)));
2206 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2207 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2209 aarch64_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[3]);
2213 (define_insn "add<mode>3_compare0"
2214 [(set (reg:CC_NZ CC_REGNUM)
2216 (plus:GPI (match_operand:GPI 1 "register_operand" "%rk,rk,rk")
2217 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
2219 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
2220 (plus:GPI (match_dup 1) (match_dup 2)))]
2223 adds\\t%<w>0, %<w>1, %<w>2
2224 adds\\t%<w>0, %<w>1, %2
2225 subs\\t%<w>0, %<w>1, #%n2"
2226 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2229 ;; zero_extend version of above
2230 (define_insn "*addsi3_compare0_uxtw"
2231 [(set (reg:CC_NZ CC_REGNUM)
2233 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk")
2234 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
2236 (set (match_operand:DI 0 "register_operand" "=r,r,r")
2237 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
2240 adds\\t%w0, %w1, %w2
2242 subs\\t%w0, %w1, #%n2"
2243 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2246 (define_insn "*add<mode>3_compareC_cconly"
2247 [(set (reg:CC_C CC_REGNUM)
2250 (match_operand:GPI 0 "register_operand" "r,r,r")
2251 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2258 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2261 (define_insn "add<mode>3_compareC"
2262 [(set (reg:CC_C CC_REGNUM)
2265 (match_operand:GPI 1 "register_operand" "rk,rk,rk")
2266 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
2268 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
2269 (plus:GPI (match_dup 1) (match_dup 2)))]
2272 adds\\t%<w>0, %<w>1, %<w>2
2273 adds\\t%<w>0, %<w>1, %2
2274 subs\\t%<w>0, %<w>1, #%n2"
2275 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2278 (define_insn "*add<mode>3_compareV_cconly_imm"
2279 [(set (reg:CC_V CC_REGNUM)
2282 (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
2283 (match_operand:<DWI> 1 "const_scalar_int_operand" ""))
2287 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))]
2288 "INTVAL (operands[1]) == INTVAL (operands[2])"
2292 [(set_attr "type" "alus_imm")]
2295 (define_insn "*add<mode>3_compareV_cconly"
2296 [(set (reg:CC_V CC_REGNUM)
2299 (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
2300 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2301 (sign_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
2303 "cmn\\t%<w>0, %<w>1"
2304 [(set_attr "type" "alus_sreg")]
2307 (define_insn "add<mode>3_compareV_imm"
2308 [(set (reg:CC_V CC_REGNUM)
2312 (match_operand:GPI 1 "register_operand" "rk,rk"))
2313 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J"))
2315 (plus:GPI (match_dup 1) (match_dup 2)))))
2316 (set (match_operand:GPI 0 "register_operand" "=r,r")
2317 (plus:GPI (match_dup 1) (match_dup 2)))]
2320 adds\\t%<w>0, %<w>1, %<w>2
2321 subs\\t%<w>0, %<w>1, #%n2"
2322 [(set_attr "type" "alus_imm,alus_imm")]
2325 (define_insn "add<mode>3_compareV"
2326 [(set (reg:CC_V CC_REGNUM)
2329 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "rk"))
2330 (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2331 (sign_extend:<DWI> (plus:GPI (match_dup 1) (match_dup 2)))))
2332 (set (match_operand:GPI 0 "register_operand" "=r")
2333 (plus:GPI (match_dup 1) (match_dup 2)))]
2335 "adds\\t%<w>0, %<w>1, %<w>2"
2336 [(set_attr "type" "alus_sreg")]
2339 (define_insn "*adds_shift_imm_<mode>"
2340 [(set (reg:CC_NZ CC_REGNUM)
2342 (plus:GPI (ASHIFT:GPI
2343 (match_operand:GPI 1 "register_operand" "r")
2344 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2345 (match_operand:GPI 3 "register_operand" "r"))
2347 (set (match_operand:GPI 0 "register_operand" "=r")
2348 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
2351 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2352 [(set_attr "type" "alus_shift_imm")]
2355 (define_insn "*subs_shift_imm_<mode>"
2356 [(set (reg:CC_NZ CC_REGNUM)
2358 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2360 (match_operand:GPI 2 "register_operand" "r")
2361 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
2363 (set (match_operand:GPI 0 "register_operand" "=r")
2364 (minus:GPI (match_dup 1)
2365 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
2367 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
2368 [(set_attr "type" "alus_shift_imm")]
2371 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2372 [(set (reg:CC_NZ CC_REGNUM)
2375 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2376 (match_operand:GPI 2 "register_operand" "rk"))
2378 (set (match_operand:GPI 0 "register_operand" "=r")
2379 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
2381 "adds\\t%<GPI:w>0, %<GPI:w>2, %w1, <su>xt<ALLX:size>"
2382 [(set_attr "type" "alus_ext")]
2385 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2386 [(set (reg:CC_NZ CC_REGNUM)
2388 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2390 (match_operand:ALLX 2 "register_operand" "r")))
2392 (set (match_operand:GPI 0 "register_operand" "=r")
2393 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
2395 "subs\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size>"
2396 [(set_attr "type" "alus_ext")]
2399 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2400 [(set (reg:CC_NZ CC_REGNUM)
2402 (plus:GPI (ashift:GPI
2404 (match_operand:ALLX 1 "register_operand" "r"))
2405 (match_operand 2 "aarch64_imm3" "Ui3"))
2406 (match_operand:GPI 3 "register_operand" "rk"))
2408 (set (match_operand:GPI 0 "register_operand" "=rk")
2409 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
2413 "adds\\t%<GPI:w>0, %<GPI:w>3, %w1, <su>xt<ALLX:size> %2"
2414 [(set_attr "type" "alus_ext")]
2417 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2418 [(set (reg:CC_NZ CC_REGNUM)
2420 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2423 (match_operand:ALLX 2 "register_operand" "r"))
2424 (match_operand 3 "aarch64_imm3" "Ui3")))
2426 (set (match_operand:GPI 0 "register_operand" "=rk")
2427 (minus:GPI (match_dup 1)
2428 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
2431 "subs\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size> %3"
2432 [(set_attr "type" "alus_ext")]
2435 (define_insn "*add<mode>3nr_compare0"
2436 [(set (reg:CC_NZ CC_REGNUM)
2438 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2439 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2446 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2449 (define_insn "aarch64_sub<mode>_compare0"
2450 [(set (reg:CC_NZ CC_REGNUM)
2452 (minus:GPI (match_operand:GPI 0 "register_operand" "r")
2453 (match_operand:GPI 1 "aarch64_plus_operand" "r"))
2456 "cmp\\t%<w>0, %<w>1"
2457 [(set_attr "type" "alus_sreg")]
2460 (define_insn "*compare_neg<mode>"
2461 [(set (reg:CC_Z CC_REGNUM)
2463 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2464 (match_operand:GPI 1 "register_operand" "r")))]
2466 "cmn\\t%<w>1, %<w>0"
2467 [(set_attr "type" "alus_sreg")]
2470 (define_insn "*add_<shift>_<mode>"
2471 [(set (match_operand:GPI 0 "register_operand" "=r")
2472 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2473 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2474 (match_operand:GPI 3 "register_operand" "r")))]
2476 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2477 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
2480 ;; zero_extend version of above
2481 (define_insn "*add_<shift>_si_uxtw"
2482 [(set (match_operand:DI 0 "register_operand" "=r")
2484 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2485 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2486 (match_operand:SI 3 "register_operand" "r"))))]
2488 "add\\t%w0, %w3, %w1, <shift> %2"
2489 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
2492 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2493 [(set (match_operand:GPI 0 "register_operand" "=rk")
2494 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2495 (match_operand:GPI 2 "register_operand" "r")))]
2497 "add\\t%<GPI:w>0, %<GPI:w>2, %w1, <su>xt<ALLX:size>"
2498 [(set_attr "type" "alu_ext")]
2501 ;; zero_extend version of above
2502 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2503 [(set (match_operand:DI 0 "register_operand" "=rk")
2505 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2506 (match_operand:GPI 2 "register_operand" "r"))))]
2508 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2509 [(set_attr "type" "alu_ext")]
2512 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2513 [(set (match_operand:GPI 0 "register_operand" "=rk")
2514 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2515 (match_operand:ALLX 1 "register_operand" "r"))
2516 (match_operand 2 "aarch64_imm3" "Ui3"))
2517 (match_operand:GPI 3 "register_operand" "r")))]
2519 "add\\t%<GPI:w>0, %<GPI:w>3, %w1, <su>xt<ALLX:size> %2"
2520 [(set_attr "type" "alu_ext")]
2523 ;; zero_extend version of above
2524 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2525 [(set (match_operand:DI 0 "register_operand" "=rk")
2527 (plus:SI (ashift:SI (ANY_EXTEND:SI
2528 (match_operand:SHORT 1 "register_operand" "r"))
2529 (match_operand 2 "aarch64_imm3" "Ui3"))
2530 (match_operand:SI 3 "register_operand" "r"))))]
2532 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2533 [(set_attr "type" "alu_ext")]
2536 (define_expand "add<mode>3_carryin"
2537 [(set (match_operand:GPI 0 "register_operand")
2540 (ltu:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2541 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2542 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2547 ;; Note that add with carry with two zero inputs is matched by cset,
2548 ;; and that add with carry with one zero input is matched by cinc.
2550 (define_insn "*add<mode>3_carryin"
2551 [(set (match_operand:GPI 0 "register_operand" "=r")
2554 (match_operand:GPI 3 "aarch64_carry_operation" "")
2555 (match_operand:GPI 1 "register_operand" "r"))
2556 (match_operand:GPI 2 "register_operand" "r")))]
2558 "adc\\t%<w>0, %<w>1, %<w>2"
2559 [(set_attr "type" "adc_reg")]
2562 ;; zero_extend version of above
2563 (define_insn "*addsi3_carryin_uxtw"
2564 [(set (match_operand:DI 0 "register_operand" "=r")
2568 (match_operand:SI 3 "aarch64_carry_operation" "")
2569 (match_operand:SI 1 "register_operand" "r"))
2570 (match_operand:SI 2 "register_operand" "r"))))]
2572 "adc\\t%w0, %w1, %w2"
2573 [(set_attr "type" "adc_reg")]
2576 (define_expand "add<mode>3_carryinC"
2584 (match_operand:GPI 1 "register_operand")))
2586 (match_operand:GPI 2 "register_operand")))
2588 (set (match_operand:GPI 0 "register_operand")
2590 (plus:GPI (match_dup 5) (match_dup 1))
2594 operands[3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
2595 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2596 operands[4] = gen_rtx_LTU (<DWI>mode, ccin, const0_rtx);
2597 operands[5] = gen_rtx_LTU (<MODE>mode, ccin, const0_rtx);
2598 operands[6] = immed_wide_int_const (wi::shwi (1, <DWI>mode)
2599 << GET_MODE_BITSIZE (<MODE>mode),
2603 (define_insn "*add<mode>3_carryinC_zero"
2604 [(set (reg:CC_ADC CC_REGNUM)
2607 (match_operand:<DWI> 2 "aarch64_carry_operation" "")
2608 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2609 (match_operand 4 "const_scalar_int_operand" "")))
2610 (set (match_operand:GPI 0 "register_operand" "=r")
2611 (plus:GPI (match_operand:GPI 3 "aarch64_carry_operation" "")
2613 "rtx_mode_t (operands[4], <DWI>mode)
2614 == (wi::shwi (1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2615 "adcs\\t%<w>0, %<w>1, <w>zr"
2616 [(set_attr "type" "adc_reg")]
2619 (define_insn "*add<mode>3_carryinC"
2620 [(set (reg:CC_ADC CC_REGNUM)
2624 (match_operand:<DWI> 3 "aarch64_carry_operation" "")
2625 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2626 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2627 (match_operand 5 "const_scalar_int_operand" "")))
2628 (set (match_operand:GPI 0 "register_operand" "=r")
2630 (plus:GPI (match_operand:GPI 4 "aarch64_carry_operation" "")
2633 "rtx_mode_t (operands[5], <DWI>mode)
2634 == (wi::shwi (1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2635 "adcs\\t%<w>0, %<w>1, %<w>2"
2636 [(set_attr "type" "adc_reg")]
2639 (define_expand "add<mode>3_carryinV"
2641 [(set (reg:CC_V CC_REGNUM)
2647 (match_operand:GPI 1 "register_operand")))
2649 (match_operand:GPI 2 "register_operand")))
2652 (plus:GPI (match_dup 4) (match_dup 1))
2654 (set (match_operand:GPI 0 "register_operand")
2656 (plus:GPI (match_dup 4) (match_dup 1))
2660 rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2661 operands[3] = gen_rtx_LTU (<DWI>mode, cc, const0_rtx);
2662 operands[4] = gen_rtx_LTU (<MODE>mode, cc, const0_rtx);
2665 (define_insn "*add<mode>3_carryinV_zero"
2666 [(set (reg:CC_V CC_REGNUM)
2669 (match_operand:<DWI> 2 "aarch64_carry_operation" "")
2670 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2673 (match_operand:GPI 3 "aarch64_carry_operation" "")
2675 (set (match_operand:GPI 0 "register_operand" "=r")
2676 (plus:GPI (match_dup 3) (match_dup 1)))]
2678 "adcs\\t%<w>0, %<w>1, <w>zr"
2679 [(set_attr "type" "adc_reg")]
2682 (define_insn "*add<mode>3_carryinV"
2683 [(set (reg:CC_V CC_REGNUM)
2687 (match_operand:<DWI> 3 "aarch64_carry_operation" "")
2688 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2689 (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2693 (match_operand:GPI 4 "aarch64_carry_operation" "")
2696 (set (match_operand:GPI 0 "register_operand" "=r")
2698 (plus:GPI (match_dup 4) (match_dup 1))
2701 "adcs\\t%<w>0, %<w>1, %<w>2"
2702 [(set_attr "type" "adc_reg")]
2705 (define_insn "*add_uxt<mode>_shift2"
2706 [(set (match_operand:GPI 0 "register_operand" "=rk")
2708 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2709 (match_operand 2 "aarch64_imm3" "Ui3"))
2710 (match_operand 3 "const_int_operand" "n"))
2711 (match_operand:GPI 4 "register_operand" "r")))]
2712 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2714 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2715 INTVAL (operands[3])));
2716 return \"add\t%<w>0, %<w>4, %w1, uxt%e3 %2\";"
2717 [(set_attr "type" "alu_ext")]
2720 ;; zero_extend version of above
2721 (define_insn "*add_uxtsi_shift2_uxtw"
2722 [(set (match_operand:DI 0 "register_operand" "=rk")
2725 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2726 (match_operand 2 "aarch64_imm3" "Ui3"))
2727 (match_operand 3 "const_int_operand" "n"))
2728 (match_operand:SI 4 "register_operand" "r"))))]
2729 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2731 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2732 INTVAL (operands[3])));
2733 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2734 [(set_attr "type" "alu_ext")]
2737 (define_insn "subsi3"
2738 [(set (match_operand:SI 0 "register_operand" "=rk")
2739 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2740 (match_operand:SI 2 "register_operand" "r")))]
2742 "sub\\t%w0, %w1, %w2"
2743 [(set_attr "type" "alu_sreg")]
2746 ;; zero_extend version of above
2747 (define_insn "*subsi3_uxtw"
2748 [(set (match_operand:DI 0 "register_operand" "=rk")
2750 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2751 (match_operand:SI 2 "register_operand" "r"))))]
2753 "sub\\t%w0, %w1, %w2"
2754 [(set_attr "type" "alu_sreg")]
2757 (define_insn "subdi3"
2758 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2759 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2760 (match_operand:DI 2 "register_operand" "r,w")))]
2764 sub\\t%d0, %d1, %d2"
2765 [(set_attr "type" "alu_sreg, neon_sub")
2766 (set_attr "arch" "*,simd")]
2769 (define_expand "subv<GPI:mode>4"
2770 [(match_operand:GPI 0 "register_operand")
2771 (match_operand:GPI 1 "register_operand")
2772 (match_operand:GPI 2 "aarch64_plus_operand")
2773 (label_ref (match_operand 3 "" ""))]
2776 if (CONST_INT_P (operands[2]))
2777 emit_insn (gen_subv<mode>_imm (operands[0], operands[1], operands[2]));
2779 emit_insn (gen_subv<mode>_insn (operands[0], operands[1], operands[2]));
2780 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2785 (define_insn "subv<GPI:mode>_insn"
2786 [(set (reg:CC_V CC_REGNUM)
2790 (match_operand:GPI 1 "register_operand" "rk")
2791 (match_operand:GPI 2 "register_operand" "r")))
2792 (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
2793 (sign_extend:<DWI> (match_dup 2)))))
2794 (set (match_operand:GPI 0 "register_operand" "=r")
2795 (minus:GPI (match_dup 1) (match_dup 2)))]
2797 "subs\\t%<w>0, %<w>1, %<w>2"
2798 [(set_attr "type" "alus_sreg")]
2801 (define_insn "subv<GPI:mode>_imm"
2802 [(set (reg:CC_V CC_REGNUM)
2806 (match_operand:GPI 1 "register_operand" "rk,rk")
2807 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))
2808 (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
2810 (set (match_operand:GPI 0 "register_operand" "=r,r")
2811 (minus:GPI (match_dup 1) (match_dup 2)))]
2814 subs\\t%<w>0, %<w>1, %2
2815 adds\\t%<w>0, %<w>1, #%n2"
2816 [(set_attr "type" "alus_sreg")]
2819 (define_expand "negv<GPI:mode>3"
2820 [(match_operand:GPI 0 "register_operand")
2821 (match_operand:GPI 1 "register_operand")
2822 (label_ref (match_operand 2 "" ""))]
2825 emit_insn (gen_negv<mode>_insn (operands[0], operands[1]));
2826 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
2832 (define_insn "negv<GPI:mode>_insn"
2833 [(set (reg:CC_V CC_REGNUM)
2836 (neg:GPI (match_operand:GPI 1 "register_operand" "r")))
2837 (neg:<DWI> (sign_extend:<DWI> (match_dup 1)))))
2838 (set (match_operand:GPI 0 "register_operand" "=r")
2839 (neg:GPI (match_dup 1)))]
2841 "negs\\t%<w>0, %<w>1"
2842 [(set_attr "type" "alus_sreg")]
2845 (define_insn "negv<GPI:mode>_cmp_only"
2846 [(set (reg:CC_V CC_REGNUM)
2849 (neg:GPI (match_operand:GPI 0 "register_operand" "r")))
2850 (neg:<DWI> (sign_extend:<DWI> (match_dup 0)))))]
2852 "negs\\t%<w>zr, %<w>0"
2853 [(set_attr "type" "alus_sreg")]
2856 (define_insn "*cmpv<GPI:mode>_insn"
2857 [(set (reg:CC_V CC_REGNUM)
2860 (minus:GPI (match_operand:GPI 0 "register_operand" "r,r,r")
2861 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))
2862 (minus:<DWI> (sign_extend:<DWI> (match_dup 0))
2863 (sign_extend:<DWI> (match_dup 1)))))]
2869 [(set_attr "type" "alus_sreg")]
2872 (define_expand "usubv<mode>4"
2873 [(match_operand:GPI 0 "register_operand")
2874 (match_operand:GPI 1 "aarch64_reg_or_zero")
2875 (match_operand:GPI 2 "aarch64_reg_or_zero")
2876 (label_ref (match_operand 3 "" ""))]
2879 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
2880 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
2885 (define_expand "subti3"
2886 [(set (match_operand:TI 0 "register_operand")
2887 (minus:TI (match_operand:TI 1 "aarch64_reg_or_zero")
2888 (match_operand:TI 2 "register_operand")))]
2891 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2893 aarch64_subvti_scratch_regs (operands[1], operands[2],
2894 &low_dest, &op1_low, &op2_low,
2895 &high_dest, &op1_high, &op2_high);
2897 emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
2898 emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
2900 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2901 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2905 (define_expand "subvti4"
2906 [(match_operand:TI 0 "register_operand")
2907 (match_operand:TI 1 "register_operand")
2908 (match_operand:TI 2 "aarch64_reg_or_imm")
2909 (label_ref (match_operand 3 "" ""))]
2912 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2914 aarch64_subvti_scratch_regs (operands[1], operands[2],
2915 &low_dest, &op1_low, &op2_low,
2916 &high_dest, &op1_high, &op2_high);
2917 aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
2918 high_dest, op1_high, op2_high, false);
2920 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2924 (define_expand "usubvti4"
2925 [(match_operand:TI 0 "register_operand")
2926 (match_operand:TI 1 "register_operand")
2927 (match_operand:TI 2 "aarch64_reg_or_imm")
2928 (label_ref (match_operand 3 "" ""))]
2931 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2933 aarch64_subvti_scratch_regs (operands[1], operands[2],
2934 &low_dest, &op1_low, &op2_low,
2935 &high_dest, &op1_high, &op2_high);
2936 aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
2937 high_dest, op1_high, op2_high, true);
2939 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
2943 (define_expand "negvti3"
2944 [(match_operand:TI 0 "register_operand")
2945 (match_operand:TI 1 "register_operand")
2946 (label_ref (match_operand 2 "" ""))]
2949 emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[0]),
2950 gen_lowpart (DImode, operands[1])));
2951 emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[0]),
2952 gen_highpart (DImode, operands[1])));
2953 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
2959 (define_insn "negdi_carryout"
2960 [(set (reg:CC CC_REGNUM)
2962 (const_int 0) (match_operand:DI 1 "register_operand" "r")))
2963 (set (match_operand:DI 0 "register_operand" "=r")
2964 (neg:DI (match_dup 1)))]
2967 [(set_attr "type" "alus_sreg")]
2970 (define_insn "negvdi_carryinV"
2971 [(set (reg:CC_V CC_REGNUM)
2974 (ltu:TI (reg:CC CC_REGNUM) (const_int 0))
2975 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))))
2977 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
2979 (set (match_operand:DI 0 "register_operand" "=r")
2980 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
2984 [(set_attr "type" "alus_sreg")]
2987 (define_insn "*sub<mode>3_compare0"
2988 [(set (reg:CC_NZ CC_REGNUM)
2989 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2990 (match_operand:GPI 2 "register_operand" "r"))
2992 (set (match_operand:GPI 0 "register_operand" "=r")
2993 (minus:GPI (match_dup 1) (match_dup 2)))]
2995 "subs\\t%<w>0, %<w>1, %<w>2"
2996 [(set_attr "type" "alus_sreg")]
2999 ;; zero_extend version of above
3000 (define_insn "*subsi3_compare0_uxtw"
3001 [(set (reg:CC_NZ CC_REGNUM)
3002 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "rk")
3003 (match_operand:SI 2 "register_operand" "r"))
3005 (set (match_operand:DI 0 "register_operand" "=r")
3006 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
3008 "subs\\t%w0, %w1, %w2"
3009 [(set_attr "type" "alus_sreg")]
3012 (define_insn "sub<mode>3_compare1_imm"
3013 [(set (reg:CC CC_REGNUM)
3015 (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ,rkZ")
3016 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))
3017 (set (match_operand:GPI 0 "register_operand" "=r,r")
3020 (match_operand:GPI 3 "aarch64_plus_immediate" "J,I")))]
3021 "UINTVAL (operands[2]) == -UINTVAL (operands[3])"
3023 subs\\t%<w>0, %<w>1, %2
3024 adds\\t%<w>0, %<w>1, #%n2"
3025 [(set_attr "type" "alus_imm")]
3028 (define_insn "sub<mode>3_compare1"
3029 [(set (reg:CC CC_REGNUM)
3031 (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ")
3032 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
3033 (set (match_operand:GPI 0 "register_operand" "=r")
3034 (minus:GPI (match_dup 1) (match_dup 2)))]
3036 "subs\\t%<w>0, %<w>1, %<w>2"
3037 [(set_attr "type" "alus_sreg")]
3041 [(set (match_operand:GPI 0 "aarch64_general_reg")
3042 (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
3043 (match_operand:GPI 2 "aarch64_reg_or_zero")))
3044 (set (reg:CC CC_REGNUM)
3048 "!reg_overlap_mentioned_p (operands[0], operands[1])
3049 && !reg_overlap_mentioned_p (operands[0], operands[2])"
3052 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
3058 ;; Same as the above peephole but with the compare and minus in
3059 ;; swapped order. The restriction on overlap between operand 0
3060 ;; and operands 1 and 2 doesn't apply here.
3062 [(set (reg:CC CC_REGNUM)
3064 (match_operand:GPI 1 "aarch64_reg_or_zero")
3065 (match_operand:GPI 2 "aarch64_reg_or_zero")))
3066 (set (match_operand:GPI 0 "aarch64_general_reg")
3067 (minus:GPI (match_dup 1)
3072 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
3079 [(set (match_operand:GPI 0 "aarch64_general_reg")
3080 (plus:GPI (match_operand:GPI 1 "register_operand")
3081 (match_operand:GPI 2 "aarch64_plus_immediate")))
3082 (set (reg:CC CC_REGNUM)
3085 (match_operand:GPI 3 "const_int_operand")))]
3086 "!reg_overlap_mentioned_p (operands[0], operands[1])
3087 && INTVAL (operands[3]) == -INTVAL (operands[2])"
3090 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3091 operands[3], operands[2]));
3096 ;; Same as the above peephole but with the compare and minus in
3097 ;; swapped order. The restriction on overlap between operand 0
3098 ;; and operands 1 doesn't apply here.
3100 [(set (reg:CC CC_REGNUM)
3102 (match_operand:GPI 1 "register_operand")
3103 (match_operand:GPI 3 "const_int_operand")))
3104 (set (match_operand:GPI 0 "aarch64_general_reg")
3105 (plus:GPI (match_dup 1)
3106 (match_operand:GPI 2 "aarch64_plus_immediate")))]
3107 "INTVAL (operands[3]) == -INTVAL (operands[2])"
3110 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3111 operands[3], operands[2]));
3116 (define_insn "*sub_<shift>_<mode>"
3117 [(set (match_operand:GPI 0 "register_operand" "=r")
3118 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3120 (match_operand:GPI 1 "register_operand" "r")
3121 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3123 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
3124 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3127 ;; zero_extend version of above
3128 (define_insn "*sub_<shift>_si_uxtw"
3129 [(set (match_operand:DI 0 "register_operand" "=r")
3131 (minus:SI (match_operand:SI 3 "register_operand" "r")
3133 (match_operand:SI 1 "register_operand" "r")
3134 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
3136 "sub\\t%w0, %w3, %w1, <shift> %2"
3137 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3140 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
3141 [(set (match_operand:GPI 0 "register_operand" "=rk")
3142 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3144 (match_operand:ALLX 2 "register_operand" "r"))))]
3146 "sub\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size>"
3147 [(set_attr "type" "alu_ext")]
3150 ;; zero_extend version of above
3151 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
3152 [(set (match_operand:DI 0 "register_operand" "=rk")
3154 (minus:SI (match_operand:SI 1 "register_operand" "rk")
3156 (match_operand:SHORT 2 "register_operand" "r")))))]
3158 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
3159 [(set_attr "type" "alu_ext")]
3162 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
3163 [(set (match_operand:GPI 0 "register_operand" "=rk")
3164 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3165 (ashift:GPI (ANY_EXTEND:GPI
3166 (match_operand:ALLX 2 "register_operand" "r"))
3167 (match_operand 3 "aarch64_imm3" "Ui3"))))]
3169 "sub\\t%<GPI:w>0, %<GPI:w>1, %w2, <su>xt<ALLX:size> %3"
3170 [(set_attr "type" "alu_ext")]
3173 ;; zero_extend version of above
3174 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
3175 [(set (match_operand:DI 0 "register_operand" "=rk")
3177 (minus:SI (match_operand:SI 1 "register_operand" "rk")
3178 (ashift:SI (ANY_EXTEND:SI
3179 (match_operand:SHORT 2 "register_operand" "r"))
3180 (match_operand 3 "aarch64_imm3" "Ui3")))))]
3182 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
3183 [(set_attr "type" "alu_ext")]
3186 ;; The hardware description is op1 + ~op2 + C.
3187 ;; = op1 + (-op2 + 1) + (1 - !C)
3188 ;; = op1 - op2 - 1 + 1 - !C
3189 ;; = op1 - op2 - !C.
3190 ;; We describe the latter.
3192 (define_insn "*sub<mode>3_carryin0"
3193 [(set (match_operand:GPI 0 "register_operand" "=r")
3195 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3196 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
3198 "sbc\\t%<w>0, %<w>1, <w>zr"
3199 [(set_attr "type" "adc_reg")]
3202 ;; zero_extend version of the above
3203 (define_insn "*subsi3_carryin_uxtw"
3204 [(set (match_operand:DI 0 "register_operand" "=r")
3207 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3208 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
3210 "sbc\\t%w0, %w1, wzr"
3211 [(set_attr "type" "adc_reg")]
3214 (define_expand "sub<mode>3_carryin"
3215 [(set (match_operand:GPI 0 "register_operand")
3218 (match_operand:GPI 1 "aarch64_reg_or_zero")
3219 (match_operand:GPI 2 "register_operand"))
3220 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
3225 (define_insn "*sub<mode>3_carryin"
3226 [(set (match_operand:GPI 0 "register_operand" "=r")
3229 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3230 (match_operand:GPI 2 "register_operand" "r"))
3231 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3234 "sbc\\t%<w>0, %<w>1, %<w>2"
3235 [(set_attr "type" "adc_reg")]
3238 ;; zero_extend version of the above
3239 (define_insn "*subsi3_carryin_uxtw"
3240 [(set (match_operand:DI 0 "register_operand" "=r")
3244 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3245 (match_operand:SI 2 "register_operand" "r"))
3246 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
3249 "sbc\\t%w0, %w1, %w2"
3250 [(set_attr "type" "adc_reg")]
3253 (define_insn "*sub<mode>3_carryin_alt"
3254 [(set (match_operand:GPI 0 "register_operand" "=r")
3257 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3258 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
3259 (match_operand:GPI 2 "register_operand" "r")))]
3261 "sbc\\t%<w>0, %<w>1, %<w>2"
3262 [(set_attr "type" "adc_reg")]
3265 ;; zero_extend version of the above
3266 (define_insn "*subsi3_carryin_alt_uxtw"
3267 [(set (match_operand:DI 0 "register_operand" "=r")
3271 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3272 (match_operand:SI 3 "aarch64_borrow_operation" ""))
3273 (match_operand:SI 2 "register_operand" "r"))))]
3275 "sbc\\t%w0, %w1, %w2"
3276 [(set_attr "type" "adc_reg")]
3279 (define_expand "usub<GPI:mode>3_carryinC"
3281 [(set (reg:CC CC_REGNUM)
3284 (match_operand:GPI 1 "aarch64_reg_or_zero"))
3287 (match_operand:GPI 2 "register_operand"))
3288 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0)))))
3289 (set (match_operand:GPI 0 "register_operand")
3291 (minus:GPI (match_dup 1) (match_dup 2))
3292 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3296 (define_insn "*usub<GPI:mode>3_carryinC_z1"
3297 [(set (reg:CC CC_REGNUM)
3302 (match_operand:GPI 1 "register_operand" "r"))
3303 (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))))
3304 (set (match_operand:GPI 0 "register_operand" "=r")
3306 (neg:GPI (match_dup 1))
3307 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3309 "sbcs\\t%<w>0, <w>zr, %<w>1"
3310 [(set_attr "type" "adc_reg")]
3313 (define_insn "*usub<GPI:mode>3_carryinC_z2"
3314 [(set (reg:CC CC_REGNUM)
3317 (match_operand:GPI 1 "register_operand" "r"))
3318 (match_operand:<DWI> 2 "aarch64_borrow_operation" "")))
3319 (set (match_operand:GPI 0 "register_operand" "=r")
3322 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3324 "sbcs\\t%<w>0, %<w>1, <w>zr"
3325 [(set_attr "type" "adc_reg")]
3328 (define_insn "*usub<GPI:mode>3_carryinC"
3329 [(set (reg:CC CC_REGNUM)
3332 (match_operand:GPI 1 "register_operand" "r"))
3335 (match_operand:GPI 2 "register_operand" "r"))
3336 (match_operand:<DWI> 3 "aarch64_borrow_operation" ""))))
3337 (set (match_operand:GPI 0 "register_operand" "=r")
3339 (minus:GPI (match_dup 1) (match_dup 2))
3340 (match_operand:GPI 4 "aarch64_borrow_operation" "")))]
3342 "sbcs\\t%<w>0, %<w>1, %<w>2"
3343 [(set_attr "type" "adc_reg")]
3346 (define_expand "sub<GPI:mode>3_carryinV"
3348 [(set (reg:CC_V CC_REGNUM)
3352 (match_operand:GPI 1 "aarch64_reg_or_zero"))
3355 (match_operand:GPI 2 "register_operand"))
3356 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0))))
3358 (minus:GPI (match_dup 1)
3359 (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))
3361 (set (match_operand:GPI 0 "register_operand")
3363 (minus:GPI (match_dup 1) (match_dup 2))
3364 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3368 (define_insn "*sub<mode>3_carryinV_z2"
3369 [(set (reg:CC_V CC_REGNUM)
3372 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
3373 (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))
3375 (minus:GPI (match_dup 1)
3376 (match_operand:GPI 3 "aarch64_borrow_operation" "")))))
3377 (set (match_operand:GPI 0 "register_operand" "=r")
3379 (match_dup 1) (match_dup 3)))]
3381 "sbcs\\t%<w>0, %<w>1, <w>zr"
3382 [(set_attr "type" "adc_reg")]
3385 (define_insn "*sub<mode>3_carryinV"
3386 [(set (reg:CC_V CC_REGNUM)
3390 (match_operand:GPI 1 "register_operand" "r"))
3393 (match_operand:GPI 2 "register_operand" "r"))
3394 (match_operand:<DWI> 3 "aarch64_borrow_operation" "")))
3398 (plus:GPI (match_operand:GPI 4 "aarch64_borrow_operation" "")
3400 (set (match_operand:GPI 0 "register_operand" "=r")
3402 (minus:GPI (match_dup 1) (match_dup 2))
3405 "sbcs\\t%<w>0, %<w>1, %<w>2"
3406 [(set_attr "type" "adc_reg")]
3409 (define_insn "*sub_uxt<mode>_shift2"
3410 [(set (match_operand:GPI 0 "register_operand" "=rk")
3411 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
3413 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3414 (match_operand 2 "aarch64_imm3" "Ui3"))
3415 (match_operand 3 "const_int_operand" "n"))))]
3416 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
3418 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3419 INTVAL (operands[3])));
3420 return \"sub\t%<w>0, %<w>4, %w1, uxt%e3 %2\";"
3421 [(set_attr "type" "alu_ext")]
3424 ;; zero_extend version of above
3425 (define_insn "*sub_uxtsi_shift2_uxtw"
3426 [(set (match_operand:DI 0 "register_operand" "=rk")
3428 (minus:SI (match_operand:SI 4 "register_operand" "rk")
3430 (ashift:SI (match_operand:SI 1 "register_operand" "r")
3431 (match_operand 2 "aarch64_imm3" "Ui3"))
3432 (match_operand 3 "const_int_operand" "n")))))]
3433 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
3435 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3436 INTVAL (operands[3])));
3437 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
3438 [(set_attr "type" "alu_ext")]
3441 (define_expand "abs<mode>2"
3442 [(match_operand:GPI 0 "register_operand")
3443 (match_operand:GPI 1 "register_operand")]
3446 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
3447 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3448 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
3453 (define_insn "neg<mode>2"
3454 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3455 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3459 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
3460 [(set_attr "type" "alu_sreg, neon_neg<q>")
3461 (set_attr "arch" "*,simd")]
3464 ;; zero_extend version of above
3465 (define_insn "*negsi2_uxtw"
3466 [(set (match_operand:DI 0 "register_operand" "=r")
3467 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
3470 [(set_attr "type" "alu_sreg")]
3473 (define_insn "*ngc<mode>"
3474 [(set (match_operand:GPI 0 "register_operand" "=r")
3476 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
3477 (match_operand:GPI 1 "register_operand" "r")))]
3479 "ngc\\t%<w>0, %<w>1"
3480 [(set_attr "type" "adc_reg")]
3483 (define_insn "*ngcsi_uxtw"
3484 [(set (match_operand:DI 0 "register_operand" "=r")
3487 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
3488 (match_operand:SI 1 "register_operand" "r"))))]
3491 [(set_attr "type" "adc_reg")]
3494 (define_insn "neg<mode>2_compare0"
3495 [(set (reg:CC_NZ CC_REGNUM)
3496 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
3498 (set (match_operand:GPI 0 "register_operand" "=r")
3499 (neg:GPI (match_dup 1)))]
3501 "negs\\t%<w>0, %<w>1"
3502 [(set_attr "type" "alus_sreg")]
3505 ;; zero_extend version of above
3506 (define_insn "*negsi2_compare0_uxtw"
3507 [(set (reg:CC_NZ CC_REGNUM)
3508 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
3510 (set (match_operand:DI 0 "register_operand" "=r")
3511 (zero_extend:DI (neg:SI (match_dup 1))))]
3514 [(set_attr "type" "alus_sreg")]
3517 (define_insn "*neg_<shift><mode>3_compare0"
3518 [(set (reg:CC_NZ CC_REGNUM)
3520 (neg:GPI (ASHIFT:GPI
3521 (match_operand:GPI 1 "register_operand" "r")
3522 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3524 (set (match_operand:GPI 0 "register_operand" "=r")
3525 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
3527 "negs\\t%<w>0, %<w>1, <shift> %2"
3528 [(set_attr "type" "alus_shift_imm")]
3531 (define_insn "*neg_<shift>_<mode>2"
3532 [(set (match_operand:GPI 0 "register_operand" "=r")
3533 (neg:GPI (ASHIFT:GPI
3534 (match_operand:GPI 1 "register_operand" "r")
3535 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3537 "neg\\t%<w>0, %<w>1, <shift> %2"
3538 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3541 ;; zero_extend version of above
3542 (define_insn "*neg_<shift>_si2_uxtw"
3543 [(set (match_operand:DI 0 "register_operand" "=r")
3546 (match_operand:SI 1 "register_operand" "r")
3547 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
3549 "neg\\t%w0, %w1, <shift> %2"
3550 [(set_attr "autodetect_type" "alu_shift_<shift>_op2")]
3553 (define_insn "mul<mode>3"
3554 [(set (match_operand:GPI 0 "register_operand" "=r")
3555 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3556 (match_operand:GPI 2 "register_operand" "r")))]
3558 "mul\\t%<w>0, %<w>1, %<w>2"
3559 [(set_attr "type" "mul")]
3562 ;; zero_extend version of above
3563 (define_insn "*mulsi3_uxtw"
3564 [(set (match_operand:DI 0 "register_operand" "=r")
3566 (mult:SI (match_operand:SI 1 "register_operand" "r")
3567 (match_operand:SI 2 "register_operand" "r"))))]
3569 "mul\\t%w0, %w1, %w2"
3570 [(set_attr "type" "mul")]
3573 (define_insn "madd<mode>"
3574 [(set (match_operand:GPI 0 "register_operand" "=r")
3575 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3576 (match_operand:GPI 2 "register_operand" "r"))
3577 (match_operand:GPI 3 "register_operand" "r")))]
3579 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
3580 [(set_attr "type" "mla")]
3583 ;; zero_extend version of above
3584 (define_insn "*maddsi_uxtw"
3585 [(set (match_operand:DI 0 "register_operand" "=r")
3587 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
3588 (match_operand:SI 2 "register_operand" "r"))
3589 (match_operand:SI 3 "register_operand" "r"))))]
3591 "madd\\t%w0, %w1, %w2, %w3"
3592 [(set_attr "type" "mla")]
3595 (define_insn "*msub<mode>"
3596 [(set (match_operand:GPI 0 "register_operand" "=r")
3597 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3598 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3599 (match_operand:GPI 2 "register_operand" "r"))))]
3602 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
3603 [(set_attr "type" "mla")]
3606 ;; zero_extend version of above
3607 (define_insn "*msubsi_uxtw"
3608 [(set (match_operand:DI 0 "register_operand" "=r")
3610 (minus:SI (match_operand:SI 3 "register_operand" "r")
3611 (mult:SI (match_operand:SI 1 "register_operand" "r")
3612 (match_operand:SI 2 "register_operand" "r")))))]
3615 "msub\\t%w0, %w1, %w2, %w3"
3616 [(set_attr "type" "mla")]
3619 (define_insn "*mul<mode>_neg"
3620 [(set (match_operand:GPI 0 "register_operand" "=r")
3621 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
3622 (match_operand:GPI 2 "register_operand" "r")))]
3625 "mneg\\t%<w>0, %<w>1, %<w>2"
3626 [(set_attr "type" "mul")]
3629 ;; zero_extend version of above
3630 (define_insn "*mulsi_neg_uxtw"
3631 [(set (match_operand:DI 0 "register_operand" "=r")
3633 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
3634 (match_operand:SI 2 "register_operand" "r"))))]
3637 "mneg\\t%w0, %w1, %w2"
3638 [(set_attr "type" "mul")]
3641 (define_insn "<su_optab>mulsidi3"
3642 [(set (match_operand:DI 0 "register_operand" "=r")
3643 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3644 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
3646 "<su>mull\\t%0, %w1, %w2"
3647 [(set_attr "type" "<su>mull")]
3650 (define_insn "<su_optab>maddsidi4"
3651 [(set (match_operand:DI 0 "register_operand" "=r")
3653 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3654 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
3655 (match_operand:DI 3 "register_operand" "r")))]
3657 "<su>maddl\\t%0, %w1, %w2, %3"
3658 [(set_attr "type" "<su>mlal")]
3661 (define_insn "<su_optab>msubsidi4"
3662 [(set (match_operand:DI 0 "register_operand" "=r")
3664 (match_operand:DI 3 "register_operand" "r")
3665 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3667 (match_operand:SI 2 "register_operand" "r")))))]
3669 "<su>msubl\\t%0, %w1, %w2, %3"
3670 [(set_attr "type" "<su>mlal")]
3673 (define_insn "*<su_optab>mulsidi_neg"
3674 [(set (match_operand:DI 0 "register_operand" "=r")
3676 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
3677 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
3679 "<su>mnegl\\t%0, %w1, %w2"
3680 [(set_attr "type" "<su>mull")]
3683 (define_expand "<su_optab>mulditi3"
3684 [(set (match_operand:TI 0 "register_operand")
3685 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
3686 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
3689 rtx low = gen_reg_rtx (DImode);
3690 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
3692 rtx high = gen_reg_rtx (DImode);
3693 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
3695 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
3696 emit_move_insn (gen_highpart (DImode, operands[0]), high);
3700 ;; The default expansion of multi3 using umuldi3_highpart will perform
3701 ;; the additions in an order that fails to combine into two madd insns.
3702 (define_expand "multi3"
3703 [(set (match_operand:TI 0 "register_operand")
3704 (mult:TI (match_operand:TI 1 "register_operand")
3705 (match_operand:TI 2 "register_operand")))]
3708 rtx l0 = gen_reg_rtx (DImode);
3709 rtx l1 = gen_lowpart (DImode, operands[1]);
3710 rtx l2 = gen_lowpart (DImode, operands[2]);
3711 rtx h0 = gen_reg_rtx (DImode);
3712 rtx h1 = gen_highpart (DImode, operands[1]);
3713 rtx h2 = gen_highpart (DImode, operands[2]);
3715 emit_insn (gen_muldi3 (l0, l1, l2));
3716 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3717 emit_insn (gen_madddi (h0, h1, l2, h0));
3718 emit_insn (gen_madddi (h0, l1, h2, h0));
3720 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
3721 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
3725 (define_insn "<su>muldi3_highpart"
3726 [(set (match_operand:DI 0 "register_operand" "=r")
3730 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
3731 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
3734 "<su>mulh\\t%0, %1, %2"
3735 [(set_attr "type" "<su>mull")]
3738 (define_insn "<su_optab>div<mode>3"
3739 [(set (match_operand:GPI 0 "register_operand" "=r")
3740 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
3741 (match_operand:GPI 2 "register_operand" "r")))]
3743 "<su>div\\t%<w>0, %<w>1, %<w>2"
3744 [(set_attr "type" "<su>div")]
3747 ;; zero_extend version of above
3748 (define_insn "*<su_optab>divsi3_uxtw"
3749 [(set (match_operand:DI 0 "register_operand" "=r")
3751 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
3752 (match_operand:SI 2 "register_operand" "r"))))]
3754 "<su>div\\t%w0, %w1, %w2"
3755 [(set_attr "type" "<su>div")]
3758 ;; -------------------------------------------------------------------
3760 ;; -------------------------------------------------------------------
3762 (define_insn "cmp<mode>"
3763 [(set (reg:CC CC_REGNUM)
3764 (compare:CC (match_operand:GPI 0 "register_operand" "rk,rk,rk")
3765 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
3771 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3774 (define_insn "fcmp<mode>"
3775 [(set (reg:CCFP CC_REGNUM)
3776 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
3777 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3781 fcmp\\t%<s>0, %<s>1"
3782 [(set_attr "type" "fcmp<s>")]
3785 (define_insn "fcmpe<mode>"
3786 [(set (reg:CCFPE CC_REGNUM)
3787 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
3788 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3792 fcmpe\\t%<s>0, %<s>1"
3793 [(set_attr "type" "fcmp<s>")]
3796 (define_insn "*cmp_swp_<shift>_reg<mode>"
3797 [(set (reg:CC_SWP CC_REGNUM)
3798 (compare:CC_SWP (ASHIFT:GPI
3799 (match_operand:GPI 0 "register_operand" "r")
3800 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3801 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3803 "cmp\\t%<w>2, %<w>0, <shift> %1"
3804 [(set_attr "type" "alus_shift_imm")]
3807 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3808 [(set (reg:CC_SWP CC_REGNUM)
3809 (compare:CC_SWP (ANY_EXTEND:GPI
3810 (match_operand:ALLX 0 "register_operand" "r"))
3811 (match_operand:GPI 1 "register_operand" "r")))]
3813 "cmp\\t%<GPI:w>1, %w0, <su>xt<ALLX:size>"
3814 [(set_attr "type" "alus_ext")]
3817 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3818 [(set (reg:CC_SWP CC_REGNUM)
3819 (compare:CC_SWP (ashift:GPI
3821 (match_operand:ALLX 0 "register_operand" "r"))
3822 (match_operand 1 "aarch64_imm3" "Ui3"))
3823 (match_operand:GPI 2 "register_operand" "r")))]
3825 "cmp\\t%<GPI:w>2, %w0, <su>xt<ALLX:size> %1"
3826 [(set_attr "type" "alus_ext")]
3829 ;; -------------------------------------------------------------------
3830 ;; Store-flag and conditional select insns
3831 ;; -------------------------------------------------------------------
3833 (define_expand "cstore<mode>4"
3834 [(set (match_operand:SI 0 "register_operand")
3835 (match_operator:SI 1 "aarch64_comparison_operator"
3836 [(match_operand:GPI 2 "register_operand")
3837 (match_operand:GPI 3 "aarch64_plus_operand")]))]
3840 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3842 operands[3] = const0_rtx;
3846 (define_expand "cstorecc4"
3847 [(set (match_operand:SI 0 "register_operand")
3848 (match_operator 1 "aarch64_comparison_operator_mode"
3849 [(match_operand 2 "cc_register")
3850 (match_operand 3 "const0_operand")]))]
3853 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3858 (define_expand "cstore<mode>4"
3859 [(set (match_operand:SI 0 "register_operand")
3860 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3861 [(match_operand:GPF 2 "register_operand")
3862 (match_operand:GPF 3 "aarch64_fp_compare_operand")]))]
3865 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3867 operands[3] = const0_rtx;
3871 (define_insn "aarch64_cstore<mode>"
3872 [(set (match_operand:ALLI 0 "register_operand" "=r")
3873 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3874 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3877 [(set_attr "type" "csel")]
3880 ;; For a 24-bit immediate CST we can optimize the compare for equality
3881 ;; and branch sequence from:
3883 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3886 ;; into the shorter:
3887 ;; sub x0, x1, #(CST & 0xfff000)
3888 ;; subs x0, x0, #(CST & 0x000fff)
3889 ;; cset x2, <ne, eq>.
3890 (define_insn_and_split "*compare_cstore<mode>_insn"
3891 [(set (match_operand:GPI 0 "register_operand" "=r")
3892 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3893 (match_operand:GPI 2 "aarch64_imm24" "n")))
3894 (clobber (reg:CC CC_REGNUM))]
3895 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3896 && !aarch64_plus_operand (operands[2], <MODE>mode)
3897 && !reload_completed"
3902 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3903 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3904 rtx tmp = gen_reg_rtx (<MODE>mode);
3905 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3906 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3907 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3908 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3909 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3912 [(set_attr "type" "csel")]
3915 ;; zero_extend version of the above
3916 (define_insn "*cstoresi_insn_uxtw"
3917 [(set (match_operand:DI 0 "register_operand" "=r")
3919 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3920 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3923 [(set_attr "type" "csel")]
3926 (define_insn "cstore<mode>_neg"
3927 [(set (match_operand:ALLI 0 "register_operand" "=r")
3928 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3929 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3931 "csetm\\t%<w>0, %m1"
3932 [(set_attr "type" "csel")]
3935 ;; zero_extend version of the above
3936 (define_insn "*cstoresi_neg_uxtw"
3937 [(set (match_operand:DI 0 "register_operand" "=r")
3939 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3940 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3943 [(set_attr "type" "csel")]
3946 (define_expand "cmov<mode>6"
3947 [(set (match_operand:GPI 0 "register_operand")
3949 (match_operator 1 "aarch64_comparison_operator"
3950 [(match_operand:GPI 2 "register_operand")
3951 (match_operand:GPI 3 "aarch64_plus_operand")])
3952 (match_operand:GPI 4 "register_operand")
3953 (match_operand:GPI 5 "register_operand")))]
3956 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3958 operands[3] = const0_rtx;
3962 (define_expand "cmov<mode>6"
3963 [(set (match_operand:GPF 0 "register_operand")
3965 (match_operator 1 "aarch64_comparison_operator"
3966 [(match_operand:GPF 2 "register_operand")
3967 (match_operand:GPF 3 "aarch64_fp_compare_operand")])
3968 (match_operand:GPF 4 "register_operand")
3969 (match_operand:GPF 5 "register_operand")))]
3972 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3974 operands[3] = const0_rtx;
3978 (define_insn "*cmov<mode>_insn"
3979 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3981 (match_operator 1 "aarch64_comparison_operator"
3982 [(match_operand 2 "cc_register" "") (const_int 0)])
3983 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3984 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3985 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3986 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3987 ;; Final two alternatives should be unreachable, but included for completeness
3989 csel\\t%<w>0, %<w>3, %<w>4, %m1
3990 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3991 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3992 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3993 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3996 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3999 ;; zero_extend version of above
4000 (define_insn "*cmovsi_insn_uxtw"
4001 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
4004 (match_operator 1 "aarch64_comparison_operator"
4005 [(match_operand 2 "cc_register" "") (const_int 0)])
4006 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4007 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
4008 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
4009 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
4010 ;; Final two alternatives should be unreachable, but included for completeness
4012 csel\\t%w0, %w3, %w4, %m1
4013 csinv\\t%w0, %w3, wzr, %m1
4014 csinv\\t%w0, %w4, wzr, %M1
4015 csinc\\t%w0, %w3, wzr, %m1
4016 csinc\\t%w0, %w4, wzr, %M1
4019 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4022 (define_insn "*cmovdi_insn_uxtw"
4023 [(set (match_operand:DI 0 "register_operand" "=r")
4025 (match_operator 1 "aarch64_comparison_operator"
4026 [(match_operand 2 "cc_register" "") (const_int 0)])
4027 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
4028 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
4030 "csel\\t%w0, %w3, %w4, %m1"
4031 [(set_attr "type" "csel")]
4034 (define_insn "*cmov<mode>_insn"
4035 [(set (match_operand:GPF 0 "register_operand" "=w")
4037 (match_operator 1 "aarch64_comparison_operator"
4038 [(match_operand 2 "cc_register" "") (const_int 0)])
4039 (match_operand:GPF 3 "register_operand" "w")
4040 (match_operand:GPF 4 "register_operand" "w")))]
4042 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
4043 [(set_attr "type" "fcsel")]
4046 (define_expand "mov<mode>cc"
4047 [(set (match_operand:ALLI 0 "register_operand")
4048 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator")
4049 (match_operand:ALLI 2 "register_operand")
4050 (match_operand:ALLI 3 "register_operand")))]
4054 enum rtx_code code = GET_CODE (operands[1]);
4056 if (code == UNEQ || code == LTGT)
4059 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4060 XEXP (operands[1], 1));
4061 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4065 (define_expand "mov<GPF:mode><GPI:mode>cc"
4066 [(set (match_operand:GPI 0 "register_operand")
4067 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator")
4068 (match_operand:GPF 2 "register_operand")
4069 (match_operand:GPF 3 "register_operand")))]
4073 enum rtx_code code = GET_CODE (operands[1]);
4075 if (code == UNEQ || code == LTGT)
4078 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4079 XEXP (operands[1], 1));
4080 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4084 (define_expand "mov<mode>cc"
4085 [(set (match_operand:GPF 0 "register_operand")
4086 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator")
4087 (match_operand:GPF 2 "register_operand")
4088 (match_operand:GPF 3 "register_operand")))]
4092 enum rtx_code code = GET_CODE (operands[1]);
4094 if (code == UNEQ || code == LTGT)
4097 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4098 XEXP (operands[1], 1));
4099 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4103 (define_expand "<neg_not_op><mode>cc"
4104 [(set (match_operand:GPI 0 "register_operand")
4105 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator")
4106 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand"))
4107 (match_operand:GPI 3 "register_operand")))]
4111 enum rtx_code code = GET_CODE (operands[1]);
4113 if (code == UNEQ || code == LTGT)
4116 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4117 XEXP (operands[1], 1));
4118 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4122 ;; CRC32 instructions.
4123 (define_insn "aarch64_<crc_variant>"
4124 [(set (match_operand:SI 0 "register_operand" "=r")
4125 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
4126 (match_operand:<crc_mode> 2 "register_operand" "r")]
4130 if (GET_MODE_BITSIZE (<crc_mode>mode) >= 64)
4131 return "<crc_variant>\\t%w0, %w1, %x2";
4133 return "<crc_variant>\\t%w0, %w1, %w2";
4135 [(set_attr "type" "crc")]
4138 (define_insn "*csinc2<mode>_insn"
4139 [(set (match_operand:GPI 0 "register_operand" "=r")
4140 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
4141 (match_operand:GPI 1 "register_operand" "r")))]
4143 "cinc\\t%<w>0, %<w>1, %m2"
4144 [(set_attr "type" "csel")]
4147 (define_insn "csinc3<mode>_insn"
4148 [(set (match_operand:GPI 0 "register_operand" "=r")
4150 (match_operand 1 "aarch64_comparison_operation" "")
4151 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
4153 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4155 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
4156 [(set_attr "type" "csel")]
4159 (define_insn "*csinv3<mode>_insn"
4160 [(set (match_operand:GPI 0 "register_operand" "=r")
4162 (match_operand 1 "aarch64_comparison_operation" "")
4163 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
4164 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4166 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
4167 [(set_attr "type" "csel")]
4170 (define_insn "csneg3_uxtw_insn"
4171 [(set (match_operand:DI 0 "register_operand" "=r")
4174 (match_operand 1 "aarch64_comparison_operation" "")
4175 (neg:SI (match_operand:SI 2 "register_operand" "r"))
4176 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
4178 "csneg\\t%w0, %w3, %w2, %M1"
4179 [(set_attr "type" "csel")]
4182 (define_insn "csneg3<mode>_insn"
4183 [(set (match_operand:GPI 0 "register_operand" "=r")
4185 (match_operand 1 "aarch64_comparison_operation" "")
4186 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
4187 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4189 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
4190 [(set_attr "type" "csel")]
4193 (define_insn "*csinv3_uxtw_insn1"
4194 [(set (match_operand:DI 0 "register_operand" "=r")
4196 (match_operand 1 "aarch64_comparison_operation" "")
4198 (match_operand:SI 2 "register_operand" "r"))
4200 (NEG_NOT:SI (match_operand:SI 3 "register_operand" "r")))))]
4202 "cs<neg_not_cs>\\t%w0, %w2, %w3, %m1"
4203 [(set_attr "type" "csel")]
4206 (define_insn "*csinv3_uxtw_insn2"
4207 [(set (match_operand:DI 0 "register_operand" "=r")
4209 (match_operand 1 "aarch64_comparison_operation" "")
4211 (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
4213 (match_operand:SI 3 "register_operand" "r"))))]
4215 "cs<neg_not_cs>\\t%w0, %w3, %w2, %M1"
4216 [(set_attr "type" "csel")]
4219 (define_insn "*csinv3_uxtw_insn3"
4220 [(set (match_operand:DI 0 "register_operand" "=r")
4222 (match_operand 1 "aarch64_comparison_operation" "")
4224 (NEG_NOT:SI (match_operand:SI 2 "register_operand" "r")))
4227 "cs<neg_not_cs>\\t%w0, wzr, %w2, %M1"
4228 [(set_attr "type" "csel")]
4231 ;; If X can be loaded by a single CNT[BHWD] instruction,
4235 ;; is equivalent to:
4237 ;; TMP = UQDEC[BHWD] (B, X)
4240 ;; Defining the pattern this way means that:
4242 ;; A = UMAX (B, X) - X
4246 ;; TMP1 = UQDEC[BHWD] (B, X)
4250 ;; which combine can optimize to:
4252 ;; A = UQDEC[BHWD] (B, X)
4254 ;; We don't use match_operand predicates because the order of the operands
4255 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4256 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4257 (define_expand "umax<mode>3"
4258 [(set (match_operand:GPI 0 "register_operand")
4259 (umax:GPI (match_operand:GPI 1 "")
4260 (match_operand:GPI 2 "")))]
4263 if (aarch64_sve_cnt_immediate (operands[1], <MODE>mode))
4264 std::swap (operands[1], operands[2]);
4265 else if (!aarch64_sve_cnt_immediate (operands[2], <MODE>mode))
4267 rtx temp = gen_reg_rtx (<MODE>mode);
4268 operands[1] = force_reg (<MODE>mode, operands[1]);
4269 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[1], operands[2]));
4270 emit_insn (gen_add<mode>3 (operands[0], temp, operands[2]));
4275 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4276 (define_insn "aarch64_uqdec<mode>"
4277 [(set (match_operand:GPI 0 "register_operand" "=r")
4279 (umax:GPI (match_operand:GPI 1 "register_operand" "0")
4280 (match_operand:GPI 2 "aarch64_sve_cnt_immediate" "Usv"))
4284 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>0", operands[2]);
4288 ;; -------------------------------------------------------------------
4289 ;; Logical operations
4290 ;; -------------------------------------------------------------------
4293 (define_insn_and_split "*aarch64_and<mode>_imm2"
4294 [(set (match_operand:GPI 0 "register_operand" "=rk")
4295 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
4296 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
4302 HOST_WIDE_INT val = INTVAL (operands[2]);
4303 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4304 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4306 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
4307 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
4312 (define_insn "<optab><mode>3"
4313 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
4314 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
4315 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
4318 <logical>\\t%<w>0, %<w>1, %<w>2
4319 <logical>\\t%<w>0, %<w>1, %2
4320 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
4321 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
4322 (set_attr "arch" "*,*,simd")]
4325 ;; zero_extend version of above
4326 (define_insn "*<optab>si3_uxtw"
4327 [(set (match_operand:DI 0 "register_operand" "=r,rk")
4329 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
4330 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
4333 <logical>\\t%w0, %w1, %w2
4334 <logical>\\t%w0, %w1, %2"
4335 [(set_attr "type" "logic_reg,logic_imm")]
4338 (define_insn "*and<mode>3_compare0"
4339 [(set (reg:CC_NZ CC_REGNUM)
4341 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
4342 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
4344 (set (match_operand:GPI 0 "register_operand" "=r,r")
4345 (and:GPI (match_dup 1) (match_dup 2)))]
4348 ands\\t%<w>0, %<w>1, %<w>2
4349 ands\\t%<w>0, %<w>1, %2"
4350 [(set_attr "type" "logics_reg,logics_imm")]
4353 ;; zero_extend version of above
4354 (define_insn "*andsi3_compare0_uxtw"
4355 [(set (reg:CC_NZ CC_REGNUM)
4357 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
4358 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
4360 (set (match_operand:DI 0 "register_operand" "=r,r")
4361 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
4364 ands\\t%w0, %w1, %w2
4365 ands\\t%w0, %w1, %2"
4366 [(set_attr "type" "logics_reg,logics_imm")]
4369 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
4370 [(set (reg:CC_NZ CC_REGNUM)
4373 (match_operand:GPI 1 "register_operand" "r")
4374 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4375 (match_operand:GPI 3 "register_operand" "r"))
4377 (set (match_operand:GPI 0 "register_operand" "=r")
4378 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
4380 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4381 [(set_attr "type" "logics_shift_imm")]
4384 ;; zero_extend version of above
4385 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4386 [(set (reg:CC_NZ CC_REGNUM)
4389 (match_operand:SI 1 "register_operand" "r")
4390 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4391 (match_operand:SI 3 "register_operand" "r"))
4393 (set (match_operand:DI 0 "register_operand" "=r")
4394 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
4397 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4398 [(set_attr "type" "logics_shift_imm")]
4401 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
4402 [(set (match_operand:GPI 0 "register_operand" "=r")
4403 (LOGICAL:GPI (SHIFT:GPI
4404 (match_operand:GPI 1 "register_operand" "r")
4405 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4406 (match_operand:GPI 3 "register_operand" "r")))]
4408 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4409 [(set_attr "type" "logic_shift_imm")]
4412 (define_insn "*<optab>_rol<mode>3"
4413 [(set (match_operand:GPI 0 "register_operand" "=r")
4414 (LOGICAL:GPI (rotate:GPI
4415 (match_operand:GPI 1 "register_operand" "r")
4416 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4417 (match_operand:GPI 3 "register_operand" "r")))]
4419 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
4420 [(set_attr "type" "logic_shift_imm")]
4423 ;; zero_extend versions of above
4424 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
4425 [(set (match_operand:DI 0 "register_operand" "=r")
4427 (LOGICAL:SI (SHIFT:SI
4428 (match_operand:SI 1 "register_operand" "r")
4429 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4430 (match_operand:SI 3 "register_operand" "r"))))]
4432 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4433 [(set_attr "type" "logic_shift_imm")]
4436 (define_insn "*<optab>_rolsi3_uxtw"
4437 [(set (match_operand:DI 0 "register_operand" "=r")
4439 (LOGICAL:SI (rotate:SI
4440 (match_operand:SI 1 "register_operand" "r")
4441 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4442 (match_operand:SI 3 "register_operand" "r"))))]
4444 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
4445 [(set_attr "type" "logic_shift_imm")]
4448 (define_insn "one_cmpl<mode>2"
4449 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4450 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
4455 [(set_attr "type" "logic_reg,neon_logic")
4456 (set_attr "arch" "*,simd")]
4459 (define_insn "*one_cmpl_zero_extend"
4460 [(set (match_operand:DI 0 "register_operand" "=r")
4462 (not:SI (match_operand:SI 1 "register_operand" "r"))))]
4465 [(set_attr "type" "logic_reg")]
4468 (define_insn "*one_cmpl_<optab><mode>2"
4469 [(set (match_operand:GPI 0 "register_operand" "=r")
4470 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
4471 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
4473 "mvn\\t%<w>0, %<w>1, <shift> %2"
4474 [(set_attr "type" "logic_shift_imm")]
4477 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
4479 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
4480 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4481 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
4482 (match_operand:GPI 2 "register_operand" "r,w")))]
4485 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
4486 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
4487 [(set_attr "type" "logic_reg,neon_logic")
4488 (set_attr "arch" "*,simd")]
4491 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
4492 [(set (match_operand:DI 0 "register_operand" "=r")
4494 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
4495 (match_operand:SI 2 "register_operand" "r"))))]
4497 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
4498 [(set_attr "type" "logic_reg")]
4501 (define_insn "*xor_one_cmplsidi3_ze"
4502 [(set (match_operand:DI 0 "register_operand" "=r")
4504 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
4505 (match_operand:SI 2 "register_operand" "r")))))]
4507 "eon\\t%w0, %w1, %w2"
4508 [(set_attr "type" "logic_reg")]
4511 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
4512 ;; eon does not operate on SIMD registers so the vector variant must be split.
4513 (define_insn_and_split "*xor_one_cmpl<mode>3"
4514 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4515 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
4516 (match_operand:GPI 2 "register_operand" "r,w"))))]
4519 eon\\t%<w>0, %<w>1, %<w>2
4521 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
4522 [(set (match_operand:GPI 0 "register_operand" "=w")
4523 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
4524 (match_operand:GPI 2 "register_operand" "w")))
4525 (set (match_dup 0) (not:GPI (match_dup 0)))]
4527 [(set_attr "type" "logic_reg,multiple")
4528 (set_attr "arch" "*,simd")]
4531 (define_insn "*and_one_cmpl<mode>3_compare0"
4532 [(set (reg:CC_NZ CC_REGNUM)
4535 (match_operand:GPI 1 "register_operand" "r"))
4536 (match_operand:GPI 2 "register_operand" "r"))
4538 (set (match_operand:GPI 0 "register_operand" "=r")
4539 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
4541 "bics\\t%<w>0, %<w>2, %<w>1"
4542 [(set_attr "type" "logics_reg")]
4545 ;; zero_extend version of above
4546 (define_insn "*and_one_cmplsi3_compare0_uxtw"
4547 [(set (reg:CC_NZ CC_REGNUM)
4550 (match_operand:SI 1 "register_operand" "r"))
4551 (match_operand:SI 2 "register_operand" "r"))
4553 (set (match_operand:DI 0 "register_operand" "=r")
4554 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
4556 "bics\\t%w0, %w2, %w1"
4557 [(set_attr "type" "logics_reg")]
4560 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
4561 [(set (reg:CC_NZ CC_REGNUM)
4564 (match_operand:GPI 0 "register_operand" "r"))
4565 (match_operand:GPI 1 "register_operand" "r"))
4568 "bics\\t<w>zr, %<w>1, %<w>0"
4569 [(set_attr "type" "logics_reg")]
4572 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
4573 [(set (match_operand:GPI 0 "register_operand" "=r")
4574 (LOGICAL:GPI (not:GPI
4576 (match_operand:GPI 1 "register_operand" "r")
4577 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
4578 (match_operand:GPI 3 "register_operand" "r")))]
4580 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4581 [(set_attr "type" "logic_shift_imm")]
4584 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
4585 [(set (match_operand:GPI 0 "register_operand" "=r")
4588 (match_operand:GPI 1 "register_operand" "r")
4589 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4590 (match_operand:GPI 3 "register_operand" "r"))))]
4592 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4593 [(set_attr "type" "logic_shift_imm")]
4596 ;; Zero-extend version of the above.
4597 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
4598 [(set (match_operand:DI 0 "register_operand" "=r")
4602 (match_operand:SI 1 "register_operand" "r")
4603 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4604 (match_operand:SI 3 "register_operand" "r")))))]
4606 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4607 [(set_attr "type" "logic_shift_imm")]
4610 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
4611 [(set (reg:CC_NZ CC_REGNUM)
4615 (match_operand:GPI 1 "register_operand" "r")
4616 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
4617 (match_operand:GPI 3 "register_operand" "r"))
4619 (set (match_operand:GPI 0 "register_operand" "=r")
4622 (match_dup 1) (match_dup 2))) (match_dup 3)))]
4624 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4625 [(set_attr "type" "logics_shift_imm")]
4628 ;; zero_extend version of above
4629 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
4630 [(set (reg:CC_NZ CC_REGNUM)
4634 (match_operand:SI 1 "register_operand" "r")
4635 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
4636 (match_operand:SI 3 "register_operand" "r"))
4638 (set (match_operand:DI 0 "register_operand" "=r")
4639 (zero_extend:DI (and:SI
4641 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
4643 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4644 [(set_attr "type" "logics_shift_imm")]
4647 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
4648 [(set (reg:CC_NZ CC_REGNUM)
4652 (match_operand:GPI 0 "register_operand" "r")
4653 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
4654 (match_operand:GPI 2 "register_operand" "r"))
4657 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
4658 [(set_attr "type" "logics_shift_imm")]
4661 (define_insn "clz<mode>2"
4662 [(set (match_operand:GPI 0 "register_operand" "=r")
4663 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
4665 "clz\\t%<w>0, %<w>1"
4666 [(set_attr "type" "clz")]
4669 (define_expand "ffs<mode>2"
4670 [(match_operand:GPI 0 "register_operand")
4671 (match_operand:GPI 1 "register_operand")]
4674 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
4675 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4677 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
4678 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
4679 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
4684 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4691 (define_expand "popcount<mode>2"
4692 [(match_operand:GPI 0 "register_operand")
4693 (match_operand:GPI 1 "register_operand")]
4696 rtx v = gen_reg_rtx (V8QImode);
4697 rtx v1 = gen_reg_rtx (V8QImode);
4698 rtx in = operands[1];
4699 rtx out = operands[0];
4700 if(<MODE>mode == SImode)
4703 tmp = gen_reg_rtx (DImode);
4704 /* If we have SImode, zero extend to DImode, pop count does
4705 not change if we have extra zeros. */
4706 emit_insn (gen_zero_extendsidi2 (tmp, in));
4709 emit_move_insn (v, gen_lowpart (V8QImode, in));
4710 emit_insn (gen_popcountv8qi2 (v1, v));
4711 emit_insn (gen_aarch64_zero_extend<mode>_reduc_plus_v8qi (out, v1));
4715 (define_insn "clrsb<mode>2"
4716 [(set (match_operand:GPI 0 "register_operand" "=r")
4717 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
4719 "cls\\t%<w>0, %<w>1"
4720 [(set_attr "type" "clz")]
4723 (define_insn "rbit<mode>2"
4724 [(set (match_operand:GPI 0 "register_operand" "=r")
4725 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
4727 "rbit\\t%<w>0, %<w>1"
4728 [(set_attr "type" "rbit")]
4731 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4732 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4733 ;; expression and split after reload to enable scheduling them apart if
4736 (define_insn_and_split "ctz<mode>2"
4737 [(set (match_operand:GPI 0 "register_operand" "=r")
4738 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
4744 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
4745 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
4749 (define_insn "*and<mode>_compare0"
4750 [(set (reg:CC_NZ CC_REGNUM)
4752 (match_operand:SHORT 0 "register_operand" "r")
4755 "tst\\t%<w>0, <short_mask>"
4756 [(set_attr "type" "alus_imm")]
4759 (define_insn "*ands<GPI:mode>_compare0"
4760 [(set (reg:CC_NZ CC_REGNUM)
4762 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
4764 (set (match_operand:GPI 0 "register_operand" "=r")
4765 (zero_extend:GPI (match_dup 1)))]
4767 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
4768 [(set_attr "type" "alus_imm")]
4771 (define_insn "*and<mode>3nr_compare0"
4772 [(set (reg:CC_NZ CC_REGNUM)
4774 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
4775 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
4781 [(set_attr "type" "logics_reg,logics_imm")]
4785 [(set (reg:CC_NZ CC_REGNUM)
4787 (and:GPI (match_operand:GPI 0 "register_operand")
4788 (match_operand:GPI 1 "aarch64_mov_imm_operand"))
4790 (clobber (match_operand:SI 2 "register_operand"))]
4792 [(set (match_dup 2) (match_dup 1))
4793 (set (reg:CC_NZ CC_REGNUM)
4795 (and:GPI (match_dup 0)
4800 (define_insn "*and<mode>3nr_compare0_zextract"
4801 [(set (reg:CC_NZ CC_REGNUM)
4803 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
4804 (match_operand:GPI 1 "const_int_operand" "n")
4805 (match_operand:GPI 2 "const_int_operand" "n"))
4807 "INTVAL (operands[1]) > 0
4808 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
4809 <= GET_MODE_BITSIZE (<MODE>mode))
4810 && aarch64_bitmask_imm (
4811 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
4816 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
4817 return "tst\\t%<w>0, %1";
4819 [(set_attr "type" "logics_shift_imm")]
4822 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
4823 [(set (reg:CC_NZ CC_REGNUM)
4826 (match_operand:GPI 0 "register_operand" "r")
4827 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
4828 (match_operand:GPI 2 "register_operand" "r"))
4831 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
4832 [(set_attr "type" "logics_shift_imm")]
4836 [(set (reg:CC_NZ CC_REGNUM)
4839 (match_operand:GPI 0 "register_operand")
4840 (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
4841 (match_operand:GPI 2 "aarch64_mov_imm_operand"))
4843 (clobber (match_operand:SI 3 "register_operand"))]
4845 [(set (match_dup 3) (match_dup 2))
4846 (set (reg:CC_NZ CC_REGNUM)
4855 ;; -------------------------------------------------------------------
4857 ;; -------------------------------------------------------------------
4859 (define_expand "<optab><mode>3"
4860 [(set (match_operand:GPI 0 "register_operand")
4861 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
4862 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4865 if (CONST_INT_P (operands[2]))
4867 operands[2] = GEN_INT (INTVAL (operands[2])
4868 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4870 if (operands[2] == const0_rtx)
4872 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4879 (define_expand "ashl<mode>3"
4880 [(set (match_operand:SHORT 0 "register_operand")
4881 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
4882 (match_operand:QI 2 "const_int_operand")))]
4885 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
4887 if (operands[2] == const0_rtx)
4889 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4895 (define_expand "rotr<mode>3"
4896 [(set (match_operand:GPI 0 "register_operand")
4897 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4898 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4901 if (CONST_INT_P (operands[2]))
4903 operands[2] = GEN_INT (INTVAL (operands[2])
4904 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4906 if (operands[2] == const0_rtx)
4908 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4915 (define_expand "rotl<mode>3"
4916 [(set (match_operand:GPI 0 "register_operand")
4917 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4918 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4921 /* (SZ - cnt) % SZ == -cnt % SZ */
4922 if (CONST_INT_P (operands[2]))
4924 operands[2] = GEN_INT ((-INTVAL (operands[2]))
4925 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4926 if (operands[2] == const0_rtx)
4928 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4933 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4938 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4939 ;; they truncate the shift/rotate amount by the size of the registers they
4940 ;; operate on: 32 for W-regs, 64 for X-regs. This allows us to optimise away
4941 ;; such redundant masking instructions. GCC can do that automatically when
4942 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4943 ;; because some of the SISD shift alternatives don't perform this truncations.
4944 ;; So this pattern exists to catch such cases.
4946 (define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
4947 [(set (match_operand:GPI 0 "register_operand" "=r")
4949 (match_operand:GPI 1 "register_operand" "r")
4950 (match_operator 4 "subreg_lowpart_operator"
4951 [(and:GPI (match_operand:GPI 2 "register_operand" "r")
4952 (match_operand 3 "const_int_operand" "n"))])))]
4953 "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
4954 "<shift>\t%<w>0, %<w>1, %<w>2"
4955 [(set_attr "type" "shift_reg")]
4958 (define_insn_and_split "*aarch64_<optab>_reg_<mode>3_neg_mask2"
4959 [(set (match_operand:GPI 0 "register_operand" "=&r")
4961 (match_operand:GPI 1 "register_operand" "r")
4962 (match_operator 4 "subreg_lowpart_operator"
4963 [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
4964 (match_operand 3 "const_int_operand" "n")))])))]
4965 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
4970 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4971 : lowpart_subreg (SImode, operands[0], <MODE>mode));
4972 emit_insn (gen_negsi2 (tmp, operands[2]));
4974 rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
4975 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
4976 SUBREG_BYTE (operands[4]));
4977 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
4982 (define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask"
4983 [(set (match_operand:GPI 0 "register_operand" "=&r")
4985 (match_operand:GPI 1 "register_operand" "r")
4986 (minus:QI (match_operand 2 "const_int_operand" "n")
4987 (match_operator 5 "subreg_lowpart_operator"
4988 [(and:SI (match_operand:SI 3 "register_operand" "r")
4989 (match_operand 4 "const_int_operand" "n"))]))))]
4990 "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
4991 && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
4996 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4999 emit_insn (gen_negsi2 (tmp, operands[3]));
5001 rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
5002 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
5003 SUBREG_BYTE (operands[5]));
5005 emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
5010 (define_insn "*aarch64_<optab>_reg_di3_mask2"
5011 [(set (match_operand:DI 0 "register_operand" "=r")
5013 (match_operand:DI 1 "register_operand" "r")
5014 (match_operator 4 "subreg_lowpart_operator"
5015 [(and:SI (match_operand:SI 2 "register_operand" "r")
5016 (match_operand 3 "const_int_operand" "n"))])))]
5017 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)"
5020 xop[0] = operands[0];
5021 xop[1] = operands[1];
5022 xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
5023 output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
5026 [(set_attr "type" "shift_reg")]
5029 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>3"
5030 [(set (match_operand:GPI 0 "register_operand" "=&r")
5032 (match_operand:GPI 1 "register_operand" "r")
5033 (minus:QI (match_operand 2 "const_int_operand" "n")
5034 (match_operand:QI 3 "register_operand" "r"))))]
5035 "INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
5040 rtx subreg_tmp = gen_lowpart (SImode, operands[3]);
5042 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5043 : gen_lowpart (SImode, operands[0]));
5045 emit_insn (gen_negsi2 (tmp, subreg_tmp));
5047 rtx and_op = gen_rtx_AND (SImode, tmp,
5048 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1));
5050 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
5052 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp2));
5055 [(set_attr "length" "8")]
5058 ;; Logical left shift using SISD or Integer instruction
5059 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
5060 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
5062 (match_operand:GPI 1 "register_operand" "r,r,w,w")
5063 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
5066 lsl\t%<w>0, %<w>1, %2
5067 lsl\t%<w>0, %<w>1, %<w>2
5068 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5069 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
5070 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")
5071 (set_attr "arch" "*,*,simd,simd")]
5074 ;; Logical right shift using SISD or Integer instruction
5075 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
5076 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
5078 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
5079 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>"
5080 "Us<cmode>,r,Us<cmode_simd>,w,0")))]
5083 lsr\t%<w>0, %<w>1, %2
5084 lsr\t%<w>0, %<w>1, %<w>2
5085 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5088 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5089 (set_attr "arch" "*,*,simd,simd,simd")]
5093 [(set (match_operand:DI 0 "aarch64_simd_register")
5095 (match_operand:DI 1 "aarch64_simd_register")
5096 (match_operand:QI 2 "aarch64_simd_register")))]
5097 "TARGET_SIMD && reload_completed"
5099 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5101 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
5103 operands[3] = gen_lowpart (QImode, operands[0]);
5108 [(set (match_operand:SI 0 "aarch64_simd_register")
5110 (match_operand:SI 1 "aarch64_simd_register")
5111 (match_operand:QI 2 "aarch64_simd_register")))]
5112 "TARGET_SIMD && reload_completed"
5114 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5116 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
5118 operands[3] = gen_lowpart (QImode, operands[0]);
5122 ;; Arithmetic right shift using SISD or Integer instruction
5123 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
5124 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
5126 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
5127 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di"
5128 "Us<cmode>,r,Us<cmode_simd>,w,0")))]
5131 asr\t%<w>0, %<w>1, %2
5132 asr\t%<w>0, %<w>1, %<w>2
5133 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5136 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5137 (set_attr "arch" "*,*,simd,simd,simd")]
5141 [(set (match_operand:DI 0 "aarch64_simd_register")
5143 (match_operand:DI 1 "aarch64_simd_register")
5144 (match_operand:QI 2 "aarch64_simd_register")))]
5145 "TARGET_SIMD && reload_completed"
5147 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5149 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
5151 operands[3] = gen_lowpart (QImode, operands[0]);
5156 [(set (match_operand:SI 0 "aarch64_simd_register")
5158 (match_operand:SI 1 "aarch64_simd_register")
5159 (match_operand:QI 2 "aarch64_simd_register")))]
5160 "TARGET_SIMD && reload_completed"
5162 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5164 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
5166 operands[3] = gen_lowpart (QImode, operands[0]);
5170 (define_insn "*aarch64_sisd_ushl"
5171 [(set (match_operand:DI 0 "register_operand" "=w")
5172 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
5173 (match_operand:QI 2 "register_operand" "w")]
5176 "ushl\t%d0, %d1, %d2"
5177 [(set_attr "type" "neon_shift_reg")]
5180 (define_insn "*aarch64_ushl_2s"
5181 [(set (match_operand:SI 0 "register_operand" "=w")
5182 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
5183 (match_operand:QI 2 "register_operand" "w")]
5186 "ushl\t%0.2s, %1.2s, %2.2s"
5187 [(set_attr "type" "neon_shift_reg")]
5190 (define_insn "*aarch64_sisd_sshl"
5191 [(set (match_operand:DI 0 "register_operand" "=w")
5192 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
5193 (match_operand:QI 2 "register_operand" "w")]
5196 "sshl\t%d0, %d1, %d2"
5197 [(set_attr "type" "neon_shift_reg")]
5200 (define_insn "*aarch64_sshl_2s"
5201 [(set (match_operand:SI 0 "register_operand" "=w")
5202 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
5203 (match_operand:QI 2 "register_operand" "w")]
5206 "sshl\t%0.2s, %1.2s, %2.2s"
5207 [(set_attr "type" "neon_shift_reg")]
5210 (define_insn "*aarch64_sisd_neg_qi"
5211 [(set (match_operand:QI 0 "register_operand" "=w")
5212 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
5216 [(set_attr "type" "neon_neg")]
5220 (define_insn "*ror<mode>3_insn"
5221 [(set (match_operand:GPI 0 "register_operand" "=r,r")
5223 (match_operand:GPI 1 "register_operand" "r,r")
5224 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
5227 ror\\t%<w>0, %<w>1, %2
5228 ror\\t%<w>0, %<w>1, %<w>2"
5229 [(set_attr "type" "rotate_imm,shift_reg")]
5232 ;; zero_extend version of above
5233 (define_insn "*<optab>si3_insn_uxtw"
5234 [(set (match_operand:DI 0 "register_operand" "=r,r")
5235 (zero_extend:DI (SHIFT:SI
5236 (match_operand:SI 1 "register_operand" "r,r")
5237 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
5240 <shift>\\t%w0, %w1, %2
5241 <shift>\\t%w0, %w1, %w2"
5242 [(set_attr "type" "bfx,shift_reg")]
5245 (define_insn "*<optab><mode>3_insn"
5246 [(set (match_operand:SHORT 0 "register_operand" "=r")
5247 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
5248 (match_operand 2 "const_int_operand" "n")))]
5249 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
5251 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5252 return "<bfshift>\t%w0, %w1, %2, %3";
5254 [(set_attr "type" "bfx")]
5257 (define_insn "*extr<mode>5_insn"
5258 [(set (match_operand:GPI 0 "register_operand" "=r")
5259 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5260 (match_operand 3 "const_int_operand" "n"))
5261 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
5262 (match_operand 4 "const_int_operand" "n"))))]
5263 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5264 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
5265 "extr\\t%<w>0, %<w>1, %<w>2, %4"
5266 [(set_attr "type" "rotate_imm")]
5269 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5270 ;; so we have to match both orderings.
5271 (define_insn "*extr<mode>5_insn_alt"
5272 [(set (match_operand:GPI 0 "register_operand" "=r")
5273 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
5274 (match_operand 4 "const_int_operand" "n"))
5275 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5276 (match_operand 3 "const_int_operand" "n"))))]
5277 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
5278 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
5279 == GET_MODE_BITSIZE (<MODE>mode))"
5280 "extr\\t%<w>0, %<w>1, %<w>2, %4"
5281 [(set_attr "type" "rotate_imm")]
5284 ;; zero_extend version of the above
5285 (define_insn "*extrsi5_insn_uxtw"
5286 [(set (match_operand:DI 0 "register_operand" "=r")
5288 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
5289 (match_operand 3 "const_int_operand" "n"))
5290 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
5291 (match_operand 4 "const_int_operand" "n")))))]
5292 "UINTVAL (operands[3]) < 32 &&
5293 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
5294 "extr\\t%w0, %w1, %w2, %4"
5295 [(set_attr "type" "rotate_imm")]
5298 (define_insn "*extrsi5_insn_uxtw_alt"
5299 [(set (match_operand:DI 0 "register_operand" "=r")
5301 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
5302 (match_operand 4 "const_int_operand" "n"))
5303 (ashift:SI (match_operand:SI 1 "register_operand" "r")
5304 (match_operand 3 "const_int_operand" "n")))))]
5305 "UINTVAL (operands[3]) < 32 &&
5306 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
5307 "extr\\t%w0, %w1, %w2, %4"
5308 [(set_attr "type" "rotate_imm")]
5311 (define_insn "*ror<mode>3_insn"
5312 [(set (match_operand:GPI 0 "register_operand" "=r")
5313 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
5314 (match_operand 2 "const_int_operand" "n")))]
5315 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
5317 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5318 return "ror\\t%<w>0, %<w>1, %3";
5320 [(set_attr "type" "rotate_imm")]
5323 ;; zero_extend version of the above
5324 (define_insn "*rorsi3_insn_uxtw"
5325 [(set (match_operand:DI 0 "register_operand" "=r")
5327 (rotate:SI (match_operand:SI 1 "register_operand" "r")
5328 (match_operand 2 "const_int_operand" "n"))))]
5329 "UINTVAL (operands[2]) < 32"
5331 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
5332 return "ror\\t%w0, %w1, %3";
5334 [(set_attr "type" "rotate_imm")]
5337 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
5338 [(set (match_operand:GPI 0 "register_operand" "=r")
5340 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
5341 (match_operand 2 "const_int_operand" "n"))))]
5342 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5344 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5345 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5347 [(set_attr "type" "bfx")]
5350 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
5351 [(set (match_operand:GPI 0 "register_operand" "=r")
5353 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
5354 (match_operand 2 "const_int_operand" "n"))))]
5355 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5357 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5358 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5360 [(set_attr "type" "bfx")]
5363 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
5364 [(set (match_operand:GPI 0 "register_operand" "=r")
5366 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
5367 (match_operand 2 "const_int_operand" "n"))))]
5368 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5370 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5371 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5373 [(set_attr "type" "bfx")]
5376 ;; -------------------------------------------------------------------
5378 ;; -------------------------------------------------------------------
5380 (define_expand "<optab>"
5381 [(set (match_operand:DI 0 "register_operand")
5382 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
5384 "aarch64_simd_shift_imm_offset_di")
5385 (match_operand 3 "aarch64_simd_shift_imm_di")))]
5388 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5389 1, GET_MODE_BITSIZE (DImode) - 1))
5395 (define_insn "*<optab><mode>"
5396 [(set (match_operand:GPI 0 "register_operand" "=r")
5397 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
5399 "aarch64_simd_shift_imm_offset_<mode>" "n")
5401 "aarch64_simd_shift_imm_<mode>" "n")))]
5402 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5403 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
5404 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
5405 [(set_attr "type" "bfx")]
5408 ;; When the bit position and width add up to 32 we can use a W-reg LSR
5409 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
5411 [(set (match_operand:DI 0 "register_operand")
5412 (zero_extract:DI (match_operand:DI 1 "register_operand")
5414 "aarch64_simd_shift_imm_offset_di")
5416 "aarch64_simd_shift_imm_di")))]
5417 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
5418 GET_MODE_BITSIZE (DImode) - 1)
5419 && (INTVAL (operands[2]) + INTVAL (operands[3]))
5420 == GET_MODE_BITSIZE (SImode)"
5422 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
5424 operands[4] = gen_lowpart (SImode, operands[1]);
5428 ;; Bitfield Insert (insv)
5429 (define_expand "insv<mode>"
5430 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
5431 (match_operand 1 "const_int_operand")
5432 (match_operand 2 "const_int_operand"))
5433 (match_operand:GPI 3 "general_operand"))]
5436 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
5437 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
5438 rtx value = operands[3];
5440 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
5443 if (CONST_INT_P (value))
5445 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
5447 /* Prefer AND/OR for inserting all zeros or all ones. */
5448 if ((UINTVAL (value) & mask) == 0
5449 || (UINTVAL (value) & mask) == mask)
5452 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
5453 if (width == 16 && (pos % 16) == 0)
5456 operands[3] = force_reg (<MODE>mode, value);
5459 (define_insn "*insv_reg<mode>"
5460 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5461 (match_operand 1 "const_int_operand" "n")
5462 (match_operand 2 "const_int_operand" "n"))
5463 (match_operand:GPI 3 "register_operand" "r"))]
5464 "!(UINTVAL (operands[1]) == 0
5465 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
5466 > GET_MODE_BITSIZE (<MODE>mode)))"
5467 "bfi\\t%<w>0, %<w>3, %2, %1"
5468 [(set_attr "type" "bfm")]
5471 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
5472 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5473 (match_operand 1 "const_int_operand" "n")
5474 (match_operand 2 "const_int_operand" "n"))
5475 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
5476 "UINTVAL (operands[1]) <= <ALLX:sizen>"
5477 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
5478 [(set_attr "type" "bfm")]
5481 ;; Match a bfi instruction where the shift of OP3 means that we are
5482 ;; actually copying the least significant bits of OP3 into OP0 by way
5483 ;; of the AND masks and the IOR instruction. A similar instruction
5484 ;; with the two parts of the IOR swapped around was never triggered
5485 ;; in a bootstrap build and test of GCC so it was not included.
5487 (define_insn "*aarch64_bfi<GPI:mode>5_shift"
5488 [(set (match_operand:GPI 0 "register_operand" "=r")
5489 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5490 (match_operand:GPI 2 "const_int_operand" "n"))
5491 (and:GPI (ashift:GPI
5492 (match_operand:GPI 3 "register_operand" "r")
5493 (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n"))
5494 (match_operand:GPI 5 "const_int_operand" "n"))))]
5495 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]),
5496 UINTVAL (operands[4]),
5497 UINTVAL(operands[5]))"
5498 "bfi\t%<GPI:w>0, %<GPI:w>3, %4, %P5"
5499 [(set_attr "type" "bfm")]
5502 (define_insn "*aarch64_bfi<GPI:mode>5_shift_alt"
5503 [(set (match_operand:GPI 0 "register_operand" "=r")
5504 (ior:GPI (and:GPI (ashift:GPI
5505 (match_operand:GPI 1 "register_operand" "r")
5506 (match_operand:GPI 2 "aarch64_simd_shift_imm_<mode>" "n"))
5507 (match_operand:GPI 3 "const_int_operand" "n"))
5508 (and:GPI (match_operand:GPI 4 "register_operand" "0")
5509 (match_operand:GPI 5 "const_int_operand" "n"))))]
5510 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[5]),
5511 UINTVAL (operands[2]),
5512 UINTVAL(operands[3]))"
5513 "bfi\t%<GPI:w>0, %<GPI:w>1, %2, %P3"
5514 [(set_attr "type" "bfm")]
5517 ;; Like *aarch64_bfi<GPI:mode>5_shift but with no and of the ashift because
5518 ;; the shift is large enough to remove the need for an AND instruction.
5520 (define_insn "*aarch64_bfi<GPI:mode>4_noand"
5521 [(set (match_operand:GPI 0 "register_operand" "=r")
5522 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5523 (match_operand:GPI 2 "const_int_operand" "n"))
5525 (match_operand:GPI 3 "register_operand" "r")
5526 (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n"))))]
5527 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]),
5528 UINTVAL (operands[4]),
5529 HOST_WIDE_INT_M1U << UINTVAL (operands[4]) )"
5531 operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[4]));
5532 return "bfi\t%<GPI:w>0, %<GPI:w>3, %4, %5";
5534 [(set_attr "type" "bfm")]
5537 (define_insn "*aarch64_bfi<GPI:mode>4_noand_alt"
5538 [(set (match_operand:GPI 0 "register_operand" "=r")
5539 (ior:GPI (ashift:GPI
5540 (match_operand:GPI 1 "register_operand" "r")
5541 (match_operand:GPI 2 "aarch64_simd_shift_imm_<mode>" "n"))
5542 (and:GPI (match_operand:GPI 3 "register_operand" "0")
5543 (match_operand:GPI 4 "const_int_operand" "n"))))]
5544 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[4]),
5545 UINTVAL (operands[2]),
5546 HOST_WIDE_INT_M1U << UINTVAL (operands[2]) )"
5548 operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[2]));
5549 return "bfi\t%<GPI:w>0, %<GPI:w>1, %2, %5";
5551 [(set_attr "type" "bfm")]
5554 ;; Like *aarch64_bfi<GPI:mode>5_shift but with no shifting, we are just
5555 ;; copying the least significant bits of OP3 to OP0. We need two versions
5556 ;; of the instruction to handle different checks on the constant values.
5558 (define_insn "*aarch64_bfi<GPI:mode>4_noshift"
5559 [(set (match_operand:GPI 0 "register_operand" "=r")
5560 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5561 (match_operand:GPI 2 "const_int_operand" "n"))
5562 (and:GPI (match_operand:GPI 3 "register_operand" "r")
5563 (match_operand:GPI 4 "const_int_operand" "n"))))]
5564 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]), 0,
5565 UINTVAL (operands[4]))"
5566 "bfi\t%<GPI:w>0, %<GPI:w>3, 0, %P4"
5567 [(set_attr "type" "bfm")]
5570 (define_insn "*aarch64_bfi<GPI:mode>4_noshift_alt"
5571 [(set (match_operand:GPI 0 "register_operand" "=r")
5572 (ior:GPI (and:GPI (match_operand:GPI 3 "register_operand" "r")
5573 (match_operand:GPI 4 "const_int_operand" "n"))
5574 (and:GPI (match_operand:GPI 1 "register_operand" "0")
5575 (match_operand:GPI 2 "const_int_operand" "n"))))]
5576 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]), 0,
5577 UINTVAL (operands[4]))"
5578 "bfi\t%<GPI:w>0, %<GPI:w>3, 0, %P4"
5579 [(set_attr "type" "bfm")]
5582 (define_insn "*extr_insv_lower_reg<mode>"
5583 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5584 (match_operand 1 "const_int_operand" "n")
5586 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
5588 (match_operand 3 "const_int_operand" "n")))]
5589 "!(UINTVAL (operands[1]) == 0
5590 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
5591 > GET_MODE_BITSIZE (<MODE>mode)))"
5592 "bfxil\\t%<w>0, %<w>2, %3, %1"
5593 [(set_attr "type" "bfm")]
5596 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
5597 [(set (match_operand:GPI 0 "register_operand" "=r")
5598 (ashift:GPI (ANY_EXTEND:GPI
5599 (match_operand:ALLX 1 "register_operand" "r"))
5600 (match_operand 2 "const_int_operand" "n")))]
5601 "UINTVAL (operands[2]) < <GPI:sizen>"
5603 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
5604 ? GEN_INT (<ALLX:sizen>)
5605 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
5606 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5608 [(set_attr "type" "bfx")]
5611 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
5613 (define_insn "*andim_ashift<mode>_bfiz"
5614 [(set (match_operand:GPI 0 "register_operand" "=r")
5615 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5616 (match_operand 2 "const_int_operand" "n"))
5617 (match_operand 3 "const_int_operand" "n")))]
5618 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
5619 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
5620 [(set_attr "type" "bfx")]
5623 ;; Match sbfiz pattern in a shift left + shift right operation.
5625 (define_insn "*ashift<mode>_extv_bfiz"
5626 [(set (match_operand:GPI 0 "register_operand" "=r")
5627 (ashift:GPI (sign_extract:GPI (match_operand:GPI 1 "register_operand" "r")
5628 (match_operand 2 "aarch64_simd_shift_imm_offset_<mode>" "n")
5630 (match_operand 3 "aarch64_simd_shift_imm_<mode>" "n")))]
5631 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5632 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
5633 "sbfiz\\t%<w>0, %<w>1, %3, %2"
5634 [(set_attr "type" "bfx")]
5637 (define_insn "*ashiftsi_extvdi_bfiz"
5638 [(set (match_operand:SI 0 "register_operand" "=r")
5640 (match_operator:SI 4 "subreg_lowpart_operator"
5642 (match_operand:DI 1 "register_operand" "r")
5643 (match_operand 2 "aarch64_simd_shift_imm_offset_si")
5645 (match_operand 3 "aarch64_simd_shift_imm_si")))]
5646 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5647 1, GET_MODE_BITSIZE (SImode) - 1)"
5648 "sbfiz\\t%w0, %w1, %3, %2"
5649 [(set_attr "type" "bfx")]
5652 ;; When the bit position and width of the equivalent extraction add up to 32
5653 ;; we can use a W-reg LSL instruction taking advantage of the implicit
5654 ;; zero-extension of the X-reg.
5656 [(set (match_operand:DI 0 "register_operand")
5657 (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
5658 (match_operand 2 "const_int_operand"))
5659 (match_operand 3 "const_int_operand")))]
5660 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
5661 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
5662 == GET_MODE_BITSIZE (SImode)"
5664 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
5666 operands[4] = gen_lowpart (SImode, operands[1]);
5670 (define_insn "bswap<mode>2"
5671 [(set (match_operand:GPI 0 "register_operand" "=r")
5672 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
5674 "rev\\t%<w>0, %<w>1"
5675 [(set_attr "type" "rev")]
5678 (define_insn "bswaphi2"
5679 [(set (match_operand:HI 0 "register_operand" "=r")
5680 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
5683 [(set_attr "type" "rev")]
5686 (define_insn "*aarch64_bfxil<mode>"
5687 [(set (match_operand:GPI 0 "register_operand" "=r,r")
5688 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "r,0")
5689 (match_operand:GPI 3 "const_int_operand" "n, Ulc"))
5690 (and:GPI (match_operand:GPI 2 "register_operand" "0,r")
5691 (match_operand:GPI 4 "const_int_operand" "Ulc, n"))))]
5692 "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
5693 && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
5694 || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
5696 switch (which_alternative)
5699 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
5700 return "bfxil\\t%<w>0, %<w>1, 0, %3";
5702 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
5703 return "bfxil\\t%<w>0, %<w>2, 0, %3";
5708 [(set_attr "type" "bfm")]
5711 ; Zero-extended version of above (aarch64_bfxil)
5712 (define_insn "*aarch64_bfxilsi_uxtw"
5713 [(set (match_operand:DI 0 "register_operand" "=r,r")
5714 (zero_extend:DI (ior:SI (and:SI (match_operand:SI 1 "register_operand"
5716 (match_operand:SI 3 "const_int_operand" "n, Ulc"))
5717 (and:SI (match_operand:SI 2 "register_operand" "0,r")
5718 (match_operand:SI 4 "const_int_operand" "Ulc, n")))))]
5719 "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
5720 && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
5721 || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
5723 switch (which_alternative)
5726 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
5727 return "bfxil\\t%0, %1, 0, %3";
5729 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
5730 return "bfxil\\t%0, %2, 0, %3";
5735 [(set_attr "type" "bfm")]
5738 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
5739 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
5740 ;; each valid permutation.
5742 (define_insn "rev16<mode>2"
5743 [(set (match_operand:GPI 0 "register_operand" "=r")
5744 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5746 (match_operand:GPI 3 "const_int_operand" "n"))
5747 (and:GPI (lshiftrt:GPI (match_dup 1)
5749 (match_operand:GPI 2 "const_int_operand" "n"))))]
5750 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
5751 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
5752 "rev16\\t%<w>0, %<w>1"
5753 [(set_attr "type" "rev")]
5756 (define_insn "rev16<mode>2_alt"
5757 [(set (match_operand:GPI 0 "register_operand" "=r")
5758 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
5760 (match_operand:GPI 2 "const_int_operand" "n"))
5761 (and:GPI (ashift:GPI (match_dup 1)
5763 (match_operand:GPI 3 "const_int_operand" "n"))))]
5764 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
5765 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
5766 "rev16\\t%<w>0, %<w>1"
5767 [(set_attr "type" "rev")]
5770 ;; zero_extend version of above
5771 (define_insn "*bswapsi2_uxtw"
5772 [(set (match_operand:DI 0 "register_operand" "=r")
5773 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
5776 [(set_attr "type" "rev")]
5779 ;; -------------------------------------------------------------------
5780 ;; Floating-point intrinsics
5781 ;; -------------------------------------------------------------------
5783 ;; frint floating-point round to integral standard patterns.
5784 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
5786 (define_insn "<frint_pattern><mode>2"
5787 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5788 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
5791 "frint<frint_suffix>\\t%<s>0, %<s>1"
5792 [(set_attr "type" "f_rint<stype>")]
5795 ;; frcvt floating-point round to integer and convert standard patterns.
5796 ;; Expands to lbtrunc, lceil, lfloor, lround.
5797 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
5798 [(set (match_operand:GPI 0 "register_operand" "=r")
5800 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
5803 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
5804 [(set_attr "type" "f_cvtf2i")]
5807 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
5808 [(set (match_operand:GPI 0 "register_operand" "=r")
5811 (match_operand:GPF 1 "register_operand" "w")
5812 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
5814 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
5815 GET_MODE_BITSIZE (<GPI:MODE>mode))"
5817 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
5819 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
5820 output_asm_insn (buf, operands);
5823 [(set_attr "type" "f_cvtf2i")]
5826 ;; fma - expand fma into patterns with the accumulator operand first since
5827 ;; reusing the accumulator results in better register allocation.
5828 ;; The register allocator considers copy preferences in operand order,
5829 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
5831 (define_expand "fma<mode>4"
5832 [(set (match_operand:GPF_F16 0 "register_operand")
5833 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand")
5834 (match_operand:GPF_F16 2 "register_operand")
5835 (match_operand:GPF_F16 3 "register_operand")))]
5839 (define_insn "*aarch64_fma<mode>4"
5840 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5841 (fma:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w")
5842 (match_operand:GPF_F16 3 "register_operand" "w")
5843 (match_operand:GPF_F16 1 "register_operand" "w")))]
5845 "fmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5846 [(set_attr "type" "fmac<stype>")]
5849 (define_expand "fnma<mode>4"
5850 [(set (match_operand:GPF_F16 0 "register_operand")
5852 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand"))
5853 (match_operand:GPF_F16 2 "register_operand")
5854 (match_operand:GPF_F16 3 "register_operand")))]
5858 (define_insn "*aarch64_fnma<mode>4"
5859 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5861 (neg:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w"))
5862 (match_operand:GPF_F16 3 "register_operand" "w")
5863 (match_operand:GPF_F16 1 "register_operand" "w")))]
5865 "fmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
5866 [(set_attr "type" "fmac<stype>")]
5870 (define_expand "fms<mode>4"
5871 [(set (match_operand:GPF 0 "register_operand")
5872 (fma:GPF (match_operand:GPF 1 "register_operand")
5873 (match_operand:GPF 2 "register_operand")
5874 (neg:GPF (match_operand:GPF 3 "register_operand"))))]
5878 (define_insn "*aarch64_fms<mode>4"
5879 [(set (match_operand:GPF 0 "register_operand" "=w")
5880 (fma:GPF (match_operand:GPF 2 "register_operand" "w")
5881 (match_operand:GPF 3 "register_operand" "w")
5882 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
5884 "fnmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
5885 [(set_attr "type" "fmac<s>")]
5888 (define_expand "fnms<mode>4"
5889 [(set (match_operand:GPF 0 "register_operand")
5890 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand"))
5891 (match_operand:GPF 2 "register_operand")
5892 (neg:GPF (match_operand:GPF 3 "register_operand"))))]
5896 (define_insn "*aarch64_fnms<mode>4"
5897 [(set (match_operand:GPF 0 "register_operand" "=w")
5898 (fma:GPF (neg:GPF (match_operand:GPF 2 "register_operand" "w"))
5899 (match_operand:GPF 3 "register_operand" "w")
5900 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
5902 "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5903 [(set_attr "type" "fmac<s>")]
5906 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5907 (define_insn "*aarch64_fnmadd<mode>4"
5908 [(set (match_operand:GPF 0 "register_operand" "=w")
5909 (neg:GPF (fma:GPF (match_operand:GPF 2 "register_operand" "w")
5910 (match_operand:GPF 3 "register_operand" "w")
5911 (match_operand:GPF 1 "register_operand" "w"))))]
5912 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5913 "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5914 [(set_attr "type" "fmac<s>")]
5917 ;; -------------------------------------------------------------------
5918 ;; Floating-point conversions
5919 ;; -------------------------------------------------------------------
5921 (define_insn "extendsfdf2"
5922 [(set (match_operand:DF 0 "register_operand" "=w")
5923 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
5926 [(set_attr "type" "f_cvt")]
5929 (define_insn "extendhfsf2"
5930 [(set (match_operand:SF 0 "register_operand" "=w")
5931 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
5934 [(set_attr "type" "f_cvt")]
5937 (define_insn "extendhfdf2"
5938 [(set (match_operand:DF 0 "register_operand" "=w")
5939 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
5942 [(set_attr "type" "f_cvt")]
5945 (define_insn "truncdfsf2"
5946 [(set (match_operand:SF 0 "register_operand" "=w")
5947 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
5950 [(set_attr "type" "f_cvt")]
5953 (define_insn "truncsfhf2"
5954 [(set (match_operand:HF 0 "register_operand" "=w")
5955 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
5958 [(set_attr "type" "f_cvt")]
5961 (define_insn "truncdfhf2"
5962 [(set (match_operand:HF 0 "register_operand" "=w")
5963 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
5966 [(set_attr "type" "f_cvt")]
5969 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5970 ;; and making r = w more expensive
5972 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>2"
5973 [(set (match_operand:GPI 0 "register_operand" "=w,?r")
5974 (FIXUORS:GPI (match_operand:<FCVT_TARGET> 1 "register_operand" "w,w")))]
5977 fcvtz<su>\t%<s>0, %<s>1
5978 fcvtz<su>\t%<w>0, %<s>1"
5979 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5982 ;; Convert HF -> SI or DI
5984 (define_insn "<optab>_trunchf<GPI:mode>2"
5985 [(set (match_operand:GPI 0 "register_operand" "=r")
5986 (FIXUORS:GPI (match_operand:HF 1 "register_operand" "w")))]
5988 "fcvtz<su>\t%<w>0, %h1"
5989 [(set_attr "type" "f_cvtf2i")]
5992 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
5993 ;; input in a fp register and output in a integer register
5995 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>2"
5996 [(set (match_operand:GPI 0 "register_operand" "=r")
5997 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand" "w")))]
5999 "fcvtz<su>\t%<w>0, %<fpw>1"
6000 [(set_attr "type" "f_cvtf2i")]
6003 (define_insn "*fix_to_zero_extend<mode>di2"
6004 [(set (match_operand:DI 0 "register_operand" "=r")
6007 (match_operand:GPF 1 "register_operand" "w"))))]
6009 "fcvtzu\t%w0, %<s>1"
6010 [(set_attr "type" "f_cvtf2i")]
6013 ;; Equal width integer to fp and multiply combine.
6014 (define_insn "*aarch64_<su_optab>cvtf<fcvt_target><GPF:mode>2_mult"
6015 [(set (match_operand:GPF 0 "register_operand" "=w,w")
6016 (mult:GPF (FLOATUORS:GPF
6017 (match_operand:<FCVT_TARGET> 1 "register_operand" "w,?r"))
6018 (match_operand:GPF 2 "aarch64_fp_pow2_recip" "Dt,Dt")))]
6021 operands[2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[2]));
6022 switch (which_alternative)
6025 return "<su_optab>cvtf\t%<GPF:s>0, %<s>1, #%2";
6027 return "<su_optab>cvtf\t%<GPF:s>0, %<w1>1, #%2";
6032 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6033 (set_attr "arch" "simd,fp")]
6036 ;; Unequal width integer to fp and multiply combine.
6037 (define_insn "*aarch64_<su_optab>cvtf<fcvt_iesize><GPF:mode>2_mult"
6038 [(set (match_operand:GPF 0 "register_operand" "=w")
6039 (mult:GPF (FLOATUORS:GPF
6040 (match_operand:<FCVT_IESIZE> 1 "register_operand" "r"))
6041 (match_operand:GPF 2 "aarch64_fp_pow2_recip" "Dt")))]
6044 operands[2] = GEN_INT (aarch64_fpconst_pow2_recip (operands[2]));
6045 return "<su_optab>cvtf\t%<GPF:s>0, %<w2>1, #%2";
6047 [(set_attr "type" "f_cvti2f")]
6050 ;; Equal width integer to fp conversion.
6051 (define_insn "<optab><fcvt_target><GPF:mode>2"
6052 [(set (match_operand:GPF 0 "register_operand" "=w,w")
6053 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,?r")))]
6056 <su_optab>cvtf\t%<GPF:s>0, %<s>1
6057 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
6058 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6059 (set_attr "arch" "simd,fp")]
6062 ;; Unequal width integer to fp conversions.
6063 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
6064 [(set (match_operand:GPF 0 "register_operand" "=w")
6065 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
6067 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
6068 [(set_attr "type" "f_cvti2f")]
6071 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
6072 ;; midend will arrange for an SImode conversion to HFmode to first go
6073 ;; through DFmode, then to HFmode. But first it will try converting
6074 ;; to DImode then down, which would match our DImode pattern below and
6075 ;; give very poor code-generation. So, we must provide our own emulation
6076 ;; of the mid-end logic.
6078 (define_insn "aarch64_fp16_<optab><mode>hf2"
6079 [(set (match_operand:HF 0 "register_operand" "=w")
6080 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
6082 "<su_optab>cvtf\t%h0, %<w>1"
6083 [(set_attr "type" "f_cvti2f")]
6086 (define_expand "<optab>sihf2"
6087 [(set (match_operand:HF 0 "register_operand")
6088 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
6091 if (TARGET_FP_F16INST)
6092 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
6095 rtx convert_target = gen_reg_rtx (DFmode);
6096 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
6097 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
6103 ;; For DImode there is no wide enough floating-point mode that we
6104 ;; can convert through natively (TFmode would work, but requires a library
6105 ;; call). However, we know that any value >= 65504 will be rounded
6106 ;; to infinity on conversion. This is well within the range of SImode, so
6108 ;; Saturate to SImode.
6109 ;; Convert from that to DFmode
6110 ;; Convert from that to HFmode (phew!).
6111 ;; Note that the saturation to SImode requires the SIMD extensions. If
6112 ;; we ever need to provide this pattern where the SIMD extensions are not
6113 ;; available, we would need a different approach.
6115 (define_expand "<optab>dihf2"
6116 [(set (match_operand:HF 0 "register_operand")
6117 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
6118 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
6120 if (TARGET_FP_F16INST)
6121 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
6124 rtx sat_target = gen_reg_rtx (SImode);
6125 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
6126 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
6133 ;; Convert between fixed-point and floating-point (scalar modes)
6135 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
6136 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
6137 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
6138 (match_operand:SI 2 "immediate_operand" "i, i")]
6142 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
6143 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
6144 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
6145 (set_attr "arch" "fp,simd")]
6148 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
6149 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
6150 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
6151 (match_operand:SI 2 "immediate_operand" "i, i")]
6155 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
6156 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
6157 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
6158 (set_attr "arch" "fp,simd")]
6161 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
6162 [(set (match_operand:GPI 0 "register_operand" "=r")
6163 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
6164 (match_operand:SI 2 "immediate_operand" "i")]
6167 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
6168 [(set_attr "type" "f_cvtf2i")]
6171 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
6172 [(set (match_operand:HF 0 "register_operand" "=w")
6173 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
6174 (match_operand:SI 2 "immediate_operand" "i")]
6177 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
6178 [(set_attr "type" "f_cvti2f")]
6181 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
6182 [(set (match_operand:HI 0 "register_operand" "=w")
6183 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
6184 (match_operand:SI 2 "immediate_operand" "i")]
6187 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
6188 [(set_attr "type" "neon_fp_to_int_s")]
6191 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
6192 [(set (match_operand:HF 0 "register_operand" "=w")
6193 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
6194 (match_operand:SI 2 "immediate_operand" "i")]
6197 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
6198 [(set_attr "type" "neon_int_to_fp_s")]
6201 ;; -------------------------------------------------------------------
6202 ;; Floating-point arithmetic
6203 ;; -------------------------------------------------------------------
6205 (define_insn "add<mode>3"
6206 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6208 (match_operand:GPF_F16 1 "register_operand" "w")
6209 (match_operand:GPF_F16 2 "register_operand" "w")))]
6211 "fadd\\t%<s>0, %<s>1, %<s>2"
6212 [(set_attr "type" "fadd<stype>")]
6215 (define_insn "sub<mode>3"
6216 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6218 (match_operand:GPF_F16 1 "register_operand" "w")
6219 (match_operand:GPF_F16 2 "register_operand" "w")))]
6221 "fsub\\t%<s>0, %<s>1, %<s>2"
6222 [(set_attr "type" "fadd<stype>")]
6225 (define_insn "mul<mode>3"
6226 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6228 (match_operand:GPF_F16 1 "register_operand" "w")
6229 (match_operand:GPF_F16 2 "register_operand" "w")))]
6231 "fmul\\t%<s>0, %<s>1, %<s>2"
6232 [(set_attr "type" "fmul<stype>")]
6235 (define_insn "*fnmul<mode>3"
6236 [(set (match_operand:GPF 0 "register_operand" "=w")
6238 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
6239 (match_operand:GPF 2 "register_operand" "w")))]
6240 "TARGET_FLOAT && !flag_rounding_math"
6241 "fnmul\\t%<s>0, %<s>1, %<s>2"
6242 [(set_attr "type" "fmul<s>")]
6245 (define_insn "*fnmul<mode>3"
6246 [(set (match_operand:GPF 0 "register_operand" "=w")
6248 (match_operand:GPF 1 "register_operand" "w")
6249 (match_operand:GPF 2 "register_operand" "w"))))]
6251 "fnmul\\t%<s>0, %<s>1, %<s>2"
6252 [(set_attr "type" "fmul<s>")]
6255 (define_expand "div<mode>3"
6256 [(set (match_operand:GPF_F16 0 "register_operand")
6257 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
6258 (match_operand:GPF_F16 2 "register_operand")))]
6261 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
6264 operands[1] = force_reg (<MODE>mode, operands[1]);
6267 (define_insn "*div<mode>3"
6268 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6269 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
6270 (match_operand:GPF_F16 2 "register_operand" "w")))]
6272 "fdiv\\t%<s>0, %<s>1, %<s>2"
6273 [(set_attr "type" "fdiv<stype>")]
6276 (define_insn "neg<mode>2"
6277 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6278 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6280 "fneg\\t%<s>0, %<s>1"
6281 [(set_attr "type" "ffarith<stype>")]
6284 (define_expand "sqrt<mode>2"
6285 [(set (match_operand:GPF_F16 0 "register_operand")
6286 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand")))]
6289 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
6293 (define_insn "*sqrt<mode>2"
6294 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6295 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6297 "fsqrt\\t%<s>0, %<s>1"
6298 [(set_attr "type" "fsqrt<stype>")]
6301 (define_insn "abs<mode>2"
6302 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6303 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6305 "fabs\\t%<s>0, %<s>1"
6306 [(set_attr "type" "ffarith<stype>")]
6309 ;; Given that smax/smin do not specify the result when either input is NaN,
6310 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
6313 (define_insn "smax<mode>3"
6314 [(set (match_operand:GPF 0 "register_operand" "=w")
6315 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
6316 (match_operand:GPF 2 "register_operand" "w")))]
6318 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
6319 [(set_attr "type" "f_minmax<s>")]
6322 (define_insn "smin<mode>3"
6323 [(set (match_operand:GPF 0 "register_operand" "=w")
6324 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
6325 (match_operand:GPF 2 "register_operand" "w")))]
6327 "fminnm\\t%<s>0, %<s>1, %<s>2"
6328 [(set_attr "type" "f_minmax<s>")]
6331 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
6332 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
6333 ;; which implement the IEEE fmax ()/fmin () functions.
6334 (define_insn "<maxmin_uns><mode>3"
6335 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6336 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
6337 (match_operand:GPF_F16 2 "register_operand" "w")]
6340 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
6341 [(set_attr "type" "f_minmax<stype>")]
6344 (define_expand "lrint<GPF:mode><GPI:mode>2"
6345 [(match_operand:GPI 0 "register_operand")
6346 (match_operand:GPF 1 "register_operand")]
6348 && ((GET_MODE_BITSIZE (<GPF:MODE>mode) <= LONG_TYPE_SIZE)
6349 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
6351 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
6352 emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1]));
6353 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt));
6358 ;; For copysign (x, y), we want to generate:
6360 ;; LDR d2, #(1 << 63)
6361 ;; BSL v2.8b, [y], [x]
6363 ;; or another, equivalent, sequence using one of BSL/BIT/BIF. Because
6364 ;; we expect these operations to nearly always operate on
6365 ;; floating-point values, we do not want the operation to be
6366 ;; simplified into a bit-field insert operation that operates on the
6367 ;; integer side, since typically that would involve three inter-bank
6368 ;; register copies. As we do not expect copysign to be followed by
6369 ;; other logical operations on the result, it seems preferable to keep
6370 ;; this as an unspec operation, rather than exposing the underlying
6371 ;; logic to the compiler.
6373 (define_expand "copysign<GPF:mode>3"
6374 [(match_operand:GPF 0 "register_operand")
6375 (match_operand:GPF 1 "register_operand")
6376 (match_operand:GPF 2 "register_operand")]
6377 "TARGET_FLOAT && TARGET_SIMD"
6379 rtx bitmask = gen_reg_rtx (<V_INT_EQUIV>mode);
6380 emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U
6381 << (GET_MODE_BITSIZE (<MODE>mode) - 1)));
6382 emit_insn (gen_copysign<mode>3_insn (operands[0], operands[1], operands[2],
6388 (define_insn "copysign<GPF:mode>3_insn"
6389 [(set (match_operand:GPF 0 "register_operand" "=w,w,w,r")
6390 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w,0,w,r")
6391 (match_operand:GPF 2 "register_operand" "w,w,0,0")
6392 (match_operand:<V_INT_EQUIV> 3 "register_operand" "0,w,w,X")]
6394 "TARGET_FLOAT && TARGET_SIMD"
6396 bsl\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>
6397 bit\\t%0.<Vbtype>, %2.<Vbtype>, %3.<Vbtype>
6398 bif\\t%0.<Vbtype>, %1.<Vbtype>, %3.<Vbtype>
6399 bfxil\\t%<w1>0, %<w1>1, #0, <sizem1>"
6400 [(set_attr "type" "neon_bsl<q>,neon_bsl<q>,neon_bsl<q>,bfm")]
6404 ;; For xorsign (x, y), we want to generate:
6407 ;; AND v3.8B, v1.8B, v2.8B
6408 ;; EOR v0.8B, v0.8B, v3.8B
6411 (define_expand "xorsign<mode>3"
6412 [(match_operand:GPF 0 "register_operand")
6413 (match_operand:GPF 1 "register_operand")
6414 (match_operand:GPF 2 "register_operand")]
6415 "TARGET_FLOAT && TARGET_SIMD"
6418 machine_mode imode = <V_INT_EQUIV>mode;
6419 rtx mask = gen_reg_rtx (imode);
6420 rtx op1x = gen_reg_rtx (imode);
6421 rtx op2x = gen_reg_rtx (imode);
6423 int bits = GET_MODE_BITSIZE (<MODE>mode) - 1;
6424 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
6427 emit_insn (gen_and<v_int_equiv>3 (op2x, mask,
6428 lowpart_subreg (imode, operands[2],
6430 emit_insn (gen_xor<v_int_equiv>3 (op1x,
6431 lowpart_subreg (imode, operands[1],
6434 emit_move_insn (operands[0],
6435 lowpart_subreg (<MODE>mode, op1x, imode));
6440 ;; -------------------------------------------------------------------
6442 ;; -------------------------------------------------------------------
6443 ;; Reload Scalar Floating point modes from constant pool.
6444 ;; The AArch64 port doesn't have __int128 constant move support.
6445 ;; The patterns need constraints due to TARGET_SECONDARY_RELOAD hook.
6446 (define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
6447 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
6448 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
6449 (clobber (match_operand:P 2 "register_operand" "=&r"))]
6452 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
6453 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
6458 ;; Reload Vector modes from constant pool.
6459 (define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
6460 [(set (match_operand:VALL 0 "register_operand" "=w")
6461 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
6462 (clobber (match_operand:P 2 "register_operand" "=&r"))]
6465 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
6466 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
6471 (define_expand "@aarch64_reload_mov<mode>"
6472 [(set (match_operand:TX 0 "register_operand" "=w")
6473 (match_operand:TX 1 "register_operand" "w"))
6474 (clobber (match_operand:DI 2 "register_operand" "=&r"))
6478 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
6479 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
6480 gen_aarch64_movtilow_tilow (op0, op1);
6481 gen_aarch64_movdi_tihigh (operands[2], op1);
6482 gen_aarch64_movtihigh_di (op0, operands[2]);
6487 ;; The following secondary reload helpers patterns are invoked
6488 ;; after or during reload as we don't want these patterns to start
6489 ;; kicking in during the combiner.
6491 (define_insn "@aarch64_movdi_<mode>low"
6492 [(set (match_operand:DI 0 "register_operand" "=r")
6493 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
6494 (const_int 64) (const_int 0)))]
6495 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6497 [(set_attr "type" "f_mrc")
6498 (set_attr "length" "4")
6501 (define_insn "@aarch64_movdi_<mode>high"
6502 [(set (match_operand:DI 0 "register_operand" "=r")
6503 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
6504 (const_int 64) (const_int 64)))]
6505 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6506 "fmov\\t%x0, %1.d[1]"
6507 [(set_attr "type" "f_mrc")
6508 (set_attr "length" "4")
6511 (define_insn "@aarch64_mov<mode>high_di"
6512 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
6513 (const_int 64) (const_int 64))
6514 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
6515 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6516 "fmov\\t%0.d[1], %x1"
6517 [(set_attr "type" "f_mcr")
6518 (set_attr "length" "4")
6521 (define_insn "@aarch64_mov<mode>low_di"
6522 [(set (match_operand:TX 0 "register_operand" "=w")
6523 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
6524 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6526 [(set_attr "type" "f_mcr")
6527 (set_attr "length" "4")
6530 (define_insn "aarch64_movtilow_tilow"
6531 [(set (match_operand:TI 0 "register_operand" "=w")
6533 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
6534 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6536 [(set_attr "type" "fmov")
6537 (set_attr "length" "4")
6540 ;; There is a deliberate reason why the parameters of high and lo_sum's
6541 ;; don't have modes for ADRP and ADD instructions. This is to allow high
6542 ;; and lo_sum's to be used with the labels defining the jump tables in
6545 (define_expand "add_losym"
6546 [(set (match_operand 0 "register_operand")
6547 (lo_sum (match_operand 1 "register_operand")
6548 (match_operand 2 "aarch64_valid_symref")))]
6551 machine_mode mode = GET_MODE (operands[0]);
6553 emit_insn ((mode == DImode
6555 : gen_add_losym_si) (operands[0],
6561 (define_insn "add_losym_<mode>"
6562 [(set (match_operand:P 0 "register_operand" "=r")
6563 (lo_sum:P (match_operand:P 1 "register_operand" "r")
6564 (match_operand 2 "aarch64_valid_symref" "S")))]
6566 "add\\t%<w>0, %<w>1, :lo12:%c2"
6567 [(set_attr "type" "alu_imm")]
6570 (define_insn "ldr_got_small_<mode>"
6571 [(set (match_operand:PTR 0 "register_operand" "=r")
6572 (unspec:PTR [(mem:PTR (lo_sum:PTR
6573 (match_operand:PTR 1 "register_operand" "r")
6574 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
6575 UNSPEC_GOTSMALLPIC))]
6577 "ldr\\t%<w>0, [%1, #:got_lo12:%c2]"
6578 [(set_attr "type" "load_<ldst_sz>")]
6581 (define_insn "ldr_got_small_sidi"
6582 [(set (match_operand:DI 0 "register_operand" "=r")
6584 (unspec:SI [(mem:SI (lo_sum:DI
6585 (match_operand:DI 1 "register_operand" "r")
6586 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
6587 UNSPEC_GOTSMALLPIC)))]
6589 "ldr\\t%w0, [%1, #:got_lo12:%c2]"
6590 [(set_attr "type" "load_4")]
6593 (define_insn "ldr_got_small_28k_<mode>"
6594 [(set (match_operand:PTR 0 "register_operand" "=r")
6595 (unspec:PTR [(mem:PTR (lo_sum:PTR
6596 (match_operand:PTR 1 "register_operand" "r")
6597 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
6598 UNSPEC_GOTSMALLPIC28K))]
6600 "ldr\\t%<w>0, [%1, #:<got_modifier>:%c2]"
6601 [(set_attr "type" "load_<ldst_sz>")]
6604 (define_insn "ldr_got_small_28k_sidi"
6605 [(set (match_operand:DI 0 "register_operand" "=r")
6607 (unspec:SI [(mem:SI (lo_sum:DI
6608 (match_operand:DI 1 "register_operand" "r")
6609 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
6610 UNSPEC_GOTSMALLPIC28K)))]
6612 "ldr\\t%w0, [%1, #:gotpage_lo14:%c2]"
6613 [(set_attr "type" "load_4")]
6616 (define_insn "@ldr_got_tiny_<mode>"
6617 [(set (match_operand:PTR 0 "register_operand" "=r")
6618 (unspec:PTR [(match_operand:PTR 1 "aarch64_valid_symref" "S")]
6619 UNSPEC_GOTTINYPIC))]
6622 [(set_attr "type" "load_<ldst_sz>")]
6625 (define_insn "ldr_got_tiny_sidi"
6626 [(set (match_operand:DI 0 "register_operand" "=r")
6628 (unspec:SI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
6629 UNSPEC_GOTTINYPIC)))]
6632 [(set_attr "type" "load_4")]
6635 (define_insn "aarch64_load_tp_hard"
6636 [(set (match_operand:DI 0 "register_operand" "=r")
6637 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
6639 "mrs\\t%0, tpidr_el0"
6640 [(set_attr "type" "mrs")]
6643 ;; The TLS ABI specifically requires that the compiler does not schedule
6644 ;; instructions in the TLS stubs, in order to enable linker relaxation.
6645 ;; Therefore we treat the stubs as an atomic sequence.
6646 (define_expand "tlsgd_small_<mode>"
6647 [(parallel [(set (match_operand:PTR 0 "register_operand")
6648 (call (mem:DI (match_dup 2)) (const_int 1)))
6649 (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
6650 (unspec:DI [(match_operand 1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
6651 (clobber (reg:DI LR_REGNUM))])]
6654 operands[2] = aarch64_tls_get_addr ();
6657 (define_insn "*tlsgd_small_<mode>"
6658 [(set (match_operand:PTR 0 "register_operand" "")
6659 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
6660 (unspec:DI [(const_int 0)] UNSPEC_CALLEE_ABI)
6661 (unspec:DI [(match_operand 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
6662 (clobber (reg:DI LR_REGNUM))
6665 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
6666 [(set_attr "type" "call")
6667 (set_attr "length" "16")])
6669 (define_insn "tlsie_small_<mode>"
6670 [(set (match_operand:PTR 0 "register_operand" "=r")
6671 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
6672 UNSPEC_GOTSMALLTLS))]
6674 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
6675 [(set_attr "type" "load_4")
6676 (set_attr "length" "8")]
6679 (define_insn "tlsie_small_sidi"
6680 [(set (match_operand:DI 0 "register_operand" "=r")
6682 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
6683 UNSPEC_GOTSMALLTLS)))]
6685 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
6686 [(set_attr "type" "load_4")
6687 (set_attr "length" "8")]
6690 (define_insn "tlsie_tiny_<mode>"
6691 [(set (match_operand:PTR 0 "register_operand" "=&r")
6692 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
6693 (match_operand:PTR 2 "register_operand" "r")]
6694 UNSPEC_GOTTINYTLS))]
6696 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
6697 [(set_attr "type" "multiple")
6698 (set_attr "length" "8")]
6701 (define_insn "tlsie_tiny_sidi"
6702 [(set (match_operand:DI 0 "register_operand" "=&r")
6704 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
6705 (match_operand:DI 2 "register_operand" "r")
6707 UNSPEC_GOTTINYTLS)))]
6709 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
6710 [(set_attr "type" "multiple")
6711 (set_attr "length" "8")]
6714 (define_insn "tlsle12_<mode>"
6715 [(set (match_operand:P 0 "register_operand" "=r")
6716 (unspec:P [(match_operand:P 1 "register_operand" "r")
6717 (match_operand 2 "aarch64_tls_le_symref" "S")]
6720 "add\\t%<w>0, %<w>1, #%L2";
6721 [(set_attr "type" "alu_sreg")
6722 (set_attr "length" "4")]
6725 (define_insn "tlsle24_<mode>"
6726 [(set (match_operand:P 0 "register_operand" "=r")
6727 (unspec:P [(match_operand:P 1 "register_operand" "r")
6728 (match_operand 2 "aarch64_tls_le_symref" "S")]
6731 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
6732 [(set_attr "type" "multiple")
6733 (set_attr "length" "8")]
6736 (define_insn "tlsle32_<mode>"
6737 [(set (match_operand:P 0 "register_operand" "=r")
6738 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
6741 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
6742 [(set_attr "type" "multiple")
6743 (set_attr "length" "8")]
6746 (define_insn "tlsle48_<mode>"
6747 [(set (match_operand:P 0 "register_operand" "=r")
6748 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
6751 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
6752 [(set_attr "type" "multiple")
6753 (set_attr "length" "12")]
6756 (define_expand "tlsdesc_small_<mode>"
6757 [(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
6762 rtx abi = gen_int_mode (aarch64_tlsdesc_abi_id (), DImode);
6764 = emit_call_insn (gen_tlsdesc_small_sve_<mode> (operands[0], abi));
6765 RTL_CONST_CALL_P (call) = 1;
6768 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
6773 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
6775 (define_insn "tlsdesc_small_advsimd_<mode>"
6776 [(set (reg:PTR R0_REGNUM)
6777 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
6779 (clobber (reg:DI LR_REGNUM))
6780 (clobber (reg:CC CC_REGNUM))
6781 (clobber (match_scratch:DI 1 "=r"))
6782 (use (reg:DI FP_REGNUM))]
6783 "TARGET_TLS_DESC && !TARGET_SVE"
6784 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
6785 [(set_attr "type" "call")
6786 (set_attr "length" "16")])
6788 ;; For SVE, model tlsdesc calls as normal calls, with the callee ABI
6789 ;; describing the extra call-preserved guarantees. This would work
6790 ;; for non-SVE too, but avoiding a call is probably better if we can.
6791 (define_insn "tlsdesc_small_sve_<mode>"
6792 [(set (reg:PTR R0_REGNUM)
6793 (call (mem:DI (unspec:PTR
6794 [(match_operand 0 "aarch64_valid_symref")]
6797 (unspec:DI [(match_operand:DI 1 "const_int_operand")] UNSPEC_CALLEE_ABI)
6798 (clobber (reg:DI LR_REGNUM))
6799 (clobber (match_scratch:DI 2 "=r"))]
6800 "TARGET_TLS_DESC && TARGET_SVE"
6801 "adrp\\tx0, %A0\;ldr\\t%<w>2, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%2"
6802 [(set_attr "type" "call")
6803 (set_attr "length" "16")])
6805 (define_insn "stack_tie"
6806 [(set (mem:BLK (scratch))
6807 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
6808 (match_operand:DI 1 "register_operand" "rk")]
6812 [(set_attr "length" "0")]
6815 (define_insn "aarch64_fjcvtzs"
6816 [(set (match_operand:SI 0 "register_operand" "=r")
6817 (unspec:SI [(match_operand:DF 1 "register_operand" "w")]
6819 (clobber (reg:CC CC_REGNUM))]
6821 "fjcvtzs\\t%w0, %d1"
6822 [(set_attr "type" "f_cvtf2i")]
6825 ;; Pointer authentication patterns are always provided. In architecture
6826 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
6827 ;; This lets the user write portable software which authenticates pointers
6828 ;; when run on something which implements ARMv8.3-A, and which runs
6829 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
6832 ;; Signing/Authenticating R30 using SP as the salt.
6834 (define_insn "<pauth_mnem_prefix>sp"
6835 [(set (reg:DI R30_REGNUM)
6836 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
6838 "hint\t<pauth_hint_num> // <pauth_mnem_prefix>sp";
6841 ;; Signing/Authenticating X17 using X16 as the salt.
6843 (define_insn "<pauth_mnem_prefix>1716"
6844 [(set (reg:DI R17_REGNUM)
6845 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
6847 "hint\t<pauth_hint_num> // <pauth_mnem_prefix>1716";
6850 ;; Stripping the signature in R30.
6852 (define_insn "xpaclri"
6853 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
6855 "hint\t7 // xpaclri"
6858 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6859 ;; all of memory. This blocks insns from being moved across this point.
6861 (define_insn "blockage"
6862 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
6865 [(set_attr "length" "0")
6866 (set_attr "type" "block")]
6869 (define_insn "probe_stack_range"
6870 [(set (match_operand:DI 0 "register_operand" "=rk")
6871 (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
6872 (match_operand:DI 2 "register_operand" "r")]
6873 UNSPECV_PROBE_STACK_RANGE))]
6876 return aarch64_output_probe_stack_range (operands[0], operands[2]);
6878 [(set_attr "length" "32")]
6881 ;; This instruction is used to generate the stack clash stack adjustment and
6882 ;; probing loop. We can't change the control flow during prologue and epilogue
6883 ;; code generation. So we must emit a volatile unspec and expand it later on.
6885 (define_insn "@probe_sve_stack_clash_<mode>"
6886 [(set (match_operand:P 0 "register_operand" "=rk")
6887 (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
6888 (match_operand:P 2 "register_operand" "r")
6889 (match_operand:P 3 "const_int_operand" "n")
6890 (match_operand:P 4 "aarch64_plus_immediate" "L")]
6891 UNSPECV_PROBE_STACK_RANGE))]
6894 return aarch64_output_probe_sve_stack_clash (operands[0], operands[2],
6895 operands[3], operands[4]);
6897 [(set_attr "length" "28")]
6900 ;; Named pattern for expanding thread pointer reference.
6901 (define_expand "get_thread_pointerdi"
6902 [(match_operand:DI 0 "register_operand")]
6905 rtx tmp = aarch64_load_tp (operands[0]);
6906 if (tmp != operands[0])
6907 emit_move_insn (operands[0], tmp);
6911 ;; Defined for -mstack-protector-guard=sysreg, which goes through this
6912 ;; pattern rather than stack_protect_combined_set. Our implementation
6913 ;; of the latter can handle both.
6914 (define_expand "stack_protect_set"
6915 [(match_operand 0 "memory_operand")
6916 (match_operand 1 "")]
6919 emit_insn (gen_stack_protect_combined_set (operands[0], operands[1]));
6923 (define_expand "stack_protect_combined_set"
6924 [(match_operand 0 "memory_operand")
6925 (match_operand 1 "")]
6928 machine_mode mode = GET_MODE (operands[0]);
6929 operands[1] = aarch64_stack_protect_canary_mem (mode, operands[1],
6930 AARCH64_SALT_SSP_SET);
6931 emit_insn ((mode == DImode
6932 ? gen_stack_protect_set_di
6933 : gen_stack_protect_set_si) (operands[0], operands[1]));
6937 ;; Operand 1 is either AARCH64_SALT_SSP_SET or AARCH64_SALT_SSP_TEST.
6938 (define_insn "reg_stack_protect_address_<mode>"
6939 [(set (match_operand:PTR 0 "register_operand" "=r")
6940 (unspec:PTR [(match_operand 1 "const_int_operand")]
6941 UNSPEC_SSP_SYSREG))]
6942 "aarch64_stack_protector_guard != SSP_GLOBAL"
6945 snprintf (buf, 150, "mrs\\t%%<w>0, %s",
6946 aarch64_stack_protector_guard_reg_str);
6947 output_asm_insn (buf, operands);
6950 [(set_attr "type" "mrs")])
6952 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
6953 ;; canary value does not live beyond the life of this sequence.
6954 (define_insn "stack_protect_set_<mode>"
6955 [(set (match_operand:PTR 0 "memory_operand" "=m")
6956 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
6958 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
6960 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2, 0"
6961 [(set_attr "length" "12")
6962 (set_attr "type" "multiple")])
6964 ;; Defined for -mstack-protector-guard=sysreg, which goes through this
6965 ;; pattern rather than stack_protect_combined_test. Our implementation
6966 ;; of the latter can handle both.
6967 (define_expand "stack_protect_test"
6968 [(match_operand 0 "memory_operand")
6969 (match_operand 1 "")
6973 emit_insn (gen_stack_protect_combined_test (operands[0], operands[1],
6978 (define_expand "stack_protect_combined_test"
6979 [(match_operand 0 "memory_operand")
6980 (match_operand 1 "")
6984 machine_mode mode = GET_MODE (operands[0]);
6985 operands[1] = aarch64_stack_protect_canary_mem (mode, operands[1],
6986 AARCH64_SALT_SSP_TEST);
6987 emit_insn ((mode == DImode
6988 ? gen_stack_protect_test_di
6989 : gen_stack_protect_test_si) (operands[0], operands[1]));
6991 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
6992 emit_jump_insn (gen_condjump (gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx),
6993 cc_reg, operands[2]));
6997 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
6998 ;; canary value does not live beyond the end of this sequence.
6999 (define_insn "stack_protect_test_<mode>"
7000 [(set (reg:CC CC_REGNUM)
7001 (unspec:CC [(match_operand:PTR 0 "memory_operand" "m")
7002 (match_operand:PTR 1 "memory_operand" "m")]
7004 (clobber (match_scratch:PTR 2 "=&r"))
7005 (clobber (match_scratch:PTR 3 "=&r"))]
7007 "ldr\t%<w>2, %0\;ldr\t%<w>3, %1\;subs\t%<w>2, %<w>2, %<w>3\;mov\t%3, 0"
7008 [(set_attr "length" "16")
7009 (set_attr "type" "multiple")])
7011 ;; Write into the Floating-point Status or Control Register.
7012 (define_insn "@aarch64_set_<fpscr_name><GPI:mode>"
7013 [(unspec_volatile [(match_operand:GPI 0 "register_operand" "r")] SET_FPSCR)]
7015 "msr\\t<fpscr_name>, %0"
7016 [(set_attr "type" "mrs")])
7018 ;; Read into the Floating-point Status or Control Register.
7019 (define_insn "@aarch64_get_<fpscr_name><GPI:mode>"
7020 [(set (match_operand:GPI 0 "register_operand" "=r")
7021 (unspec_volatile:GPI [(const_int 0)] GET_FPSCR))]
7023 "mrs\\t%0, <fpscr_name>"
7024 [(set_attr "type" "mrs")])
7026 ;; Define the subtract-one-and-jump insns so loop.c
7027 ;; knows what to generate.
7028 (define_expand "doloop_end"
7029 [(use (match_operand 0 "" "")) ; loop pseudo
7030 (use (match_operand 1 "" ""))] ; label
7031 "optimize > 0 && flag_modulo_sched"
7040 /* Currently SMS relies on the do-loop pattern to recognize loops
7041 where (1) the control part consists of all insns defining and/or
7042 using a certain 'count' register and (2) the loop count can be
7043 adjusted by modifying this register prior to the loop.
7044 ??? The possible introduction of a new block to initialize the
7045 new IV can potentially affect branch optimizations. */
7047 if (GET_MODE (operands[0]) != DImode)
7051 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
7053 cmp = XVECEXP (PATTERN (insn), 0, 0);
7054 cc_reg = SET_DEST (cmp);
7055 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
7056 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
7057 emit_jump_insn (gen_rtx_SET (pc_rtx,
7058 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
7063 ;; Track speculation through conditional branches. We assume that
7064 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
7065 (define_insn "speculation_tracker"
7066 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7067 (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
7068 UNSPEC_SPECULATION_TRACKER))]
7071 operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7072 output_asm_insn ("csel\\t%1, %1, xzr, %m0", operands);
7075 [(set_attr "type" "csel")]
7078 ;; Like speculation_tracker, but track the inverse condition.
7079 (define_insn "speculation_tracker_rev"
7080 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7081 (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
7082 UNSPEC_SPECULATION_TRACKER_REV))]
7085 operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7086 output_asm_insn ("csel\\t%1, %1, xzr, %M0", operands);
7089 [(set_attr "type" "csel")]
7092 ;; BTI <target> instructions
7093 (define_insn "bti_noarg"
7094 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_NOARG)]
7097 [(set_attr "type" "no_insn")]
7100 (define_insn "bti_c"
7101 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_C)]
7104 [(set_attr "type" "no_insn")]
7107 (define_insn "bti_j"
7108 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_J)]
7111 [(set_attr "type" "no_insn")]
7114 (define_insn "bti_jc"
7115 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_JC)]
7117 "hint\t38 // bti jc"
7118 [(set_attr "type" "no_insn")]
7121 ;; Hard speculation barrier.
7122 (define_insn "speculation_barrier"
7123 [(unspec_volatile [(const_int 0)] UNSPECV_SPECULATION_BARRIER)]
7126 [(set_attr "length" "8")
7127 (set_attr "type" "block")
7128 (set_attr "speculation_barrier" "true")]
7131 ;; Support for __builtin_speculation_safe_value when we have speculation
7132 ;; tracking enabled. Use the speculation tracker to decide whether to
7133 ;; copy operand 1 to the target, or to copy the fail value (operand 2).
7134 (define_expand "@despeculate_copy<ALLI_TI:mode>"
7135 [(set (match_operand:ALLI_TI 0 "register_operand")
7136 (unspec_volatile:ALLI_TI
7137 [(match_operand:ALLI_TI 1 "register_operand")
7138 (match_operand:ALLI_TI 2 "aarch64_reg_or_zero")
7139 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7140 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7144 if (operands[2] == const0_rtx)
7147 if (<MODE>mode == TImode)
7148 tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7150 tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
7152 emit_insn (gen_despeculate_simple<mode> (operands[0], operands[1],
7160 ;; Patterns to match despeculate_copy<mode>. Note that "hint 0x14" is the
7161 ;; encoding for CSDB, but will work in older versions of the assembler.
7162 (define_insn "*despeculate_copy<ALLI:mode>_insn"
7163 [(set (match_operand:ALLI 0 "register_operand" "=r")
7164 (unspec_volatile:ALLI
7165 [(match_operand:ALLI 1 "register_operand" "r")
7166 (match_operand:ALLI 2 "aarch64_reg_or_zero" "rZ")
7167 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7168 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7171 operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7172 output_asm_insn ("cmp\\t%3, #0\;csel\\t%<w>0, %<w>1, %<w>2, ne\;hint\t0x14 // csdb",
7176 [(set_attr "length" "12")
7177 (set_attr "type" "block")
7178 (set_attr "speculation_barrier" "true")]
7181 ;; Pattern to match despeculate_copyti
7182 (define_insn "*despeculate_copyti_insn"
7183 [(set (match_operand:TI 0 "register_operand" "=r")
7185 [(match_operand:TI 1 "register_operand" "r")
7186 (match_operand:TI 2 "aarch64_reg_or_zero" "rZ")
7187 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7188 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7191 operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7193 ("cmp\\t%3, #0\;csel\\t%0, %1, %2, ne\;csel\\t%H0, %H1, %H2, ne\;hint\t0x14 // csdb",
7197 [(set_attr "length" "16")
7198 (set_attr "type" "block")
7199 (set_attr "speculation_barrier" "true")]
7202 (define_insn "despeculate_simple<ALLI:mode>"
7203 [(set (match_operand:ALLI 0 "register_operand" "=r")
7204 (unspec_volatile:ALLI
7205 [(match_operand:ALLI 1 "register_operand" "r")
7206 (use (match_operand:ALLI 2 "register_operand" ""))]
7207 UNSPECV_SPECULATION_BARRIER))]
7209 "and\\t%<w>0, %<w>1, %<w>2\;hint\t0x14 // csdb"
7210 [(set_attr "type" "block")
7211 (set_attr "length" "8")
7212 (set_attr "speculation_barrier" "true")]
7215 (define_insn "despeculate_simpleti"
7216 [(set (match_operand:TI 0 "register_operand" "=r")
7218 [(match_operand:TI 1 "register_operand" "r")
7219 (use (match_operand:DI 2 "register_operand" ""))]
7220 UNSPECV_SPECULATION_BARRIER))]
7222 "and\\t%0, %1, %2\;and\\t%H0, %H1, %2\;hint\t0x14 // csdb"
7223 [(set_attr "type" "block")
7224 (set_attr "length" "12")
7225 (set_attr "speculation_barrier" "true")]
7228 (define_insn "aarch64_<frintnzs_op><mode>"
7229 [(set (match_operand:VSFDF 0 "register_operand" "=w")
7230 (unspec:VSFDF [(match_operand:VSFDF 1 "register_operand" "w")]
7232 "TARGET_FRINT && TARGET_FLOAT
7233 && !(VECTOR_MODE_P (<MODE>mode) && !TARGET_SIMD)"
7234 "<frintnzs_op>\\t%<v>0<Vmtype>, %<v>1<Vmtype>"
7235 [(set_attr "type" "f_rint<stype>")]
7238 ;; Transactional Memory Extension (TME) instructions.
7240 (define_insn "tstart"
7241 [(set (match_operand:DI 0 "register_operand" "=r")
7242 (unspec_volatile:DI [(const_int 0)] UNSPECV_TSTART))
7243 (clobber (mem:BLK (scratch)))]
7246 [(set_attr "type" "tme")]
7249 (define_insn "ttest"
7250 [(set (match_operand:DI 0 "register_operand" "=r")
7251 (unspec_volatile:DI [(const_int 0)] UNSPEC_TTEST))
7252 (clobber (mem:BLK (scratch)))]
7255 [(set_attr "type" "tme")]
7258 (define_insn "tcommit"
7259 [(unspec_volatile:BLK [(const_int 0)] UNSPECV_TCOMMIT)
7260 (clobber (mem:BLK (scratch)))]
7263 [(set_attr "type" "tme")]
7266 (define_insn "tcancel"
7267 [(unspec_volatile:BLK
7268 [(match_operand 0 "const_int_operand" "n")] UNSPECV_TCANCEL)
7269 (clobber (mem:BLK (scratch)))]
7270 "TARGET_TME && (UINTVAL (operands[0]) <= 65535)"
7272 [(set_attr "type" "tme")]
7275 (define_insn "aarch64_rndr"
7276 [(set (match_operand:DI 0 "register_operand" "=r")
7277 (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDR))
7278 (set (reg:CC_Z CC_REGNUM)
7279 (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDR))]
7282 [(set_attr "type" "mrs")]
7285 (define_insn "aarch64_rndrrs"
7286 [(set (match_operand:DI 0 "register_operand" "=r")
7287 (unspec_volatile:DI [(const_int 0)] UNSPEC_RNDRRS))
7288 (set (reg:CC_Z CC_REGNUM)
7289 (unspec_volatile:CC_Z [(const_int 0)] UNSPEC_RNDRRS))]
7292 [(set_attr "type" "mrs")]
7295 ;; Memory Tagging Extension (MTE) instructions.
7298 [(set (match_operand:DI 0 "register_operand" "=rk")
7300 (and:DI (match_operand:DI 1 "register_operand" "rk")
7301 (const_int -1080863910568919041)) ;; 0xf0ff...
7302 (ashift:DI (unspec:QI [(match_operand:DI 2 "register_operand" "r")]
7307 [(set_attr "type" "memtag")]
7311 [(set (match_operand:DI 0 "register_operand" "=r")
7314 (and:QI (lshiftrt:DI
7315 (match_operand:DI 1 "register_operand" "rk")
7316 (const_int 56)) (const_int 15)))
7317 (match_operand:DI 2 "register_operand" "r")))]
7320 [(set_attr "type" "memtag")]
7324 [(set (match_operand:DI 0 "register_operand" "=rk")
7326 (and:DI (plus:DI (match_operand:DI 1 "register_operand" "rk")
7327 (match_operand:DI 2 "aarch64_granule16_uimm6" "i"))
7328 (const_int -1080863910568919041)) ;; 0xf0ff...
7331 [(and:QI (lshiftrt:DI (match_dup 1) (const_int 56)) (const_int 15))
7332 (match_operand:QI 3 "aarch64_memtag_tag_offset" "i")]
7336 "addg\\t%0, %1, #%2, #%3"
7337 [(set_attr "type" "memtag")]
7341 [(set (match_operand:DI 0 "register_operand" "=r")
7343 (and:DI (match_operand:DI 1 "register_operand" "rk")
7344 (const_int 72057594037927935)) ;; 0x00ff...
7345 (and:DI (match_operand:DI 2 "register_operand" "rk")
7346 (const_int 72057594037927935))))] ;; 0x00ff...
7349 [(set_attr "type" "memtag")]
7352 ;; LDG will use the 16-byte aligned value of the address.
7354 [(set (match_operand:DI 0 "register_operand" "+r")
7356 (and:DI (match_dup 0) (const_int -1080863910568919041)) ;; 0xf0ff...
7359 [(and:DI (plus:DI (match_operand:DI 1 "register_operand" "rk")
7360 (match_operand:DI 2 "aarch64_granule16_simm9" "i"))
7361 (const_int -16))] UNSPEC_TAG_SPACE))
7364 "ldg\\t%0, [%1, #%2]"
7365 [(set_attr "type" "memtag")]
7368 ;; STG doesn't align the address but aborts with alignment fault
7369 ;; when the address is not 16-byte aligned.
7371 [(set (mem:QI (unspec:DI
7372 [(plus:DI (match_operand:DI 1 "register_operand" "rk")
7373 (match_operand:DI 2 "aarch64_granule16_simm9" "i"))]
7375 (and:QI (lshiftrt:DI (match_operand:DI 0 "register_operand" "rk")
7376 (const_int 56)) (const_int 15)))]
7378 "stg\\t%0, [%1, #%2]"
7379 [(set_attr "type" "memtag")]
7383 (include "aarch64-simd.md")
7385 ;; Atomic Operations
7386 (include "atomics.md")
7388 ;; ldp/stp peephole patterns
7389 (include "aarch64-ldpstp.md")
7392 (include "aarch64-sve.md")
7395 (include "aarch64-sve2.md")