1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2019 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/>.
88 (LAST_SAVED_REGNUM 63)
92 ;; Defined only to make the DWARF description simpler.
110 ;; Scratch register used by stack clash protection to calculate
111 ;; SVE CFA offsets during probing.
112 (STACK_CLASH_SVE_CFA_REGNUM 11)
113 ;; Scratch registers for prologue/epilogue use.
116 ;; A couple of call-clobbered registers that we need to reserve when
117 ;; tracking speculation this is not ABI, so is subject to change.
118 (SPECULATION_SCRATCH_REGNUM 14)
119 (SPECULATION_TRACKER_REGNUM 15)
120 ;; Scratch registers used in frame layout.
127 (define_c_enum "unspec" [
155 UNSPEC_GOTSMALLPIC28K
236 UNSPEC_SPECULATION_TRACKER
240 (define_c_enum "unspecv" [
241 UNSPECV_EH_RETURN ; Represent EH_RETURN
242 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
243 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
244 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
245 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
246 UNSPECV_BLOCKAGE ; Represent a blockage
247 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
248 UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
249 UNSPECV_BTI_NOARG ; Represent BTI.
250 UNSPECV_BTI_C ; Represent BTI c.
251 UNSPECV_BTI_J ; Represent BTI j.
252 UNSPECV_BTI_JC ; Represent BTI jc.
256 ;; If further include files are added the defintion of MD_INCLUDES
259 (include "constraints.md")
260 (include "predicates.md")
261 (include "iterators.md")
263 ;; -------------------------------------------------------------------
264 ;; Instruction types and attributes
265 ;; -------------------------------------------------------------------
267 ; The "type" attribute is included here from AArch32 backend to be able
268 ; to share pipeline descriptions.
269 (include "../arm/types.md")
271 ;; It is important to set the fp or simd attributes to yes when a pattern
272 ;; alternative uses the FP or SIMD register files, usually signified by use of
273 ;; the 'w' constraint. This will ensure that the alternative will be
274 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
275 ;; architecture extensions. If all the alternatives in a pattern use the
276 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
279 ;; Attributes of the architecture required to support the instruction (or
280 ;; alternative). This attribute is used to compute attribute "enabled", use type
281 ;; "any" to enable an alternative in all cases.
283 (define_enum "arches" [ any rcpc8_4 fp simd sve fp16])
285 (define_enum_attr "arch" "arches" (const_string "any"))
287 ;; [For compatibility with Arm in pipeline models]
288 ;; Attribute that specifies whether or not the instruction touches fp
290 ;; Note that this attribute is not used anywhere in either the arm or aarch64
291 ;; backends except in the scheduling description for xgene1. In that
292 ;; scheduling description this attribute is used to subclass the load_4 and
294 (define_attr "fp" "no,yes"
296 (eq_attr "arch" "fp")
298 (const_string "no")))
300 (define_attr "arch_enabled" "no,yes"
303 (eq_attr "arch" "any")
305 (and (eq_attr "arch" "rcpc8_4")
306 (match_test "AARCH64_ISA_RCPC8_4"))
308 (and (eq_attr "arch" "fp")
309 (match_test "TARGET_FLOAT"))
311 (and (eq_attr "arch" "simd")
312 (match_test "TARGET_SIMD"))
314 (and (eq_attr "arch" "fp16")
315 (match_test "TARGET_FP_F16INST"))
317 (and (eq_attr "arch" "sve")
318 (match_test "TARGET_SVE")))
320 (const_string "no")))
322 ;; Attribute that controls whether an alternative is enabled or not.
323 ;; Currently it is only used to disable alternatives which touch fp or simd
324 ;; registers when -mgeneral-regs-only is specified or to require a special
325 ;; architecture support.
326 (define_attr "enabled" "no,yes" (attr "arch_enabled"))
328 ;; Attribute that specifies whether we are dealing with a branch to a
329 ;; label that is far away, i.e. further away than the maximum/minimum
330 ;; representable in a signed 21-bits number.
333 (define_attr "far_branch" "" (const_int 0))
335 ;; Attribute that specifies whether the alternative uses MOVPRFX.
336 (define_attr "movprfx" "no,yes" (const_string "no"))
338 (define_attr "length" ""
339 (cond [(eq_attr "movprfx" "yes")
343 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
344 ;; no predicated insns.
345 (define_attr "predicated" "yes,no" (const_string "no"))
347 ;; Set to true on an insn that requires the speculation tracking state to be
348 ;; in the tracking register before the insn issues. Otherwise the compiler
349 ;; may chose to hold the tracking state encoded in SP.
350 (define_attr "speculation_barrier" "true,false" (const_string "false"))
352 ;; -------------------------------------------------------------------
353 ;; Pipeline descriptions and scheduling
354 ;; -------------------------------------------------------------------
357 (include "aarch64-tune.md")
360 (include "../arm/cortex-a53.md")
361 (include "../arm/cortex-a57.md")
362 (include "../arm/exynos-m1.md")
363 (include "falkor.md")
364 (include "saphira.md")
365 (include "thunderx.md")
366 (include "../arm/xgene1.md")
367 (include "thunderx2t99.md")
368 (include "tsv110.md")
370 ;; -------------------------------------------------------------------
371 ;; Jumps and other miscellaneous insns
372 ;; -------------------------------------------------------------------
374 (define_insn "indirect_jump"
375 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
378 [(set_attr "type" "branch")]
382 [(set (pc) (label_ref (match_operand 0 "" "")))]
385 [(set_attr "type" "branch")]
388 (define_expand "cbranch<mode>4"
389 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
390 [(match_operand:GPI 1 "register_operand" "")
391 (match_operand:GPI 2 "aarch64_plus_operand" "")])
392 (label_ref (match_operand 3 "" ""))
396 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
398 operands[2] = const0_rtx;
402 (define_expand "cbranch<mode>4"
403 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
404 [(match_operand:GPF 1 "register_operand" "")
405 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
406 (label_ref (match_operand 3 "" ""))
410 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
412 operands[2] = const0_rtx;
416 (define_expand "cbranchcc4"
417 [(set (pc) (if_then_else
418 (match_operator 0 "aarch64_comparison_operator"
419 [(match_operand 1 "cc_register" "")
420 (match_operand 2 "const0_operand")])
421 (label_ref (match_operand 3 "" ""))
426 (define_insn "ccmp<mode>"
427 [(set (match_operand:CC 1 "cc_register" "")
429 (match_operator 4 "aarch64_comparison_operator"
430 [(match_operand 0 "cc_register" "")
433 (match_operand:GPI 2 "register_operand" "r,r,r")
434 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
435 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
438 ccmp\\t%<w>2, %<w>3, %k5, %m4
439 ccmp\\t%<w>2, %3, %k5, %m4
440 ccmn\\t%<w>2, #%n3, %k5, %m4"
441 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
444 (define_insn "fccmp<mode>"
445 [(set (match_operand:CCFP 1 "cc_register" "")
447 (match_operator 4 "aarch64_comparison_operator"
448 [(match_operand 0 "cc_register" "")
451 (match_operand:GPF 2 "register_operand" "w")
452 (match_operand:GPF 3 "register_operand" "w"))
453 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
455 "fccmp\\t%<s>2, %<s>3, %k5, %m4"
456 [(set_attr "type" "fccmp<s>")]
459 (define_insn "fccmpe<mode>"
460 [(set (match_operand:CCFPE 1 "cc_register" "")
462 (match_operator 4 "aarch64_comparison_operator"
463 [(match_operand 0 "cc_register" "")
466 (match_operand:GPF 2 "register_operand" "w")
467 (match_operand:GPF 3 "register_operand" "w"))
468 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
470 "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
471 [(set_attr "type" "fccmp<s>")]
474 ;; Expansion of signed mod by a power of 2 using CSNEG.
475 ;; For x0 % n where n is a power of 2 produce:
477 ;; and x0, x0, #(n - 1)
478 ;; and x1, x1, #(n - 1)
479 ;; csneg x0, x0, x1, mi
481 (define_expand "mod<mode>3"
482 [(match_operand:GPI 0 "register_operand" "")
483 (match_operand:GPI 1 "register_operand" "")
484 (match_operand:GPI 2 "const_int_operand" "")]
487 HOST_WIDE_INT val = INTVAL (operands[2]);
490 || exact_log2 (val) <= 0
491 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
494 rtx mask = GEN_INT (val - 1);
496 /* In the special case of x0 % 2 we can do the even shorter:
502 rtx masked = gen_reg_rtx (<MODE>mode);
503 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
504 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
505 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
506 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
510 rtx neg_op = gen_reg_rtx (<MODE>mode);
511 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
513 /* Extract the condition register and mode. */
514 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
515 rtx cc_reg = SET_DEST (cmp);
516 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
518 rtx masked_pos = gen_reg_rtx (<MODE>mode);
519 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
521 rtx masked_neg = gen_reg_rtx (<MODE>mode);
522 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
524 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
525 masked_neg, masked_pos));
530 (define_insn "condjump"
531 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
532 [(match_operand 1 "cc_register" "") (const_int 0)])
533 (label_ref (match_operand 2 "" ""))
537 /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
538 but the "." is required for SVE conditions. */
539 bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
540 if (get_attr_length (insn) == 8)
541 return aarch64_gen_far_branch (operands, 2, "Lbcond",
542 use_dot_p ? "b.%M0\\t" : "b%M0\\t");
544 return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
546 [(set_attr "type" "branch")
548 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
549 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
552 (set (attr "far_branch")
553 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
554 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
559 ;; For a 24-bit immediate CST we can optimize the compare for equality
560 ;; and branch sequence from:
562 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
566 ;; sub x0, x1, #(CST & 0xfff000)
567 ;; subs x0, x0, #(CST & 0x000fff)
569 (define_insn_and_split "*compare_condjump<mode>"
570 [(set (pc) (if_then_else (EQL
571 (match_operand:GPI 0 "register_operand" "r")
572 (match_operand:GPI 1 "aarch64_imm24" "n"))
573 (label_ref:P (match_operand 2 "" ""))
575 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
576 && !aarch64_plus_operand (operands[1], <MODE>mode)
577 && !reload_completed"
582 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
583 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
584 rtx tmp = gen_reg_rtx (<MODE>mode);
585 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
586 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
587 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
588 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
589 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
594 (define_expand "casesi"
595 [(match_operand:SI 0 "register_operand" "") ; Index
596 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
597 (match_operand:SI 2 "const_int_operand" "") ; Total range
598 (match_operand:DI 3 "" "") ; Table label
599 (match_operand:DI 4 "" "")] ; Out of range label
602 if (operands[1] != const0_rtx)
604 rtx reg = gen_reg_rtx (SImode);
606 /* Canonical RTL says that if you have:
610 then this should be emitted as:
614 The use of trunc_int_for_mode ensures that the resulting
615 constant can be represented in SImode, this is important
616 for the corner case where operand[1] is INT_MIN. */
618 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
620 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
621 (operands[1], SImode))
622 operands[1] = force_reg (SImode, operands[1]);
623 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
627 if (!aarch64_plus_operand (operands[2], SImode))
628 operands[2] = force_reg (SImode, operands[2]);
629 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
631 operands[0], operands[2], operands[4]));
633 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3]));
635 = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], operands[0]),
637 operands[2] = gen_rtx_MEM (DImode, operands[2]);
638 MEM_READONLY_P (operands[2]) = 1;
639 MEM_NOTRAP_P (operands[2]) = 1;
640 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[3]));
645 (define_expand "casesi_dispatch"
647 [(set (pc) (match_operand:DI 0 ""))
648 (clobber (reg:CC CC_REGNUM))
649 (clobber (match_scratch:DI 2))
650 (clobber (match_scratch:DI 3))
651 (use (label_ref:DI (match_operand 1 "")))])]
654 (define_insn "*casesi_dispatch"
657 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
658 (match_operand:SI 1 "register_operand" "r")]
660 (clobber (reg:CC CC_REGNUM))
661 (clobber (match_scratch:DI 3 "=r"))
662 (clobber (match_scratch:DI 4 "=r"))
663 (use (label_ref:DI (match_operand 2 "" "")))])]
666 return aarch64_output_casesi (operands);
668 [(set_attr "length" "16")
669 (set_attr "type" "branch")]
673 [(unspec[(const_int 0)] UNSPEC_NOP)]
676 [(set_attr "type" "no_insn")]
679 (define_insn "prefetch"
680 [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
681 (match_operand:QI 1 "const_int_operand" "")
682 (match_operand:QI 2 "const_int_operand" ""))]
685 const char * pftype[2][4] =
687 {"prfm\\tPLDL1STRM, %0",
688 "prfm\\tPLDL3KEEP, %0",
689 "prfm\\tPLDL2KEEP, %0",
690 "prfm\\tPLDL1KEEP, %0"},
691 {"prfm\\tPSTL1STRM, %0",
692 "prfm\\tPSTL3KEEP, %0",
693 "prfm\\tPSTL2KEEP, %0",
694 "prfm\\tPSTL1KEEP, %0"},
697 int locality = INTVAL (operands[2]);
699 gcc_assert (IN_RANGE (locality, 0, 3));
701 /* PRFM accepts the same addresses as a 64-bit LDR so wrap
702 the address into a DImode MEM so that aarch64_print_operand knows
704 operands[0] = gen_rtx_MEM (DImode, operands[0]);
705 return pftype[INTVAL(operands[1])][locality];
707 [(set_attr "type" "load_4")]
711 [(trap_if (const_int 1) (const_int 8))]
714 [(set_attr "type" "trap")])
716 (define_expand "prologue"
717 [(clobber (const_int 0))]
720 aarch64_expand_prologue ();
725 (define_expand "epilogue"
726 [(clobber (const_int 0))]
729 aarch64_expand_epilogue (false);
734 (define_expand "sibcall_epilogue"
735 [(clobber (const_int 0))]
738 aarch64_expand_epilogue (true);
743 (define_insn "*do_return"
747 if (aarch64_return_address_signing_enabled ()
749 && !crtl->calls_eh_return)
751 if (aarch64_ra_sign_key == AARCH64_KEY_B)
758 [(set_attr "type" "branch")]
761 (define_expand "return"
763 "aarch64_use_return_insn_p ()"
767 (define_insn "simple_return"
769 "aarch64_use_simple_return_insn_p ()"
771 [(set_attr "type" "branch")]
774 (define_insn "*cb<optab><mode>1"
775 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
777 (label_ref (match_operand 1 "" ""))
779 "!aarch64_track_speculation"
781 if (get_attr_length (insn) == 8)
782 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
784 return "<cbz>\\t%<w>0, %l1";
786 [(set_attr "type" "branch")
788 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
789 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
792 (set (attr "far_branch")
793 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
794 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
799 (define_insn "*tb<optab><mode>1"
800 [(set (pc) (if_then_else
801 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
804 "aarch64_simd_shift_imm_<mode>" "n"))
806 (label_ref (match_operand 2 "" ""))
808 (clobber (reg:CC CC_REGNUM))]
809 "!aarch64_track_speculation"
811 if (get_attr_length (insn) == 8)
813 if (get_attr_far_branch (insn) == 1)
814 return aarch64_gen_far_branch (operands, 2, "Ltb",
815 "<inv_tb>\\t%<w>0, %1, ");
818 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
819 return "tst\t%<w>0, %1\;<bcond>\t%l2";
823 return "<tbz>\t%<w>0, %1, %l2";
825 [(set_attr "type" "branch")
827 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
828 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
831 (set (attr "far_branch")
832 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
833 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
839 (define_insn "*cb<optab><mode>1"
840 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
842 (label_ref (match_operand 1 "" ""))
844 (clobber (reg:CC CC_REGNUM))]
845 "!aarch64_track_speculation"
847 if (get_attr_length (insn) == 8)
849 if (get_attr_far_branch (insn) == 1)
850 return aarch64_gen_far_branch (operands, 1, "Ltb",
851 "<inv_tb>\\t%<w>0, <sizem1>, ");
855 uint64_t val = ((uint64_t) 1)
856 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
857 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
858 output_asm_insn (buf, operands);
859 return "<bcond>\t%l1";
863 return "<tbz>\t%<w>0, <sizem1>, %l1";
865 [(set_attr "type" "branch")
867 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
868 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
871 (set (attr "far_branch")
872 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
873 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
878 ;; -------------------------------------------------------------------
879 ;; Subroutine calls and sibcalls
880 ;; -------------------------------------------------------------------
882 (define_expand "call"
883 [(parallel [(call (match_operand 0 "memory_operand" "")
884 (match_operand 1 "general_operand" ""))
885 (use (match_operand 2 "" ""))
886 (clobber (reg:DI LR_REGNUM))])]
890 aarch64_expand_call (NULL_RTX, operands[0], false);
895 (define_insn "*call_insn"
896 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
897 (match_operand 1 "" ""))
898 (clobber (reg:DI LR_REGNUM))]
903 [(set_attr "type" "call, call")]
906 (define_expand "call_value"
907 [(parallel [(set (match_operand 0 "" "")
908 (call (match_operand 1 "memory_operand" "")
909 (match_operand 2 "general_operand" "")))
910 (use (match_operand 3 "" ""))
911 (clobber (reg:DI LR_REGNUM))])]
915 aarch64_expand_call (operands[0], operands[1], false);
920 (define_insn "*call_value_insn"
921 [(set (match_operand 0 "" "")
922 (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
923 (match_operand 2 "" "")))
924 (clobber (reg:DI LR_REGNUM))]
929 [(set_attr "type" "call, call")]
932 (define_expand "sibcall"
933 [(parallel [(call (match_operand 0 "memory_operand" "")
934 (match_operand 1 "general_operand" ""))
936 (use (match_operand 2 "" ""))])]
939 aarch64_expand_call (NULL_RTX, operands[0], true);
944 (define_expand "sibcall_value"
945 [(parallel [(set (match_operand 0 "" "")
946 (call (match_operand 1 "memory_operand" "")
947 (match_operand 2 "general_operand" "")))
949 (use (match_operand 3 "" ""))])]
952 aarch64_expand_call (operands[0], operands[1], true);
957 (define_insn "*sibcall_insn"
958 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
959 (match_operand 1 "" ""))
961 "SIBLING_CALL_P (insn)"
965 [(set_attr "type" "branch, branch")]
968 (define_insn "*sibcall_value_insn"
969 [(set (match_operand 0 "" "")
971 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
972 (match_operand 2 "" "")))
974 "SIBLING_CALL_P (insn)"
978 [(set_attr "type" "branch, branch")]
981 ;; Call subroutine returning any type.
983 (define_expand "untyped_call"
984 [(parallel [(call (match_operand 0 "")
987 (match_operand 2 "")])]
992 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
994 for (i = 0; i < XVECLEN (operands[2], 0); i++)
996 rtx set = XVECEXP (operands[2], 0, i);
997 emit_move_insn (SET_DEST (set), SET_SRC (set));
1000 /* The optimizer does not know that the call sets the function value
1001 registers we stored in the result block. We avoid problems by
1002 claiming that all hard registers are used and clobbered at this
1004 emit_insn (gen_blockage ());
1008 ;; -------------------------------------------------------------------
1010 ;; -------------------------------------------------------------------
1012 (define_expand "mov<mode>"
1013 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
1014 (match_operand:SHORT 1 "general_operand" ""))]
1017 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1018 operands[1] = force_reg (<MODE>mode, operands[1]);
1020 if (GET_CODE (operands[1]) == CONST_POLY_INT)
1022 aarch64_expand_mov_immediate (operands[0], operands[1]);
1028 (define_insn "*mov<mode>_aarch64"
1029 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
1030 (match_operand:SHORT 1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
1031 "(register_operand (operands[0], <MODE>mode)
1032 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
1034 switch (which_alternative)
1037 return "mov\t%w0, %w1";
1039 return "mov\t%w0, %1";
1041 return aarch64_output_scalar_simd_mov_immediate (operands[1],
1044 return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1046 return "ldr<size>\t%w0, %1";
1048 return "ldr\t%<size>0, %1";
1050 return "str<size>\t%w1, %0";
1052 return "str\t%<size>1, %0";
1054 return "umov\t%w0, %1.<v>[0]";
1056 return "dup\t%0.<Vallxd>, %w1";
1058 return "dup\t%<Vetype>0, %1.<v>[0]";
1063 ;; The "mov_imm" type for CNT is just a placeholder.
1064 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
1065 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
1066 (set_attr "arch" "*,*,simd,sve,*,*,*,*,simd,simd,simd")]
1069 (define_expand "mov<mode>"
1070 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
1071 (match_operand:GPI 1 "general_operand" ""))]
1074 if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
1075 && <MODE>mode == DImode
1076 && aarch64_split_dimode_const_store (operands[0], operands[1]))
1079 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1080 operands[1] = force_reg (<MODE>mode, operands[1]);
1082 /* FIXME: RR we still need to fix up what we are doing with
1083 symbol_refs and other types of constants. */
1084 if (CONSTANT_P (operands[1])
1085 && !CONST_INT_P (operands[1]))
1087 aarch64_expand_mov_immediate (operands[0], operands[1]);
1093 (define_insn_and_split "*movsi_aarch64"
1094 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1095 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1096 "(register_operand (operands[0], SImode)
1097 || aarch64_reg_or_zero (operands[1], SImode))"
1104 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1114 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
1115 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1116 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1119 aarch64_expand_mov_immediate (operands[0], operands[1]);
1122 ;; The "mov_imm" type for CNT is just a placeholder.
1123 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1124 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1125 (set_attr "arch" "*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1128 (define_insn_and_split "*movdi_aarch64"
1129 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1130 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1131 "(register_operand (operands[0], DImode)
1132 || aarch64_reg_or_zero (operands[1], DImode))"
1140 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1150 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
1151 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1152 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1155 aarch64_expand_mov_immediate (operands[0], operands[1]);
1158 ;; The "mov_imm" type for CNTD is just a placeholder.
1159 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1160 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1162 (set_attr "arch" "*,*,*,*,*,*,sve,*,fp,*,fp,*,*,fp,fp,fp,simd")]
1165 (define_insn "insv_imm<mode>"
1166 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1168 (match_operand:GPI 1 "const_int_operand" "n"))
1169 (match_operand:GPI 2 "const_int_operand" "n"))]
1170 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1171 && UINTVAL (operands[1]) % 16 == 0"
1172 "movk\\t%<w>0, %X2, lsl %1"
1173 [(set_attr "type" "mov_imm")]
1176 (define_expand "movti"
1177 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1178 (match_operand:TI 1 "general_operand" ""))]
1181 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1182 operands[1] = force_reg (TImode, operands[1]);
1184 if (GET_CODE (operands[1]) == CONST_POLY_INT)
1186 emit_move_insn (gen_lowpart (DImode, operands[0]),
1187 gen_lowpart (DImode, operands[1]));
1188 emit_move_insn (gen_highpart (DImode, operands[0]), const0_rtx);
1194 (define_insn "*movti_aarch64"
1195 [(set (match_operand:TI 0
1196 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m")
1198 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1199 "(register_operand (operands[0], TImode)
1200 || aarch64_reg_or_zero (operands[1], TImode))"
1205 mov\\t%0.16b, %1.16b
1211 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1212 load_16,store_16,store_16,\
1214 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1215 (set_attr "arch" "*,*,*,simd,*,*,*,fp,fp")]
1218 ;; Split a TImode register-register or register-immediate move into
1219 ;; its component DImode pieces, taking care to handle overlapping
1220 ;; source and dest registers.
1222 [(set (match_operand:TI 0 "register_operand" "")
1223 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1224 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1227 aarch64_split_128bit_move (operands[0], operands[1]);
1231 (define_expand "mov<mode>"
1232 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1233 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1238 aarch64_err_no_fpadvsimd (<MODE>mode);
1242 if (GET_CODE (operands[0]) == MEM
1243 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1244 && aarch64_float_const_zero_rtx_p (operands[1])))
1245 operands[1] = force_reg (<MODE>mode, operands[1]);
1249 (define_insn "*movhf_aarch64"
1250 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w , w,?r,w,w ,w ,w,m,r,m ,r")
1251 (match_operand:HF 1 "general_operand" "Y ,?rY,?r, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1252 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1253 || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1259 mov\\t%0.h[0], %1.h[0]
1261 * return aarch64_output_scalar_simd_mov_immediate (operands[1], HImode);
1267 [(set_attr "type" "neon_move,f_mcr,neon_move,neon_to_gp, neon_move,fconsts, \
1268 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1269 (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
1272 (define_insn "*movsf_aarch64"
1273 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1274 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1275 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1276 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1283 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1290 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1291 f_loads,f_stores,load_4,store_4,mov_reg,\
1293 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1296 (define_insn "*movdf_aarch64"
1297 [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1298 (match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1299 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1300 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1307 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1314 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1315 f_loadd,f_stored,load_8,store_8,mov_reg,\
1317 (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
1321 [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
1322 (match_operand:GPF_HF 1 "general_operand"))]
1323 "can_create_pseudo_p ()
1324 && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
1325 && !aarch64_float_const_representable_p (operands[1])
1326 && aarch64_float_const_rtx_p (operands[1])"
1329 unsigned HOST_WIDE_INT ival;
1330 if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
1333 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1334 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1335 emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
1340 (define_insn "*movtf_aarch64"
1341 [(set (match_operand:TF 0
1342 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1344 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1345 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1346 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1348 mov\\t%0.16b, %1.16b
1359 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1360 f_loadd,f_stored,load_16,store_16,store_16")
1361 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1362 (set_attr "arch" "simd,*,*,*,simd,*,*,*,*,*,*")]
1366 [(set (match_operand:TF 0 "register_operand" "")
1367 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1368 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1371 aarch64_split_128bit_move (operands[0], operands[1]);
1378 ;; 2 is size of copy in bytes
1381 (define_expand "cpymemdi"
1382 [(match_operand:BLK 0 "memory_operand")
1383 (match_operand:BLK 1 "memory_operand")
1384 (match_operand:DI 2 "immediate_operand")
1385 (match_operand:DI 3 "immediate_operand")]
1388 if (aarch64_expand_cpymem (operands))
1394 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1395 ;; fairly lax checking on the second memory operation.
1396 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1397 [(set (match_operand:SX 0 "register_operand" "=r,w")
1398 (match_operand:SX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1399 (set (match_operand:SX2 2 "register_operand" "=r,w")
1400 (match_operand:SX2 3 "memory_operand" "m,m"))]
1401 "rtx_equal_p (XEXP (operands[3], 0),
1402 plus_constant (Pmode,
1403 XEXP (operands[1], 0),
1404 GET_MODE_SIZE (<SX:MODE>mode)))"
1408 [(set_attr "type" "load_8,neon_load1_2reg")
1409 (set_attr "arch" "*,fp")]
1412 ;; Storing different modes that can still be merged
1413 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1414 [(set (match_operand:DX 0 "register_operand" "=r,w")
1415 (match_operand:DX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1416 (set (match_operand:DX2 2 "register_operand" "=r,w")
1417 (match_operand:DX2 3 "memory_operand" "m,m"))]
1418 "rtx_equal_p (XEXP (operands[3], 0),
1419 plus_constant (Pmode,
1420 XEXP (operands[1], 0),
1421 GET_MODE_SIZE (<DX:MODE>mode)))"
1425 [(set_attr "type" "load_16,neon_load1_2reg")
1426 (set_attr "arch" "*,fp")]
1429 (define_insn "load_pair_dw_tftf"
1430 [(set (match_operand:TF 0 "register_operand" "=w")
1431 (match_operand:TF 1 "aarch64_mem_pair_operand" "Ump"))
1432 (set (match_operand:TF 2 "register_operand" "=w")
1433 (match_operand:TF 3 "memory_operand" "m"))]
1435 && rtx_equal_p (XEXP (operands[3], 0),
1436 plus_constant (Pmode,
1437 XEXP (operands[1], 0),
1438 GET_MODE_SIZE (TFmode)))"
1439 "ldp\\t%q0, %q2, %1"
1440 [(set_attr "type" "neon_ldp_q")
1441 (set_attr "fp" "yes")]
1444 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1445 ;; fairly lax checking on the second memory operation.
1446 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1447 [(set (match_operand:SX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1448 (match_operand:SX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1449 (set (match_operand:SX2 2 "memory_operand" "=m,m")
1450 (match_operand:SX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1451 "rtx_equal_p (XEXP (operands[2], 0),
1452 plus_constant (Pmode,
1453 XEXP (operands[0], 0),
1454 GET_MODE_SIZE (<SX:MODE>mode)))"
1458 [(set_attr "type" "store_8,neon_store1_2reg")
1459 (set_attr "arch" "*,fp")]
1462 ;; Storing different modes that can still be merged
1463 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1464 [(set (match_operand:DX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1465 (match_operand:DX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1466 (set (match_operand:DX2 2 "memory_operand" "=m,m")
1467 (match_operand:DX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1468 "rtx_equal_p (XEXP (operands[2], 0),
1469 plus_constant (Pmode,
1470 XEXP (operands[0], 0),
1471 GET_MODE_SIZE (<DX:MODE>mode)))"
1475 [(set_attr "type" "store_16,neon_store1_2reg")
1476 (set_attr "arch" "*,fp")]
1479 (define_insn "store_pair_dw_tftf"
1480 [(set (match_operand:TF 0 "aarch64_mem_pair_operand" "=Ump")
1481 (match_operand:TF 1 "register_operand" "w"))
1482 (set (match_operand:TF 2 "memory_operand" "=m")
1483 (match_operand:TF 3 "register_operand" "w"))]
1485 rtx_equal_p (XEXP (operands[2], 0),
1486 plus_constant (Pmode,
1487 XEXP (operands[0], 0),
1488 GET_MODE_SIZE (TFmode)))"
1489 "stp\\t%q1, %q3, %0"
1490 [(set_attr "type" "neon_stp_q")
1491 (set_attr "fp" "yes")]
1494 ;; Load pair with post-index writeback. This is primarily used in function
1496 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1498 [(set (match_operand:P 0 "register_operand" "=k")
1499 (plus:P (match_operand:P 1 "register_operand" "0")
1500 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1501 (set (match_operand:GPI 2 "register_operand" "=r")
1502 (mem:GPI (match_dup 1)))
1503 (set (match_operand:GPI 3 "register_operand" "=r")
1504 (mem:GPI (plus:P (match_dup 1)
1505 (match_operand:P 5 "const_int_operand" "n"))))])]
1506 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1507 "ldp\\t%<w>2, %<w>3, [%1], %4"
1508 [(set_attr "type" "load_<ldpstp_sz>")]
1511 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1513 [(set (match_operand:P 0 "register_operand" "=k")
1514 (plus:P (match_operand:P 1 "register_operand" "0")
1515 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1516 (set (match_operand:GPF 2 "register_operand" "=w")
1517 (mem:GPF (match_dup 1)))
1518 (set (match_operand:GPF 3 "register_operand" "=w")
1519 (mem:GPF (plus:P (match_dup 1)
1520 (match_operand:P 5 "const_int_operand" "n"))))])]
1521 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1522 "ldp\\t%<w>2, %<w>3, [%1], %4"
1523 [(set_attr "type" "neon_load1_2reg")]
1526 (define_insn "loadwb_pair<TX:mode>_<P:mode>"
1528 [(set (match_operand:P 0 "register_operand" "=k")
1529 (plus:P (match_operand:P 1 "register_operand" "0")
1530 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1531 (set (match_operand:TX 2 "register_operand" "=w")
1532 (mem:TX (match_dup 1)))
1533 (set (match_operand:TX 3 "register_operand" "=w")
1534 (mem:TX (plus:P (match_dup 1)
1535 (match_operand:P 5 "const_int_operand" "n"))))])]
1536 "TARGET_SIMD && INTVAL (operands[5]) == GET_MODE_SIZE (<TX:MODE>mode)"
1537 "ldp\\t%q2, %q3, [%1], %4"
1538 [(set_attr "type" "neon_ldp_q")]
1541 ;; Store pair with pre-index writeback. This is primarily used in function
1543 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1545 [(set (match_operand:P 0 "register_operand" "=&k")
1546 (plus:P (match_operand:P 1 "register_operand" "0")
1547 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1548 (set (mem:GPI (plus:P (match_dup 0)
1550 (match_operand:GPI 2 "register_operand" "r"))
1551 (set (mem:GPI (plus:P (match_dup 0)
1552 (match_operand:P 5 "const_int_operand" "n")))
1553 (match_operand:GPI 3 "register_operand" "r"))])]
1554 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1555 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1556 [(set_attr "type" "store_<ldpstp_sz>")]
1559 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1561 [(set (match_operand:P 0 "register_operand" "=&k")
1562 (plus:P (match_operand:P 1 "register_operand" "0")
1563 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1564 (set (mem:GPF (plus:P (match_dup 0)
1566 (match_operand:GPF 2 "register_operand" "w"))
1567 (set (mem:GPF (plus:P (match_dup 0)
1568 (match_operand:P 5 "const_int_operand" "n")))
1569 (match_operand:GPF 3 "register_operand" "w"))])]
1570 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1571 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1572 [(set_attr "type" "neon_store1_2reg<q>")]
1575 (define_insn "storewb_pair<TX:mode>_<P:mode>"
1577 [(set (match_operand:P 0 "register_operand" "=&k")
1578 (plus:P (match_operand:P 1 "register_operand" "0")
1579 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1580 (set (mem:TX (plus:P (match_dup 0)
1582 (match_operand:TX 2 "register_operand" "w"))
1583 (set (mem:TX (plus:P (match_dup 0)
1584 (match_operand:P 5 "const_int_operand" "n")))
1585 (match_operand:TX 3 "register_operand" "w"))])]
1587 && INTVAL (operands[5])
1588 == INTVAL (operands[4]) + GET_MODE_SIZE (<TX:MODE>mode)"
1589 "stp\\t%q2, %q3, [%0, %4]!"
1590 [(set_attr "type" "neon_stp_q")]
1593 ;; -------------------------------------------------------------------
1594 ;; Sign/Zero extension
1595 ;; -------------------------------------------------------------------
1597 (define_expand "<optab>sidi2"
1598 [(set (match_operand:DI 0 "register_operand")
1599 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1603 (define_insn "*extendsidi2_aarch64"
1604 [(set (match_operand:DI 0 "register_operand" "=r,r")
1605 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1610 [(set_attr "type" "extend,load_4")]
1613 (define_insn "*load_pair_extendsidi2_aarch64"
1614 [(set (match_operand:DI 0 "register_operand" "=r")
1615 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1616 (set (match_operand:DI 2 "register_operand" "=r")
1617 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1618 "rtx_equal_p (XEXP (operands[3], 0),
1619 plus_constant (Pmode,
1620 XEXP (operands[1], 0),
1621 GET_MODE_SIZE (SImode)))"
1622 "ldpsw\\t%0, %2, %1"
1623 [(set_attr "type" "load_8")]
1626 (define_insn "*zero_extendsidi2_aarch64"
1627 [(set (match_operand:DI 0 "register_operand" "=r,r,w,w,r,w")
1628 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,r,m,w,w")))]
1637 [(set_attr "type" "mov_reg,load_4,f_mcr,f_loads,f_mrc,fmov")
1638 (set_attr "arch" "*,*,fp,fp,fp,fp")]
1641 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1642 [(set (match_operand:DI 0 "register_operand" "=r,w")
1643 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump")))
1644 (set (match_operand:DI 2 "register_operand" "=r,w")
1645 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m,m")))]
1646 "rtx_equal_p (XEXP (operands[3], 0),
1647 plus_constant (Pmode,
1648 XEXP (operands[1], 0),
1649 GET_MODE_SIZE (SImode)))"
1653 [(set_attr "type" "load_8,neon_load1_2reg")
1654 (set_attr "arch" "*,fp")]
1657 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1658 [(set (match_operand:GPI 0 "register_operand")
1659 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1663 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1664 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1665 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1668 sxt<SHORT:size>\t%<GPI:w>0, %w1
1669 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1670 [(set_attr "type" "extend,load_4")]
1673 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1674 [(set (match_operand:GPI 0 "register_operand" "=r,r,w")
1675 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1678 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1679 ldr<SHORT:size>\t%w0, %1
1680 ldr\t%<SHORT:size>0, %1"
1681 [(set_attr "type" "logic_imm,load_4,f_loads")
1682 (set_attr "arch" "*,*,fp")]
1685 (define_expand "<optab>qihi2"
1686 [(set (match_operand:HI 0 "register_operand")
1687 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1691 (define_insn "*extendqihi2_aarch64"
1692 [(set (match_operand:HI 0 "register_operand" "=r,r")
1693 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1698 [(set_attr "type" "extend,load_4")]
1701 (define_insn "*zero_extendqihi2_aarch64"
1702 [(set (match_operand:HI 0 "register_operand" "=r,r")
1703 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1708 [(set_attr "type" "logic_imm,load_4")]
1711 ;; -------------------------------------------------------------------
1712 ;; Simple arithmetic
1713 ;; -------------------------------------------------------------------
1715 (define_expand "add<mode>3"
1717 (match_operand:GPI 0 "register_operand" "")
1718 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1719 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "")))]
1722 /* If operands[1] is a subreg extract the inner RTX. */
1723 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1725 /* If the constant is too large for a single instruction and isn't frame
1726 based, split off the immediate so it is available for CSE. */
1727 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1728 && can_create_pseudo_p ()
1730 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1731 operands[2] = force_reg (<MODE>mode, operands[2]);
1732 /* Expand polynomial additions now if the destination is the stack
1733 pointer, since we don't want to use that as a temporary. */
1734 else if (operands[0] == stack_pointer_rtx
1735 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode))
1737 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
1738 operands[2], NULL_RTX, NULL_RTX);
1743 (define_insn "*add<mode>3_aarch64"
1745 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,rk")
1747 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,rk")
1748 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uav")))]
1751 add\\t%<w>0, %<w>1, %2
1752 add\\t%<w>0, %<w>1, %<w>2
1753 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1754 sub\\t%<w>0, %<w>1, #%n2
1756 * return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]);"
1757 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1758 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm")
1759 (set_attr "arch" "*,*,simd,*,*,*")]
1762 ;; zero_extend version of above
1763 (define_insn "*addsi3_aarch64_uxtw"
1765 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1767 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1768 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1773 sub\\t%w0, %w1, #%n2
1775 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1778 ;; If there's a free register, and we can load the constant with a
1779 ;; single instruction, do so. This has a chance to improve scheduling.
1781 [(match_scratch:GPI 3 "r")
1782 (set (match_operand:GPI 0 "register_operand")
1784 (match_operand:GPI 1 "register_operand")
1785 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1786 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1787 [(set (match_dup 3) (match_dup 2))
1788 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1792 [(match_scratch:SI 3 "r")
1793 (set (match_operand:DI 0 "register_operand")
1796 (match_operand:SI 1 "register_operand")
1797 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1798 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1799 [(set (match_dup 3) (match_dup 2))
1800 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1803 ;; After peephole2 has had a chance to run, split any remaining long
1804 ;; additions into two add immediates.
1806 [(set (match_operand:GPI 0 "register_operand")
1808 (match_operand:GPI 1 "register_operand")
1809 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1810 "epilogue_completed"
1811 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1812 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1814 HOST_WIDE_INT i = INTVAL (operands[2]);
1815 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1816 operands[3] = GEN_INT (i - s);
1817 operands[4] = GEN_INT (s);
1821 ;; Match addition of polynomial offsets that require one temporary, for which
1822 ;; we can use the early-clobbered destination register. This is a separate
1823 ;; pattern so that the early clobber doesn't affect register allocation
1824 ;; for other forms of addition. However, we still need to provide an
1825 ;; all-register alternative, in case the offset goes out of range after
1826 ;; elimination. For completeness we might as well provide all GPR-based
1827 ;; alternatives from the main pattern.
1829 ;; We don't have a pattern for additions requiring two temporaries since at
1830 ;; present LRA doesn't allow new scratches to be added during elimination.
1831 ;; Such offsets should be rare anyway.
1833 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1834 ;; here would go away. We could just handle all polynomial constants in
1836 (define_insn_and_split "*add<mode>3_poly_1"
1838 (match_operand:GPI 0 "register_operand" "=r,r,r,r,r,&r")
1840 (match_operand:GPI 1 "register_operand" "%rk,rk,rk,rk,rk,rk")
1841 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uat")))]
1842 "TARGET_SVE && operands[0] != stack_pointer_rtx"
1844 add\\t%<w>0, %<w>1, %2
1845 add\\t%<w>0, %<w>1, %<w>2
1846 sub\\t%<w>0, %<w>1, #%n2
1848 * return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]);
1850 "&& epilogue_completed
1851 && !reg_overlap_mentioned_p (operands[0], operands[1])
1852 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)"
1855 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
1856 operands[2], operands[0], NULL_RTX);
1859 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1860 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,multiple")]
1864 [(set (match_operand:DI 0 "register_operand")
1867 (match_operand:SI 1 "register_operand")
1868 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1869 "epilogue_completed"
1870 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1871 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1873 HOST_WIDE_INT i = INTVAL (operands[2]);
1874 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1875 operands[3] = GEN_INT (i - s);
1876 operands[4] = GEN_INT (s);
1877 operands[5] = gen_lowpart (SImode, operands[0]);
1881 (define_expand "addv<mode>4"
1882 [(match_operand:GPI 0 "register_operand")
1883 (match_operand:GPI 1 "register_operand")
1884 (match_operand:GPI 2 "aarch64_plus_operand")
1885 (label_ref (match_operand 3 "" ""))]
1888 if (CONST_INT_P (operands[2]))
1889 emit_insn (gen_add<mode>3_compareV_imm (operands[0], operands[1],
1892 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
1893 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1898 (define_expand "uaddv<mode>4"
1899 [(match_operand:GPI 0 "register_operand")
1900 (match_operand:GPI 1 "register_operand")
1901 (match_operand:GPI 2 "register_operand")
1902 (label_ref (match_operand 3 "" ""))]
1905 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
1906 aarch64_gen_unlikely_cbranch (LTU, CC_Cmode, operands[3]);
1911 (define_expand "addti3"
1912 [(set (match_operand:TI 0 "register_operand" "")
1913 (plus:TI (match_operand:TI 1 "register_operand" "")
1914 (match_operand:TI 2 "aarch64_reg_or_imm" "")))]
1917 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1919 aarch64_addti_scratch_regs (operands[1], operands[2],
1920 &low_dest, &op1_low, &op2_low,
1921 &high_dest, &op1_high, &op2_high);
1923 if (op2_low == const0_rtx)
1926 if (!aarch64_pluslong_operand (op2_high, DImode))
1927 op2_high = force_reg (DImode, op2_high);
1928 emit_insn (gen_adddi3 (high_dest, op1_high, op2_high));
1932 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1933 force_reg (DImode, op2_low)));
1934 emit_insn (gen_adddi3_carryin (high_dest, op1_high,
1935 force_reg (DImode, op2_high)));
1938 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
1939 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
1944 (define_expand "addvti4"
1945 [(match_operand:TI 0 "register_operand" "")
1946 (match_operand:TI 1 "register_operand" "")
1947 (match_operand:TI 2 "aarch64_reg_or_imm" "")
1948 (label_ref (match_operand 3 "" ""))]
1951 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1953 aarch64_addti_scratch_regs (operands[1], operands[2],
1954 &low_dest, &op1_low, &op2_low,
1955 &high_dest, &op1_high, &op2_high);
1957 if (op2_low == const0_rtx)
1960 emit_insn (gen_adddi3_compareV (high_dest, op1_high,
1961 force_reg (DImode, op2_high)));
1965 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
1966 force_reg (DImode, op2_low)));
1967 emit_insn (gen_adddi3_carryinV (high_dest, op1_high,
1968 force_reg (DImode, op2_high)));
1971 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
1972 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
1974 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1978 (define_expand "uaddvti4"
1979 [(match_operand:TI 0 "register_operand" "")
1980 (match_operand:TI 1 "register_operand" "")
1981 (match_operand:TI 2 "aarch64_reg_or_imm" "")
1982 (label_ref (match_operand 3 "" ""))]
1985 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
1987 aarch64_addti_scratch_regs (operands[1], operands[2],
1988 &low_dest, &op1_low, &op2_low,
1989 &high_dest, &op1_high, &op2_high);
1991 if (op2_low == const0_rtx)
1994 emit_insn (gen_adddi3_compareC (high_dest, op1_high,
1995 force_reg (DImode, op2_high)));
1999 emit_insn (gen_adddi3_compareC (low_dest, op1_low,
2000 force_reg (DImode, op2_low)));
2001 emit_insn (gen_adddi3_carryinC (high_dest, op1_high,
2002 force_reg (DImode, op2_high)));
2005 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2006 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2008 aarch64_gen_unlikely_cbranch (GEU, CC_ADCmode, operands[3]);
2012 (define_insn "add<mode>3_compare0"
2013 [(set (reg:CC_NZ CC_REGNUM)
2015 (plus:GPI (match_operand:GPI 1 "register_operand" "%rk,rk,rk")
2016 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
2018 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
2019 (plus:GPI (match_dup 1) (match_dup 2)))]
2022 adds\\t%<w>0, %<w>1, %<w>2
2023 adds\\t%<w>0, %<w>1, %2
2024 subs\\t%<w>0, %<w>1, #%n2"
2025 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2028 ;; zero_extend version of above
2029 (define_insn "*addsi3_compare0_uxtw"
2030 [(set (reg:CC_NZ CC_REGNUM)
2032 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk")
2033 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
2035 (set (match_operand:DI 0 "register_operand" "=r,r,r")
2036 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
2039 adds\\t%w0, %w1, %w2
2041 subs\\t%w0, %w1, #%n2"
2042 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2045 (define_insn "*add<mode>3_compareC_cconly"
2046 [(set (reg:CC_C CC_REGNUM)
2049 (match_operand:GPI 0 "register_operand" "r,r,r")
2050 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2057 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2060 (define_insn "add<mode>3_compareC"
2061 [(set (reg:CC_C CC_REGNUM)
2064 (match_operand:GPI 1 "register_operand" "rk,rk,rk")
2065 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
2067 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
2068 (plus:GPI (match_dup 1) (match_dup 2)))]
2071 adds\\t%<w>0, %<w>1, %<w>2
2072 adds\\t%<w>0, %<w>1, %2
2073 subs\\t%<w>0, %<w>1, #%n2"
2074 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2077 (define_insn "*add<mode>3_compareV_cconly_imm"
2078 [(set (reg:CC_V CC_REGNUM)
2081 (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
2082 (match_operand:<DWI> 1 "const_scalar_int_operand" ""))
2086 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))]
2087 "INTVAL (operands[1]) == INTVAL (operands[2])"
2091 [(set_attr "type" "alus_imm")]
2094 (define_insn "*add<mode>3_compareV_cconly"
2095 [(set (reg:CC_V CC_REGNUM)
2098 (sign_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
2099 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2100 (sign_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
2102 "cmn\\t%<w>0, %<w>1"
2103 [(set_attr "type" "alus_sreg")]
2106 (define_insn "add<mode>3_compareV_imm"
2107 [(set (reg:CC_V CC_REGNUM)
2111 (match_operand:GPI 1 "register_operand" "rk,rk"))
2112 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J"))
2114 (plus:GPI (match_dup 1) (match_dup 2)))))
2115 (set (match_operand:GPI 0 "register_operand" "=r,r")
2116 (plus:GPI (match_dup 1) (match_dup 2)))]
2119 adds\\t%<w>0, %<w>1, %<w>2
2120 subs\\t%<w>0, %<w>1, #%n2"
2121 [(set_attr "type" "alus_imm,alus_imm")]
2124 (define_insn "add<mode>3_compareV"
2125 [(set (reg:CC_V CC_REGNUM)
2128 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "rk"))
2129 (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2130 (sign_extend:<DWI> (plus:GPI (match_dup 1) (match_dup 2)))))
2131 (set (match_operand:GPI 0 "register_operand" "=r")
2132 (plus:GPI (match_dup 1) (match_dup 2)))]
2134 "adds\\t%<w>0, %<w>1, %<w>2"
2135 [(set_attr "type" "alus_sreg")]
2138 (define_insn "*adds_shift_imm_<mode>"
2139 [(set (reg:CC_NZ CC_REGNUM)
2141 (plus:GPI (ASHIFT:GPI
2142 (match_operand:GPI 1 "register_operand" "r")
2143 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2144 (match_operand:GPI 3 "register_operand" "r"))
2146 (set (match_operand:GPI 0 "register_operand" "=r")
2147 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
2150 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2151 [(set_attr "type" "alus_shift_imm")]
2154 (define_insn "*subs_shift_imm_<mode>"
2155 [(set (reg:CC_NZ CC_REGNUM)
2157 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2159 (match_operand:GPI 2 "register_operand" "r")
2160 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
2162 (set (match_operand:GPI 0 "register_operand" "=r")
2163 (minus:GPI (match_dup 1)
2164 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
2166 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
2167 [(set_attr "type" "alus_shift_imm")]
2170 (define_insn "*adds_mul_imm_<mode>"
2171 [(set (reg:CC_NZ CC_REGNUM)
2174 (match_operand:GPI 1 "register_operand" "r")
2175 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2176 (match_operand:GPI 3 "register_operand" "r"))
2178 (set (match_operand:GPI 0 "register_operand" "=r")
2179 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
2182 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2183 [(set_attr "type" "alus_shift_imm")]
2186 (define_insn "*subs_mul_imm_<mode>"
2187 [(set (reg:CC_NZ CC_REGNUM)
2189 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2191 (match_operand:GPI 2 "register_operand" "r")
2192 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
2194 (set (match_operand:GPI 0 "register_operand" "=r")
2195 (minus:GPI (match_dup 1)
2196 (mult:GPI (match_dup 2) (match_dup 3))))]
2198 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
2199 [(set_attr "type" "alus_shift_imm")]
2202 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
2203 [(set (reg:CC_NZ CC_REGNUM)
2206 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2207 (match_operand:GPI 2 "register_operand" "rk"))
2209 (set (match_operand:GPI 0 "register_operand" "=r")
2210 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
2212 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2213 [(set_attr "type" "alus_ext")]
2216 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
2217 [(set (reg:CC_NZ CC_REGNUM)
2219 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2221 (match_operand:ALLX 2 "register_operand" "r")))
2223 (set (match_operand:GPI 0 "register_operand" "=r")
2224 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
2226 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2227 [(set_attr "type" "alus_ext")]
2230 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
2231 [(set (reg:CC_NZ CC_REGNUM)
2233 (plus:GPI (ashift:GPI
2235 (match_operand:ALLX 1 "register_operand" "r"))
2236 (match_operand 2 "aarch64_imm3" "Ui3"))
2237 (match_operand:GPI 3 "register_operand" "rk"))
2239 (set (match_operand:GPI 0 "register_operand" "=rk")
2240 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
2244 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2245 [(set_attr "type" "alus_ext")]
2248 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
2249 [(set (reg:CC_NZ CC_REGNUM)
2251 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2254 (match_operand:ALLX 2 "register_operand" "r"))
2255 (match_operand 3 "aarch64_imm3" "Ui3")))
2257 (set (match_operand:GPI 0 "register_operand" "=rk")
2258 (minus:GPI (match_dup 1)
2259 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
2262 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2263 [(set_attr "type" "alus_ext")]
2266 (define_insn "*adds_<optab><mode>_multp2"
2267 [(set (reg:CC_NZ CC_REGNUM)
2269 (plus:GPI (ANY_EXTRACT:GPI
2270 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2271 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2272 (match_operand 3 "const_int_operand" "n")
2274 (match_operand:GPI 4 "register_operand" "rk"))
2276 (set (match_operand:GPI 0 "register_operand" "=r")
2277 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
2281 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2282 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2283 [(set_attr "type" "alus_ext")]
2286 (define_insn "*subs_<optab><mode>_multp2"
2287 [(set (reg:CC_NZ CC_REGNUM)
2289 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2291 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2292 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2293 (match_operand 3 "const_int_operand" "n")
2296 (set (match_operand:GPI 0 "register_operand" "=r")
2297 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
2298 (mult:GPI (match_dup 1) (match_dup 2))
2301 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2302 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2303 [(set_attr "type" "alus_ext")]
2306 (define_insn "*add<mode>3nr_compare0"
2307 [(set (reg:CC_NZ CC_REGNUM)
2309 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2310 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2317 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2320 (define_insn "aarch64_sub<mode>_compare0"
2321 [(set (reg:CC_NZ CC_REGNUM)
2323 (minus:GPI (match_operand:GPI 0 "register_operand" "r")
2324 (match_operand:GPI 1 "aarch64_plus_operand" "r"))
2327 "cmp\\t%<w>0, %<w>1"
2328 [(set_attr "type" "alus_sreg")]
2331 (define_insn "*compare_neg<mode>"
2332 [(set (reg:CC_Z CC_REGNUM)
2334 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2335 (match_operand:GPI 1 "register_operand" "r")))]
2337 "cmn\\t%<w>1, %<w>0"
2338 [(set_attr "type" "alus_sreg")]
2341 (define_insn "*add_<shift>_<mode>"
2342 [(set (match_operand:GPI 0 "register_operand" "=r")
2343 (plus:GPI (ASHIFT:GPI (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 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2348 [(set_attr "type" "alu_shift_imm")]
2351 ;; zero_extend version of above
2352 (define_insn "*add_<shift>_si_uxtw"
2353 [(set (match_operand:DI 0 "register_operand" "=r")
2355 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2356 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2357 (match_operand:SI 3 "register_operand" "r"))))]
2359 "add\\t%w0, %w3, %w1, <shift> %2"
2360 [(set_attr "type" "alu_shift_imm")]
2363 (define_insn "*add_mul_imm_<mode>"
2364 [(set (match_operand:GPI 0 "register_operand" "=r")
2365 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2366 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2367 (match_operand:GPI 3 "register_operand" "r")))]
2369 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2370 [(set_attr "type" "alu_shift_imm")]
2373 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2374 [(set (match_operand:GPI 0 "register_operand" "=rk")
2375 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2376 (match_operand:GPI 2 "register_operand" "r")))]
2378 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2379 [(set_attr "type" "alu_ext")]
2382 ;; zero_extend version of above
2383 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2384 [(set (match_operand:DI 0 "register_operand" "=rk")
2386 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2387 (match_operand:GPI 2 "register_operand" "r"))))]
2389 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2390 [(set_attr "type" "alu_ext")]
2393 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2394 [(set (match_operand:GPI 0 "register_operand" "=rk")
2395 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2396 (match_operand:ALLX 1 "register_operand" "r"))
2397 (match_operand 2 "aarch64_imm3" "Ui3"))
2398 (match_operand:GPI 3 "register_operand" "r")))]
2400 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2401 [(set_attr "type" "alu_ext")]
2404 ;; zero_extend version of above
2405 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2406 [(set (match_operand:DI 0 "register_operand" "=rk")
2408 (plus:SI (ashift:SI (ANY_EXTEND:SI
2409 (match_operand:SHORT 1 "register_operand" "r"))
2410 (match_operand 2 "aarch64_imm3" "Ui3"))
2411 (match_operand:SI 3 "register_operand" "r"))))]
2413 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2414 [(set_attr "type" "alu_ext")]
2417 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2418 [(set (match_operand:GPI 0 "register_operand" "=rk")
2419 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2420 (match_operand:ALLX 1 "register_operand" "r"))
2421 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2422 (match_operand:GPI 3 "register_operand" "r")))]
2424 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2425 [(set_attr "type" "alu_ext")]
2428 ;; zero_extend version of above
2429 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2430 [(set (match_operand:DI 0 "register_operand" "=rk")
2431 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2432 (match_operand:SHORT 1 "register_operand" "r"))
2433 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2434 (match_operand:SI 3 "register_operand" "r"))))]
2436 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2437 [(set_attr "type" "alu_ext")]
2440 (define_insn "*add_<optab><mode>_multp2"
2441 [(set (match_operand:GPI 0 "register_operand" "=rk")
2442 (plus:GPI (ANY_EXTRACT:GPI
2443 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2444 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2445 (match_operand 3 "const_int_operand" "n")
2447 (match_operand:GPI 4 "register_operand" "r")))]
2448 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2449 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2450 [(set_attr "type" "alu_ext")]
2453 ;; zero_extend version of above
2454 (define_insn "*add_<optab>si_multp2_uxtw"
2455 [(set (match_operand:DI 0 "register_operand" "=rk")
2457 (plus:SI (ANY_EXTRACT:SI
2458 (mult:SI (match_operand:SI 1 "register_operand" "r")
2459 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2460 (match_operand 3 "const_int_operand" "n")
2462 (match_operand:SI 4 "register_operand" "r"))))]
2463 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2464 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2465 [(set_attr "type" "alu_ext")]
2468 (define_expand "add<mode>3_carryin"
2469 [(set (match_operand:GPI 0 "register_operand")
2472 (ltu:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2473 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2474 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2479 ;; Note that add with carry with two zero inputs is matched by cset,
2480 ;; and that add with carry with one zero input is matched by cinc.
2482 (define_insn "*add<mode>3_carryin"
2483 [(set (match_operand:GPI 0 "register_operand" "=r")
2486 (match_operand:GPI 3 "aarch64_carry_operation" "")
2487 (match_operand:GPI 1 "register_operand" "r"))
2488 (match_operand:GPI 2 "register_operand" "r")))]
2490 "adc\\t%<w>0, %<w>1, %<w>2"
2491 [(set_attr "type" "adc_reg")]
2494 ;; zero_extend version of above
2495 (define_insn "*addsi3_carryin_uxtw"
2496 [(set (match_operand:DI 0 "register_operand" "=r")
2500 (match_operand:SI 3 "aarch64_carry_operation" "")
2501 (match_operand:SI 1 "register_operand" "r"))
2502 (match_operand:SI 2 "register_operand" "r"))))]
2504 "adc\\t%w0, %w1, %w2"
2505 [(set_attr "type" "adc_reg")]
2508 (define_expand "add<mode>3_carryinC"
2516 (match_operand:GPI 1 "register_operand" "")))
2518 (match_operand:GPI 2 "register_operand" "")))
2520 (set (match_operand:GPI 0 "register_operand")
2522 (plus:GPI (match_dup 5) (match_dup 1))
2526 operands[3] = gen_rtx_REG (CC_ADCmode, CC_REGNUM);
2527 rtx ccin = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2528 operands[4] = gen_rtx_LTU (<DWI>mode, ccin, const0_rtx);
2529 operands[5] = gen_rtx_LTU (<MODE>mode, ccin, const0_rtx);
2530 operands[6] = immed_wide_int_const (wi::shwi (1, <DWI>mode)
2531 << GET_MODE_BITSIZE (<MODE>mode),
2535 (define_insn "*add<mode>3_carryinC_zero"
2536 [(set (reg:CC_ADC CC_REGNUM)
2539 (match_operand:<DWI> 2 "aarch64_carry_operation" "")
2540 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2541 (match_operand 4 "const_scalar_int_operand" "")))
2542 (set (match_operand:GPI 0 "register_operand" "=r")
2543 (plus:GPI (match_operand:GPI 3 "aarch64_carry_operation" "")
2545 "rtx_mode_t (operands[4], <DWI>mode)
2546 == (wi::shwi (1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2547 "adcs\\t%<w>0, %<w>1, <w>zr"
2548 [(set_attr "type" "adc_reg")]
2551 (define_insn "*add<mode>3_carryinC"
2552 [(set (reg:CC_ADC CC_REGNUM)
2556 (match_operand:<DWI> 3 "aarch64_carry_operation" "")
2557 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2558 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2559 (match_operand 5 "const_scalar_int_operand" "")))
2560 (set (match_operand:GPI 0 "register_operand" "=r")
2562 (plus:GPI (match_operand:GPI 4 "aarch64_carry_operation" "")
2565 "rtx_mode_t (operands[5], <DWI>mode)
2566 == (wi::shwi (1, <DWI>mode) << (unsigned) GET_MODE_BITSIZE (<MODE>mode))"
2567 "adcs\\t%<w>0, %<w>1, %<w>2"
2568 [(set_attr "type" "adc_reg")]
2571 (define_expand "add<mode>3_carryinV"
2573 [(set (reg:CC_V CC_REGNUM)
2579 (match_operand:GPI 1 "register_operand" "")))
2581 (match_operand:GPI 2 "register_operand" "")))
2584 (plus:GPI (match_dup 4) (match_dup 1))
2586 (set (match_operand:GPI 0 "register_operand")
2588 (plus:GPI (match_dup 4) (match_dup 1))
2592 rtx cc = gen_rtx_REG (CC_Cmode, CC_REGNUM);
2593 operands[3] = gen_rtx_LTU (<DWI>mode, cc, const0_rtx);
2594 operands[4] = gen_rtx_LTU (<MODE>mode, cc, const0_rtx);
2597 (define_insn "*add<mode>3_carryinV_zero"
2598 [(set (reg:CC_V CC_REGNUM)
2601 (match_operand:<DWI> 2 "aarch64_carry_operation" "")
2602 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2605 (match_operand:GPI 3 "aarch64_carry_operation" "")
2607 (set (match_operand:GPI 0 "register_operand" "=r")
2608 (plus:GPI (match_dup 3) (match_dup 1)))]
2610 "adcs\\t%<w>0, %<w>1, <w>zr"
2611 [(set_attr "type" "adc_reg")]
2614 (define_insn "*add<mode>3_carryinV"
2615 [(set (reg:CC_V CC_REGNUM)
2619 (match_operand:<DWI> 3 "aarch64_carry_operation" "")
2620 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
2621 (sign_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
2625 (match_operand:GPI 4 "aarch64_carry_operation" "")
2628 (set (match_operand:GPI 0 "register_operand" "=r")
2630 (plus:GPI (match_dup 4) (match_dup 1))
2633 "adcs\\t%<w>0, %<w>1, %<w>2"
2634 [(set_attr "type" "adc_reg")]
2637 (define_insn "*add_uxt<mode>_shift2"
2638 [(set (match_operand:GPI 0 "register_operand" "=rk")
2640 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2641 (match_operand 2 "aarch64_imm3" "Ui3"))
2642 (match_operand 3 "const_int_operand" "n"))
2643 (match_operand:GPI 4 "register_operand" "r")))]
2644 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2646 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2647 INTVAL (operands[3])));
2648 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2649 [(set_attr "type" "alu_ext")]
2652 ;; zero_extend version of above
2653 (define_insn "*add_uxtsi_shift2_uxtw"
2654 [(set (match_operand:DI 0 "register_operand" "=rk")
2657 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2658 (match_operand 2 "aarch64_imm3" "Ui3"))
2659 (match_operand 3 "const_int_operand" "n"))
2660 (match_operand:SI 4 "register_operand" "r"))))]
2661 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2663 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2664 INTVAL (operands[3])));
2665 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2666 [(set_attr "type" "alu_ext")]
2669 (define_insn "*add_uxt<mode>_multp2"
2670 [(set (match_operand:GPI 0 "register_operand" "=rk")
2672 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2673 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2674 (match_operand 3 "const_int_operand" "n"))
2675 (match_operand:GPI 4 "register_operand" "r")))]
2676 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2678 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2679 INTVAL (operands[3])));
2680 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2681 [(set_attr "type" "alu_ext")]
2684 ;; zero_extend version of above
2685 (define_insn "*add_uxtsi_multp2_uxtw"
2686 [(set (match_operand:DI 0 "register_operand" "=rk")
2689 (mult:SI (match_operand:SI 1 "register_operand" "r")
2690 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2691 (match_operand 3 "const_int_operand" "n"))
2692 (match_operand:SI 4 "register_operand" "r"))))]
2693 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2695 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2696 INTVAL (operands[3])));
2697 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2698 [(set_attr "type" "alu_ext")]
2701 (define_insn "subsi3"
2702 [(set (match_operand:SI 0 "register_operand" "=rk")
2703 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2704 (match_operand:SI 2 "register_operand" "r")))]
2706 "sub\\t%w0, %w1, %w2"
2707 [(set_attr "type" "alu_sreg")]
2710 ;; zero_extend version of above
2711 (define_insn "*subsi3_uxtw"
2712 [(set (match_operand:DI 0 "register_operand" "=rk")
2714 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2715 (match_operand:SI 2 "register_operand" "r"))))]
2717 "sub\\t%w0, %w1, %w2"
2718 [(set_attr "type" "alu_sreg")]
2721 (define_insn "subdi3"
2722 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2723 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2724 (match_operand:DI 2 "register_operand" "r,w")))]
2728 sub\\t%d0, %d1, %d2"
2729 [(set_attr "type" "alu_sreg, neon_sub")
2730 (set_attr "arch" "*,simd")]
2733 (define_expand "subv<GPI:mode>4"
2734 [(match_operand:GPI 0 "register_operand")
2735 (match_operand:GPI 1 "register_operand")
2736 (match_operand:GPI 2 "aarch64_plus_operand")
2737 (label_ref (match_operand 3 "" ""))]
2740 if (CONST_INT_P (operands[2]))
2741 emit_insn (gen_subv<mode>_imm (operands[0], operands[1], operands[2]));
2743 emit_insn (gen_subv<mode>_insn (operands[0], operands[1], operands[2]));
2744 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2749 (define_insn "subv<GPI:mode>_insn"
2750 [(set (reg:CC_V CC_REGNUM)
2754 (match_operand:GPI 1 "register_operand" "rk")
2755 (match_operand:GPI 2 "register_operand" "r")))
2756 (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
2757 (sign_extend:<DWI> (match_dup 2)))))
2758 (set (match_operand:GPI 0 "register_operand" "=r")
2759 (minus:GPI (match_dup 1) (match_dup 2)))]
2761 "subs\\t%<w>0, %<w>1, %<w>2"
2762 [(set_attr "type" "alus_sreg")]
2765 (define_insn "subv<GPI:mode>_imm"
2766 [(set (reg:CC_V CC_REGNUM)
2770 (match_operand:GPI 1 "register_operand" "rk,rk")
2771 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))
2772 (minus:<DWI> (sign_extend:<DWI> (match_dup 1))
2774 (set (match_operand:GPI 0 "register_operand" "=r,r")
2775 (minus:GPI (match_dup 1) (match_dup 2)))]
2778 subs\\t%<w>0, %<w>1, %2
2779 adds\\t%<w>0, %<w>1, #%n2"
2780 [(set_attr "type" "alus_sreg")]
2783 (define_expand "negv<GPI:mode>3"
2784 [(match_operand:GPI 0 "register_operand")
2785 (match_operand:GPI 1 "register_operand")
2786 (label_ref (match_operand 2 "" ""))]
2789 emit_insn (gen_negv<mode>_insn (operands[0], operands[1]));
2790 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
2796 (define_insn "negv<GPI:mode>_insn"
2797 [(set (reg:CC_V CC_REGNUM)
2800 (neg:GPI (match_operand:GPI 1 "register_operand" "r")))
2801 (neg:<DWI> (sign_extend:<DWI> (match_dup 1)))))
2802 (set (match_operand:GPI 0 "register_operand" "=r")
2803 (neg:GPI (match_dup 1)))]
2805 "negs\\t%<w>0, %<w>1"
2806 [(set_attr "type" "alus_sreg")]
2809 (define_insn "negv<GPI:mode>_cmp_only"
2810 [(set (reg:CC_V CC_REGNUM)
2813 (neg:GPI (match_operand:GPI 0 "register_operand" "r")))
2814 (neg:<DWI> (sign_extend:<DWI> (match_dup 0)))))]
2816 "negs\\t%<w>zr, %<w>0"
2817 [(set_attr "type" "alus_sreg")]
2820 (define_insn "*cmpv<GPI:mode>_insn"
2821 [(set (reg:CC_V CC_REGNUM)
2824 (minus:GPI (match_operand:GPI 0 "register_operand" "r,r,r")
2825 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))
2826 (minus:<DWI> (sign_extend:<DWI> (match_dup 0))
2827 (sign_extend:<DWI> (match_dup 1)))))]
2833 [(set_attr "type" "alus_sreg")]
2836 (define_expand "usubv<mode>4"
2837 [(match_operand:GPI 0 "register_operand")
2838 (match_operand:GPI 1 "aarch64_reg_or_zero")
2839 (match_operand:GPI 2 "aarch64_reg_or_zero")
2840 (label_ref (match_operand 3 "" ""))]
2843 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
2844 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
2849 (define_expand "subti3"
2850 [(set (match_operand:TI 0 "register_operand" "")
2851 (minus:TI (match_operand:TI 1 "aarch64_reg_or_zero" "")
2852 (match_operand:TI 2 "register_operand" "")))]
2855 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2857 aarch64_subvti_scratch_regs (operands[1], operands[2],
2858 &low_dest, &op1_low, &op2_low,
2859 &high_dest, &op1_high, &op2_high);
2861 emit_insn (gen_subdi3_compare1 (low_dest, op1_low, op2_low));
2862 emit_insn (gen_subdi3_carryin (high_dest, op1_high, op2_high));
2864 emit_move_insn (gen_lowpart (DImode, operands[0]), low_dest);
2865 emit_move_insn (gen_highpart (DImode, operands[0]), high_dest);
2869 (define_expand "subvti4"
2870 [(match_operand:TI 0 "register_operand")
2871 (match_operand:TI 1 "register_operand")
2872 (match_operand:TI 2 "aarch64_reg_or_imm")
2873 (label_ref (match_operand 3 "" ""))]
2876 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2878 aarch64_subvti_scratch_regs (operands[1], operands[2],
2879 &low_dest, &op1_low, &op2_low,
2880 &high_dest, &op1_high, &op2_high);
2881 aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
2882 high_dest, op1_high, op2_high, false);
2884 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
2888 (define_expand "usubvti4"
2889 [(match_operand:TI 0 "register_operand")
2890 (match_operand:TI 1 "register_operand")
2891 (match_operand:TI 2 "aarch64_reg_or_imm")
2892 (label_ref (match_operand 3 "" ""))]
2895 rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
2897 aarch64_subvti_scratch_regs (operands[1], operands[2],
2898 &low_dest, &op1_low, &op2_low,
2899 &high_dest, &op1_high, &op2_high);
2900 aarch64_expand_subvti (operands[0], low_dest, op1_low, op2_low,
2901 high_dest, op1_high, op2_high, true);
2903 aarch64_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
2907 (define_expand "negvti3"
2908 [(match_operand:TI 0 "register_operand")
2909 (match_operand:TI 1 "register_operand")
2910 (label_ref (match_operand 2 "" ""))]
2913 emit_insn (gen_negdi_carryout (gen_lowpart (DImode, operands[0]),
2914 gen_lowpart (DImode, operands[1])));
2915 emit_insn (gen_negvdi_carryinV (gen_highpart (DImode, operands[0]),
2916 gen_highpart (DImode, operands[1])));
2917 aarch64_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
2923 (define_insn "negdi_carryout"
2924 [(set (reg:CC CC_REGNUM)
2926 (const_int 0) (match_operand:DI 1 "register_operand" "r")))
2927 (set (match_operand:DI 0 "register_operand" "=r")
2928 (neg:DI (match_dup 1)))]
2931 [(set_attr "type" "alus_sreg")]
2934 (define_insn "negvdi_carryinV"
2935 [(set (reg:CC_V CC_REGNUM)
2938 (ltu:TI (reg:CC CC_REGNUM) (const_int 0))
2939 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))))
2941 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
2943 (set (match_operand:DI 0 "register_operand" "=r")
2944 (neg:DI (plus:DI (ltu:DI (reg:CC CC_REGNUM) (const_int 0))
2948 [(set_attr "type" "alus_sreg")]
2951 (define_insn "*sub<mode>3_compare0"
2952 [(set (reg:CC_NZ CC_REGNUM)
2953 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2954 (match_operand:GPI 2 "register_operand" "r"))
2956 (set (match_operand:GPI 0 "register_operand" "=r")
2957 (minus:GPI (match_dup 1) (match_dup 2)))]
2959 "subs\\t%<w>0, %<w>1, %<w>2"
2960 [(set_attr "type" "alus_sreg")]
2963 ;; zero_extend version of above
2964 (define_insn "*subsi3_compare0_uxtw"
2965 [(set (reg:CC_NZ CC_REGNUM)
2966 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "rk")
2967 (match_operand:SI 2 "register_operand" "r"))
2969 (set (match_operand:DI 0 "register_operand" "=r")
2970 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2972 "subs\\t%w0, %w1, %w2"
2973 [(set_attr "type" "alus_sreg")]
2976 (define_insn "sub<mode>3_compare1_imm"
2977 [(set (reg:CC CC_REGNUM)
2979 (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ,rkZ")
2980 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))
2981 (set (match_operand:GPI 0 "register_operand" "=r,r")
2984 (match_operand:GPI 3 "aarch64_plus_immediate" "J,I")))]
2985 "UINTVAL (operands[2]) == -UINTVAL (operands[3])"
2987 subs\\t%<w>0, %<w>1, %2
2988 adds\\t%<w>0, %<w>1, #%n2"
2989 [(set_attr "type" "alus_imm")]
2992 (define_insn "sub<mode>3_compare1"
2993 [(set (reg:CC CC_REGNUM)
2995 (match_operand:GPI 1 "aarch64_reg_or_zero" "rkZ")
2996 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2997 (set (match_operand:GPI 0 "register_operand" "=r")
2998 (minus:GPI (match_dup 1) (match_dup 2)))]
3000 "subs\\t%<w>0, %<w>1, %<w>2"
3001 [(set_attr "type" "alus_sreg")]
3005 [(set (match_operand:GPI 0 "aarch64_general_reg")
3006 (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
3007 (match_operand:GPI 2 "aarch64_reg_or_zero")))
3008 (set (reg:CC CC_REGNUM)
3012 "!reg_overlap_mentioned_p (operands[0], operands[1])
3013 && !reg_overlap_mentioned_p (operands[0], operands[2])"
3016 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
3022 ;; Same as the above peephole but with the compare and minus in
3023 ;; swapped order. The restriction on overlap between operand 0
3024 ;; and operands 1 and 2 doesn't apply here.
3026 [(set (reg:CC CC_REGNUM)
3028 (match_operand:GPI 1 "aarch64_reg_or_zero")
3029 (match_operand:GPI 2 "aarch64_reg_or_zero")))
3030 (set (match_operand:GPI 0 "aarch64_general_reg")
3031 (minus:GPI (match_dup 1)
3036 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
3043 [(set (match_operand:GPI 0 "aarch64_general_reg")
3044 (plus:GPI (match_operand:GPI 1 "register_operand")
3045 (match_operand:GPI 2 "aarch64_plus_immediate")))
3046 (set (reg:CC CC_REGNUM)
3049 (match_operand:GPI 3 "const_int_operand")))]
3050 "!reg_overlap_mentioned_p (operands[0], operands[1])
3051 && INTVAL (operands[3]) == -INTVAL (operands[2])"
3054 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3055 operands[3], operands[2]));
3060 ;; Same as the above peephole but with the compare and minus in
3061 ;; swapped order. The restriction on overlap between operand 0
3062 ;; and operands 1 doesn't apply here.
3064 [(set (reg:CC CC_REGNUM)
3066 (match_operand:GPI 1 "register_operand")
3067 (match_operand:GPI 3 "const_int_operand")))
3068 (set (match_operand:GPI 0 "aarch64_general_reg")
3069 (plus:GPI (match_dup 1)
3070 (match_operand:GPI 2 "aarch64_plus_immediate")))]
3071 "INTVAL (operands[3]) == -INTVAL (operands[2])"
3074 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
3075 operands[3], operands[2]));
3080 (define_insn "*sub_<shift>_<mode>"
3081 [(set (match_operand:GPI 0 "register_operand" "=r")
3082 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3084 (match_operand:GPI 1 "register_operand" "r")
3085 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3087 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
3088 [(set_attr "type" "alu_shift_imm")]
3091 ;; zero_extend version of above
3092 (define_insn "*sub_<shift>_si_uxtw"
3093 [(set (match_operand:DI 0 "register_operand" "=r")
3095 (minus:SI (match_operand:SI 3 "register_operand" "r")
3097 (match_operand:SI 1 "register_operand" "r")
3098 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
3100 "sub\\t%w0, %w3, %w1, <shift> %2"
3101 [(set_attr "type" "alu_shift_imm")]
3104 (define_insn "*sub_mul_imm_<mode>"
3105 [(set (match_operand:GPI 0 "register_operand" "=r")
3106 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3108 (match_operand:GPI 1 "register_operand" "r")
3109 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
3111 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
3112 [(set_attr "type" "alu_shift_imm")]
3115 ;; zero_extend version of above
3116 (define_insn "*sub_mul_imm_si_uxtw"
3117 [(set (match_operand:DI 0 "register_operand" "=r")
3119 (minus:SI (match_operand:SI 3 "register_operand" "r")
3121 (match_operand:SI 1 "register_operand" "r")
3122 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
3124 "sub\\t%w0, %w3, %w1, lsl %p2"
3125 [(set_attr "type" "alu_shift_imm")]
3128 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
3129 [(set (match_operand:GPI 0 "register_operand" "=rk")
3130 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3132 (match_operand:ALLX 2 "register_operand" "r"))))]
3134 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
3135 [(set_attr "type" "alu_ext")]
3138 ;; zero_extend version of above
3139 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
3140 [(set (match_operand:DI 0 "register_operand" "=rk")
3142 (minus:SI (match_operand:SI 1 "register_operand" "rk")
3144 (match_operand:SHORT 2 "register_operand" "r")))))]
3146 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
3147 [(set_attr "type" "alu_ext")]
3150 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
3151 [(set (match_operand:GPI 0 "register_operand" "=rk")
3152 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
3153 (ashift:GPI (ANY_EXTEND:GPI
3154 (match_operand:ALLX 2 "register_operand" "r"))
3155 (match_operand 3 "aarch64_imm3" "Ui3"))))]
3157 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
3158 [(set_attr "type" "alu_ext")]
3161 ;; zero_extend version of above
3162 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
3163 [(set (match_operand:DI 0 "register_operand" "=rk")
3165 (minus:SI (match_operand:SI 1 "register_operand" "rk")
3166 (ashift:SI (ANY_EXTEND:SI
3167 (match_operand:SHORT 2 "register_operand" "r"))
3168 (match_operand 3 "aarch64_imm3" "Ui3")))))]
3170 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
3171 [(set_attr "type" "alu_ext")]
3174 (define_insn "*sub_<optab><mode>_multp2"
3175 [(set (match_operand:GPI 0 "register_operand" "=rk")
3176 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
3178 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3179 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
3180 (match_operand 3 "const_int_operand" "n")
3182 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
3183 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
3184 [(set_attr "type" "alu_ext")]
3187 ;; zero_extend version of above
3188 (define_insn "*sub_<optab>si_multp2_uxtw"
3189 [(set (match_operand:DI 0 "register_operand" "=rk")
3191 (minus:SI (match_operand:SI 4 "register_operand" "rk")
3193 (mult:SI (match_operand:SI 1 "register_operand" "r")
3194 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
3195 (match_operand 3 "const_int_operand" "n")
3197 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
3198 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
3199 [(set_attr "type" "alu_ext")]
3202 ;; The hardware description is op1 + ~op2 + C.
3203 ;; = op1 + (-op2 + 1) + (1 - !C)
3204 ;; = op1 - op2 - 1 + 1 - !C
3205 ;; = op1 - op2 - !C.
3206 ;; We describe the latter.
3208 (define_insn "*sub<mode>3_carryin0"
3209 [(set (match_operand:GPI 0 "register_operand" "=r")
3211 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3212 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
3214 "sbc\\t%<w>0, %<w>1, <w>zr"
3215 [(set_attr "type" "adc_reg")]
3218 ;; zero_extend version of the above
3219 (define_insn "*subsi3_carryin_uxtw"
3220 [(set (match_operand:DI 0 "register_operand" "=r")
3223 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3224 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
3226 "sbc\\t%w0, %w1, wzr"
3227 [(set_attr "type" "adc_reg")]
3230 (define_expand "sub<mode>3_carryin"
3231 [(set (match_operand:GPI 0 "register_operand")
3234 (match_operand:GPI 1 "aarch64_reg_or_zero")
3235 (match_operand:GPI 2 "register_operand"))
3236 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
3241 (define_insn "*sub<mode>3_carryin"
3242 [(set (match_operand:GPI 0 "register_operand" "=r")
3245 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3246 (match_operand:GPI 2 "register_operand" "r"))
3247 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3250 "sbc\\t%<w>0, %<w>1, %<w>2"
3251 [(set_attr "type" "adc_reg")]
3254 ;; zero_extend version of the above
3255 (define_insn "*subsi3_carryin_uxtw"
3256 [(set (match_operand:DI 0 "register_operand" "=r")
3260 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3261 (match_operand:SI 2 "register_operand" "r"))
3262 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
3265 "sbc\\t%w0, %w1, %w2"
3266 [(set_attr "type" "adc_reg")]
3269 (define_insn "*sub<mode>3_carryin_alt"
3270 [(set (match_operand:GPI 0 "register_operand" "=r")
3273 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
3274 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
3275 (match_operand:GPI 2 "register_operand" "r")))]
3277 "sbc\\t%<w>0, %<w>1, %<w>2"
3278 [(set_attr "type" "adc_reg")]
3281 ;; zero_extend version of the above
3282 (define_insn "*subsi3_carryin_alt_uxtw"
3283 [(set (match_operand:DI 0 "register_operand" "=r")
3287 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
3288 (match_operand:SI 3 "aarch64_borrow_operation" ""))
3289 (match_operand:SI 2 "register_operand" "r"))))]
3291 "sbc\\t%w0, %w1, %w2"
3292 [(set_attr "type" "adc_reg")]
3295 (define_expand "usub<GPI:mode>3_carryinC"
3297 [(set (reg:CC CC_REGNUM)
3300 (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
3303 (match_operand:GPI 2 "register_operand" ""))
3304 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0)))))
3305 (set (match_operand:GPI 0 "register_operand" "")
3307 (minus:GPI (match_dup 1) (match_dup 2))
3308 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3312 (define_insn "*usub<GPI:mode>3_carryinC_z1"
3313 [(set (reg:CC CC_REGNUM)
3318 (match_operand:GPI 1 "register_operand" "r"))
3319 (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))))
3320 (set (match_operand:GPI 0 "register_operand" "=r")
3322 (neg:GPI (match_dup 1))
3323 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3325 "sbcs\\t%<w>0, <w>zr, %<w>1"
3326 [(set_attr "type" "adc_reg")]
3329 (define_insn "*usub<GPI:mode>3_carryinC_z2"
3330 [(set (reg:CC CC_REGNUM)
3333 (match_operand:GPI 1 "register_operand" "r"))
3334 (match_operand:<DWI> 2 "aarch64_borrow_operation" "")))
3335 (set (match_operand:GPI 0 "register_operand" "=r")
3338 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
3340 "sbcs\\t%<w>0, %<w>1, <w>zr"
3341 [(set_attr "type" "adc_reg")]
3344 (define_insn "*usub<GPI:mode>3_carryinC"
3345 [(set (reg:CC CC_REGNUM)
3348 (match_operand:GPI 1 "register_operand" "r"))
3351 (match_operand:GPI 2 "register_operand" "r"))
3352 (match_operand:<DWI> 3 "aarch64_borrow_operation" ""))))
3353 (set (match_operand:GPI 0 "register_operand" "=r")
3355 (minus:GPI (match_dup 1) (match_dup 2))
3356 (match_operand:GPI 4 "aarch64_borrow_operation" "")))]
3358 "sbcs\\t%<w>0, %<w>1, %<w>2"
3359 [(set_attr "type" "adc_reg")]
3362 (define_expand "sub<GPI:mode>3_carryinV"
3364 [(set (reg:CC_V CC_REGNUM)
3368 (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
3371 (match_operand:GPI 2 "register_operand" ""))
3372 (ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0))))
3374 (minus:GPI (match_dup 1)
3375 (plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))
3377 (set (match_operand:GPI 0 "register_operand" "")
3379 (minus:GPI (match_dup 1) (match_dup 2))
3380 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
3384 (define_insn "*sub<mode>3_carryinV_z2"
3385 [(set (reg:CC_V CC_REGNUM)
3388 (sign_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
3389 (match_operand:<DWI> 2 "aarch64_borrow_operation" ""))
3391 (minus:GPI (match_dup 1)
3392 (match_operand:GPI 3 "aarch64_borrow_operation" "")))))
3393 (set (match_operand:GPI 0 "register_operand" "=r")
3395 (match_dup 1) (match_dup 3)))]
3397 "sbcs\\t%<w>0, %<w>1, <w>zr"
3398 [(set_attr "type" "adc_reg")]
3401 (define_insn "*sub<mode>3_carryinV"
3402 [(set (reg:CC_V CC_REGNUM)
3406 (match_operand:GPI 1 "register_operand" "r"))
3409 (match_operand:GPI 2 "register_operand" "r"))
3410 (match_operand:<DWI> 3 "aarch64_borrow_operation" "")))
3414 (plus:GPI (match_operand:GPI 4 "aarch64_borrow_operation" "")
3416 (set (match_operand:GPI 0 "register_operand" "=r")
3418 (minus:GPI (match_dup 1) (match_dup 2))
3421 "sbcs\\t%<w>0, %<w>1, %<w>2"
3422 [(set_attr "type" "adc_reg")]
3425 (define_insn "*sub_uxt<mode>_shift2"
3426 [(set (match_operand:GPI 0 "register_operand" "=rk")
3427 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
3429 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
3430 (match_operand 2 "aarch64_imm3" "Ui3"))
3431 (match_operand 3 "const_int_operand" "n"))))]
3432 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
3434 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3435 INTVAL (operands[3])));
3436 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
3437 [(set_attr "type" "alu_ext")]
3440 ;; zero_extend version of above
3441 (define_insn "*sub_uxtsi_shift2_uxtw"
3442 [(set (match_operand:DI 0 "register_operand" "=rk")
3444 (minus:SI (match_operand:SI 4 "register_operand" "rk")
3446 (ashift:SI (match_operand:SI 1 "register_operand" "r")
3447 (match_operand 2 "aarch64_imm3" "Ui3"))
3448 (match_operand 3 "const_int_operand" "n")))))]
3449 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
3451 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
3452 INTVAL (operands[3])));
3453 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
3454 [(set_attr "type" "alu_ext")]
3457 (define_insn "*sub_uxt<mode>_multp2"
3458 [(set (match_operand:GPI 0 "register_operand" "=rk")
3459 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
3461 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3462 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
3463 (match_operand 3 "const_int_operand" "n"))))]
3464 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
3466 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
3467 INTVAL (operands[3])));
3468 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
3469 [(set_attr "type" "alu_ext")]
3472 ;; zero_extend version of above
3473 (define_insn "*sub_uxtsi_multp2_uxtw"
3474 [(set (match_operand:DI 0 "register_operand" "=rk")
3476 (minus:SI (match_operand:SI 4 "register_operand" "rk")
3478 (mult:SI (match_operand:SI 1 "register_operand" "r")
3479 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
3480 (match_operand 3 "const_int_operand" "n")))))]
3481 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
3483 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
3484 INTVAL (operands[3])));
3485 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
3486 [(set_attr "type" "alu_ext")]
3489 (define_expand "abs<mode>2"
3490 [(match_operand:GPI 0 "register_operand" "")
3491 (match_operand:GPI 1 "register_operand" "")]
3494 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
3495 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
3496 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
3501 (define_insn "neg<mode>2"
3502 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3503 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3507 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
3508 [(set_attr "type" "alu_sreg, neon_neg<q>")
3509 (set_attr "arch" "*,simd")]
3512 ;; zero_extend version of above
3513 (define_insn "*negsi2_uxtw"
3514 [(set (match_operand:DI 0 "register_operand" "=r")
3515 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
3518 [(set_attr "type" "alu_sreg")]
3521 (define_insn "*ngc<mode>"
3522 [(set (match_operand:GPI 0 "register_operand" "=r")
3524 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
3525 (match_operand:GPI 1 "register_operand" "r")))]
3527 "ngc\\t%<w>0, %<w>1"
3528 [(set_attr "type" "adc_reg")]
3531 (define_insn "*ngcsi_uxtw"
3532 [(set (match_operand:DI 0 "register_operand" "=r")
3535 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
3536 (match_operand:SI 1 "register_operand" "r"))))]
3539 [(set_attr "type" "adc_reg")]
3542 (define_insn "neg<mode>2_compare0"
3543 [(set (reg:CC_NZ CC_REGNUM)
3544 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
3546 (set (match_operand:GPI 0 "register_operand" "=r")
3547 (neg:GPI (match_dup 1)))]
3549 "negs\\t%<w>0, %<w>1"
3550 [(set_attr "type" "alus_sreg")]
3553 ;; zero_extend version of above
3554 (define_insn "*negsi2_compare0_uxtw"
3555 [(set (reg:CC_NZ CC_REGNUM)
3556 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
3558 (set (match_operand:DI 0 "register_operand" "=r")
3559 (zero_extend:DI (neg:SI (match_dup 1))))]
3562 [(set_attr "type" "alus_sreg")]
3565 (define_insn "*neg_<shift><mode>3_compare0"
3566 [(set (reg:CC_NZ CC_REGNUM)
3568 (neg:GPI (ASHIFT:GPI
3569 (match_operand:GPI 1 "register_operand" "r")
3570 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3572 (set (match_operand:GPI 0 "register_operand" "=r")
3573 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
3575 "negs\\t%<w>0, %<w>1, <shift> %2"
3576 [(set_attr "type" "alus_shift_imm")]
3579 (define_insn "*neg_<shift>_<mode>2"
3580 [(set (match_operand:GPI 0 "register_operand" "=r")
3581 (neg:GPI (ASHIFT:GPI
3582 (match_operand:GPI 1 "register_operand" "r")
3583 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3585 "neg\\t%<w>0, %<w>1, <shift> %2"
3586 [(set_attr "type" "alu_shift_imm")]
3589 ;; zero_extend version of above
3590 (define_insn "*neg_<shift>_si2_uxtw"
3591 [(set (match_operand:DI 0 "register_operand" "=r")
3594 (match_operand:SI 1 "register_operand" "r")
3595 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
3597 "neg\\t%w0, %w1, <shift> %2"
3598 [(set_attr "type" "alu_shift_imm")]
3601 (define_insn "*neg_mul_imm_<mode>2"
3602 [(set (match_operand:GPI 0 "register_operand" "=r")
3604 (match_operand:GPI 1 "register_operand" "r")
3605 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
3607 "neg\\t%<w>0, %<w>1, lsl %p2"
3608 [(set_attr "type" "alu_shift_imm")]
3611 ;; zero_extend version of above
3612 (define_insn "*neg_mul_imm_si2_uxtw"
3613 [(set (match_operand:DI 0 "register_operand" "=r")
3616 (match_operand:SI 1 "register_operand" "r")
3617 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
3619 "neg\\t%w0, %w1, lsl %p2"
3620 [(set_attr "type" "alu_shift_imm")]
3623 (define_insn "mul<mode>3"
3624 [(set (match_operand:GPI 0 "register_operand" "=r")
3625 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3626 (match_operand:GPI 2 "register_operand" "r")))]
3628 "mul\\t%<w>0, %<w>1, %<w>2"
3629 [(set_attr "type" "mul")]
3632 ;; zero_extend version of above
3633 (define_insn "*mulsi3_uxtw"
3634 [(set (match_operand:DI 0 "register_operand" "=r")
3636 (mult:SI (match_operand:SI 1 "register_operand" "r")
3637 (match_operand:SI 2 "register_operand" "r"))))]
3639 "mul\\t%w0, %w1, %w2"
3640 [(set_attr "type" "mul")]
3643 (define_insn "madd<mode>"
3644 [(set (match_operand:GPI 0 "register_operand" "=r")
3645 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3646 (match_operand:GPI 2 "register_operand" "r"))
3647 (match_operand:GPI 3 "register_operand" "r")))]
3649 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
3650 [(set_attr "type" "mla")]
3653 ;; zero_extend version of above
3654 (define_insn "*maddsi_uxtw"
3655 [(set (match_operand:DI 0 "register_operand" "=r")
3657 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
3658 (match_operand:SI 2 "register_operand" "r"))
3659 (match_operand:SI 3 "register_operand" "r"))))]
3661 "madd\\t%w0, %w1, %w2, %w3"
3662 [(set_attr "type" "mla")]
3665 (define_insn "*msub<mode>"
3666 [(set (match_operand:GPI 0 "register_operand" "=r")
3667 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
3668 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
3669 (match_operand:GPI 2 "register_operand" "r"))))]
3672 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
3673 [(set_attr "type" "mla")]
3676 ;; zero_extend version of above
3677 (define_insn "*msubsi_uxtw"
3678 [(set (match_operand:DI 0 "register_operand" "=r")
3680 (minus:SI (match_operand:SI 3 "register_operand" "r")
3681 (mult:SI (match_operand:SI 1 "register_operand" "r")
3682 (match_operand:SI 2 "register_operand" "r")))))]
3685 "msub\\t%w0, %w1, %w2, %w3"
3686 [(set_attr "type" "mla")]
3689 (define_insn "*mul<mode>_neg"
3690 [(set (match_operand:GPI 0 "register_operand" "=r")
3691 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
3692 (match_operand:GPI 2 "register_operand" "r")))]
3695 "mneg\\t%<w>0, %<w>1, %<w>2"
3696 [(set_attr "type" "mul")]
3699 ;; zero_extend version of above
3700 (define_insn "*mulsi_neg_uxtw"
3701 [(set (match_operand:DI 0 "register_operand" "=r")
3703 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
3704 (match_operand:SI 2 "register_operand" "r"))))]
3707 "mneg\\t%w0, %w1, %w2"
3708 [(set_attr "type" "mul")]
3711 (define_insn "<su_optab>mulsidi3"
3712 [(set (match_operand:DI 0 "register_operand" "=r")
3713 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3714 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
3716 "<su>mull\\t%0, %w1, %w2"
3717 [(set_attr "type" "<su>mull")]
3720 (define_insn "<su_optab>maddsidi4"
3721 [(set (match_operand:DI 0 "register_operand" "=r")
3723 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3724 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
3725 (match_operand:DI 3 "register_operand" "r")))]
3727 "<su>maddl\\t%0, %w1, %w2, %3"
3728 [(set_attr "type" "<su>mlal")]
3731 (define_insn "<su_optab>msubsidi4"
3732 [(set (match_operand:DI 0 "register_operand" "=r")
3734 (match_operand:DI 3 "register_operand" "r")
3735 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
3737 (match_operand:SI 2 "register_operand" "r")))))]
3739 "<su>msubl\\t%0, %w1, %w2, %3"
3740 [(set_attr "type" "<su>mlal")]
3743 (define_insn "*<su_optab>mulsidi_neg"
3744 [(set (match_operand:DI 0 "register_operand" "=r")
3746 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
3747 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
3749 "<su>mnegl\\t%0, %w1, %w2"
3750 [(set_attr "type" "<su>mull")]
3753 (define_expand "<su_optab>mulditi3"
3754 [(set (match_operand:TI 0 "register_operand")
3755 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
3756 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
3759 rtx low = gen_reg_rtx (DImode);
3760 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
3762 rtx high = gen_reg_rtx (DImode);
3763 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
3765 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
3766 emit_move_insn (gen_highpart (DImode, operands[0]), high);
3770 ;; The default expansion of multi3 using umuldi3_highpart will perform
3771 ;; the additions in an order that fails to combine into two madd insns.
3772 (define_expand "multi3"
3773 [(set (match_operand:TI 0 "register_operand")
3774 (mult:TI (match_operand:TI 1 "register_operand")
3775 (match_operand:TI 2 "register_operand")))]
3778 rtx l0 = gen_reg_rtx (DImode);
3779 rtx l1 = gen_lowpart (DImode, operands[1]);
3780 rtx l2 = gen_lowpart (DImode, operands[2]);
3781 rtx h0 = gen_reg_rtx (DImode);
3782 rtx h1 = gen_highpart (DImode, operands[1]);
3783 rtx h2 = gen_highpart (DImode, operands[2]);
3785 emit_insn (gen_muldi3 (l0, l1, l2));
3786 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3787 emit_insn (gen_madddi (h0, h1, l2, h0));
3788 emit_insn (gen_madddi (h0, l1, h2, h0));
3790 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
3791 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
3795 (define_insn "<su>muldi3_highpart"
3796 [(set (match_operand:DI 0 "register_operand" "=r")
3800 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
3801 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
3804 "<su>mulh\\t%0, %1, %2"
3805 [(set_attr "type" "<su>mull")]
3808 (define_insn "<su_optab>div<mode>3"
3809 [(set (match_operand:GPI 0 "register_operand" "=r")
3810 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
3811 (match_operand:GPI 2 "register_operand" "r")))]
3813 "<su>div\\t%<w>0, %<w>1, %<w>2"
3814 [(set_attr "type" "<su>div")]
3817 ;; zero_extend version of above
3818 (define_insn "*<su_optab>divsi3_uxtw"
3819 [(set (match_operand:DI 0 "register_operand" "=r")
3821 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
3822 (match_operand:SI 2 "register_operand" "r"))))]
3824 "<su>div\\t%w0, %w1, %w2"
3825 [(set_attr "type" "<su>div")]
3828 ;; -------------------------------------------------------------------
3830 ;; -------------------------------------------------------------------
3832 (define_insn "cmp<mode>"
3833 [(set (reg:CC CC_REGNUM)
3834 (compare:CC (match_operand:GPI 0 "register_operand" "rk,rk,rk")
3835 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
3841 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3844 (define_insn "fcmp<mode>"
3845 [(set (reg:CCFP CC_REGNUM)
3846 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
3847 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3851 fcmp\\t%<s>0, %<s>1"
3852 [(set_attr "type" "fcmp<s>")]
3855 (define_insn "fcmpe<mode>"
3856 [(set (reg:CCFPE CC_REGNUM)
3857 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
3858 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3862 fcmpe\\t%<s>0, %<s>1"
3863 [(set_attr "type" "fcmp<s>")]
3866 (define_insn "*cmp_swp_<shift>_reg<mode>"
3867 [(set (reg:CC_SWP CC_REGNUM)
3868 (compare:CC_SWP (ASHIFT:GPI
3869 (match_operand:GPI 0 "register_operand" "r")
3870 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3871 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3873 "cmp\\t%<w>2, %<w>0, <shift> %1"
3874 [(set_attr "type" "alus_shift_imm")]
3877 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3878 [(set (reg:CC_SWP CC_REGNUM)
3879 (compare:CC_SWP (ANY_EXTEND:GPI
3880 (match_operand:ALLX 0 "register_operand" "r"))
3881 (match_operand:GPI 1 "register_operand" "r")))]
3883 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3884 [(set_attr "type" "alus_ext")]
3887 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3888 [(set (reg:CC_SWP CC_REGNUM)
3889 (compare:CC_SWP (ashift:GPI
3891 (match_operand:ALLX 0 "register_operand" "r"))
3892 (match_operand 1 "aarch64_imm3" "Ui3"))
3893 (match_operand:GPI 2 "register_operand" "r")))]
3895 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3896 [(set_attr "type" "alus_ext")]
3899 ;; -------------------------------------------------------------------
3900 ;; Store-flag and conditional select insns
3901 ;; -------------------------------------------------------------------
3903 (define_expand "cstore<mode>4"
3904 [(set (match_operand:SI 0 "register_operand" "")
3905 (match_operator:SI 1 "aarch64_comparison_operator"
3906 [(match_operand:GPI 2 "register_operand" "")
3907 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3910 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3912 operands[3] = const0_rtx;
3916 (define_expand "cstorecc4"
3917 [(set (match_operand:SI 0 "register_operand")
3918 (match_operator 1 "aarch64_comparison_operator_mode"
3919 [(match_operand 2 "cc_register")
3920 (match_operand 3 "const0_operand")]))]
3923 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3928 (define_expand "cstore<mode>4"
3929 [(set (match_operand:SI 0 "register_operand" "")
3930 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3931 [(match_operand:GPF 2 "register_operand" "")
3932 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3935 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3937 operands[3] = const0_rtx;
3941 (define_insn "aarch64_cstore<mode>"
3942 [(set (match_operand:ALLI 0 "register_operand" "=r")
3943 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3944 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3947 [(set_attr "type" "csel")]
3950 ;; For a 24-bit immediate CST we can optimize the compare for equality
3951 ;; and branch sequence from:
3953 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3956 ;; into the shorter:
3957 ;; sub x0, x1, #(CST & 0xfff000)
3958 ;; subs x0, x0, #(CST & 0x000fff)
3959 ;; cset x2, <ne, eq>.
3960 (define_insn_and_split "*compare_cstore<mode>_insn"
3961 [(set (match_operand:GPI 0 "register_operand" "=r")
3962 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3963 (match_operand:GPI 2 "aarch64_imm24" "n")))
3964 (clobber (reg:CC CC_REGNUM))]
3965 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3966 && !aarch64_plus_operand (operands[2], <MODE>mode)
3967 && !reload_completed"
3972 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3973 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3974 rtx tmp = gen_reg_rtx (<MODE>mode);
3975 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3976 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3977 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3978 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3979 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3982 [(set_attr "type" "csel")]
3985 ;; zero_extend version of the above
3986 (define_insn "*cstoresi_insn_uxtw"
3987 [(set (match_operand:DI 0 "register_operand" "=r")
3989 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3990 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3993 [(set_attr "type" "csel")]
3996 (define_insn "cstore<mode>_neg"
3997 [(set (match_operand:ALLI 0 "register_operand" "=r")
3998 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3999 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4001 "csetm\\t%<w>0, %m1"
4002 [(set_attr "type" "csel")]
4005 ;; zero_extend version of the above
4006 (define_insn "*cstoresi_neg_uxtw"
4007 [(set (match_operand:DI 0 "register_operand" "=r")
4009 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
4010 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
4013 [(set_attr "type" "csel")]
4016 (define_expand "cmov<mode>6"
4017 [(set (match_operand:GPI 0 "register_operand" "")
4019 (match_operator 1 "aarch64_comparison_operator"
4020 [(match_operand:GPI 2 "register_operand" "")
4021 (match_operand:GPI 3 "aarch64_plus_operand" "")])
4022 (match_operand:GPI 4 "register_operand" "")
4023 (match_operand:GPI 5 "register_operand" "")))]
4026 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4028 operands[3] = const0_rtx;
4032 (define_expand "cmov<mode>6"
4033 [(set (match_operand:GPF 0 "register_operand" "")
4035 (match_operator 1 "aarch64_comparison_operator"
4036 [(match_operand:GPF 2 "register_operand" "")
4037 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
4038 (match_operand:GPF 4 "register_operand" "")
4039 (match_operand:GPF 5 "register_operand" "")))]
4042 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
4044 operands[3] = const0_rtx;
4048 (define_insn "*cmov<mode>_insn"
4049 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
4051 (match_operator 1 "aarch64_comparison_operator"
4052 [(match_operand 2 "cc_register" "") (const_int 0)])
4053 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4054 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
4055 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
4056 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
4057 ;; Final two alternatives should be unreachable, but included for completeness
4059 csel\\t%<w>0, %<w>3, %<w>4, %m1
4060 csinv\\t%<w>0, %<w>3, <w>zr, %m1
4061 csinv\\t%<w>0, %<w>4, <w>zr, %M1
4062 csinc\\t%<w>0, %<w>3, <w>zr, %m1
4063 csinc\\t%<w>0, %<w>4, <w>zr, %M1
4066 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4069 ;; zero_extend version of above
4070 (define_insn "*cmovsi_insn_uxtw"
4071 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
4074 (match_operator 1 "aarch64_comparison_operator"
4075 [(match_operand 2 "cc_register" "") (const_int 0)])
4076 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
4077 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
4078 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
4079 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
4080 ;; Final two alternatives should be unreachable, but included for completeness
4082 csel\\t%w0, %w3, %w4, %m1
4083 csinv\\t%w0, %w3, wzr, %m1
4084 csinv\\t%w0, %w4, wzr, %M1
4085 csinc\\t%w0, %w3, wzr, %m1
4086 csinc\\t%w0, %w4, wzr, %M1
4089 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
4092 (define_insn "*cmovdi_insn_uxtw"
4093 [(set (match_operand:DI 0 "register_operand" "=r")
4095 (match_operator 1 "aarch64_comparison_operator"
4096 [(match_operand 2 "cc_register" "") (const_int 0)])
4097 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
4098 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
4100 "csel\\t%w0, %w3, %w4, %m1"
4101 [(set_attr "type" "csel")]
4104 (define_insn "*cmov<mode>_insn"
4105 [(set (match_operand:GPF 0 "register_operand" "=w")
4107 (match_operator 1 "aarch64_comparison_operator"
4108 [(match_operand 2 "cc_register" "") (const_int 0)])
4109 (match_operand:GPF 3 "register_operand" "w")
4110 (match_operand:GPF 4 "register_operand" "w")))]
4112 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
4113 [(set_attr "type" "fcsel")]
4116 (define_expand "mov<mode>cc"
4117 [(set (match_operand:ALLI 0 "register_operand" "")
4118 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
4119 (match_operand:ALLI 2 "register_operand" "")
4120 (match_operand:ALLI 3 "register_operand" "")))]
4124 enum rtx_code code = GET_CODE (operands[1]);
4126 if (code == UNEQ || code == LTGT)
4129 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4130 XEXP (operands[1], 1));
4131 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4135 (define_expand "mov<GPF:mode><GPI:mode>cc"
4136 [(set (match_operand:GPI 0 "register_operand" "")
4137 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
4138 (match_operand:GPF 2 "register_operand" "")
4139 (match_operand:GPF 3 "register_operand" "")))]
4143 enum rtx_code code = GET_CODE (operands[1]);
4145 if (code == UNEQ || code == LTGT)
4148 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4149 XEXP (operands[1], 1));
4150 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4154 (define_expand "mov<mode>cc"
4155 [(set (match_operand:GPF 0 "register_operand" "")
4156 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
4157 (match_operand:GPF 2 "register_operand" "")
4158 (match_operand:GPF 3 "register_operand" "")))]
4162 enum rtx_code code = GET_CODE (operands[1]);
4164 if (code == UNEQ || code == LTGT)
4167 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4168 XEXP (operands[1], 1));
4169 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4173 (define_expand "<neg_not_op><mode>cc"
4174 [(set (match_operand:GPI 0 "register_operand" "")
4175 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
4176 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
4177 (match_operand:GPI 3 "register_operand" "")))]
4181 enum rtx_code code = GET_CODE (operands[1]);
4183 if (code == UNEQ || code == LTGT)
4186 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
4187 XEXP (operands[1], 1));
4188 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
4192 ;; CRC32 instructions.
4193 (define_insn "aarch64_<crc_variant>"
4194 [(set (match_operand:SI 0 "register_operand" "=r")
4195 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
4196 (match_operand:<crc_mode> 2 "register_operand" "r")]
4200 if (GET_MODE_BITSIZE (<crc_mode>mode) >= 64)
4201 return "<crc_variant>\\t%w0, %w1, %x2";
4203 return "<crc_variant>\\t%w0, %w1, %w2";
4205 [(set_attr "type" "crc")]
4208 (define_insn "*csinc2<mode>_insn"
4209 [(set (match_operand:GPI 0 "register_operand" "=r")
4210 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
4211 (match_operand:GPI 1 "register_operand" "r")))]
4213 "cinc\\t%<w>0, %<w>1, %m2"
4214 [(set_attr "type" "csel")]
4217 (define_insn "csinc3<mode>_insn"
4218 [(set (match_operand:GPI 0 "register_operand" "=r")
4220 (match_operand 1 "aarch64_comparison_operation" "")
4221 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
4223 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4225 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
4226 [(set_attr "type" "csel")]
4229 (define_insn "*csinv3<mode>_insn"
4230 [(set (match_operand:GPI 0 "register_operand" "=r")
4232 (match_operand 1 "aarch64_comparison_operation" "")
4233 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
4234 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4236 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
4237 [(set_attr "type" "csel")]
4240 (define_insn "csneg3_uxtw_insn"
4241 [(set (match_operand:DI 0 "register_operand" "=r")
4244 (match_operand 1 "aarch64_comparison_operation" "")
4245 (neg:SI (match_operand:SI 2 "register_operand" "r"))
4246 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
4248 "csneg\\t%w0, %w3, %w2, %M1"
4249 [(set_attr "type" "csel")]
4252 (define_insn "csneg3<mode>_insn"
4253 [(set (match_operand:GPI 0 "register_operand" "=r")
4255 (match_operand 1 "aarch64_comparison_operation" "")
4256 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
4257 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
4259 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
4260 [(set_attr "type" "csel")]
4263 ;; If X can be loaded by a single CNT[BHWD] instruction,
4267 ;; is equivalent to:
4269 ;; TMP = UQDEC[BHWD] (B, X)
4272 ;; Defining the pattern this way means that:
4274 ;; A = UMAX (B, X) - X
4278 ;; TMP1 = UQDEC[BHWD] (B, X)
4282 ;; which combine can optimize to:
4284 ;; A = UQDEC[BHWD] (B, X)
4286 ;; We don't use match_operand predicates because the order of the operands
4287 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
4288 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
4289 (define_expand "umax<mode>3"
4290 [(set (match_operand:GPI 0 "register_operand")
4291 (umax:GPI (match_operand:GPI 1 "")
4292 (match_operand:GPI 2 "")))]
4295 if (aarch64_sve_cnt_immediate (operands[1], <MODE>mode))
4296 std::swap (operands[1], operands[2]);
4297 else if (!aarch64_sve_cnt_immediate (operands[2], <MODE>mode))
4299 rtx temp = gen_reg_rtx (<MODE>mode);
4300 operands[1] = force_reg (<MODE>mode, operands[1]);
4301 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[1], operands[2]));
4302 emit_insn (gen_add<mode>3 (operands[0], temp, operands[2]));
4307 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
4308 (define_insn "aarch64_uqdec<mode>"
4309 [(set (match_operand:GPI 0 "register_operand" "=r")
4311 (umax:GPI (match_operand:GPI 1 "register_operand" "0")
4312 (match_operand:GPI 2 "aarch64_sve_cnt_immediate" "Usv"))
4316 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>0", operands[2]);
4320 ;; -------------------------------------------------------------------
4321 ;; Logical operations
4322 ;; -------------------------------------------------------------------
4325 (define_insn_and_split "*aarch64_and<mode>_imm2"
4326 [(set (match_operand:GPI 0 "register_operand" "=rk")
4327 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
4328 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
4334 HOST_WIDE_INT val = INTVAL (operands[2]);
4335 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
4336 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
4338 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
4339 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
4344 (define_insn "<optab><mode>3"
4345 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
4346 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
4347 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
4350 <logical>\\t%<w>0, %<w>1, %<w>2
4351 <logical>\\t%<w>0, %<w>1, %2
4352 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
4353 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
4354 (set_attr "arch" "*,*,simd")]
4357 ;; zero_extend version of above
4358 (define_insn "*<optab>si3_uxtw"
4359 [(set (match_operand:DI 0 "register_operand" "=r,rk")
4361 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
4362 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
4365 <logical>\\t%w0, %w1, %w2
4366 <logical>\\t%w0, %w1, %2"
4367 [(set_attr "type" "logic_reg,logic_imm")]
4370 (define_insn "*and<mode>3_compare0"
4371 [(set (reg:CC_NZ CC_REGNUM)
4373 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
4374 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
4376 (set (match_operand:GPI 0 "register_operand" "=r,r")
4377 (and:GPI (match_dup 1) (match_dup 2)))]
4380 ands\\t%<w>0, %<w>1, %<w>2
4381 ands\\t%<w>0, %<w>1, %2"
4382 [(set_attr "type" "logics_reg,logics_imm")]
4385 ;; zero_extend version of above
4386 (define_insn "*andsi3_compare0_uxtw"
4387 [(set (reg:CC_NZ CC_REGNUM)
4389 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
4390 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
4392 (set (match_operand:DI 0 "register_operand" "=r,r")
4393 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
4396 ands\\t%w0, %w1, %w2
4397 ands\\t%w0, %w1, %2"
4398 [(set_attr "type" "logics_reg,logics_imm")]
4401 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
4402 [(set (reg:CC_NZ CC_REGNUM)
4405 (match_operand:GPI 1 "register_operand" "r")
4406 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4407 (match_operand:GPI 3 "register_operand" "r"))
4409 (set (match_operand:GPI 0 "register_operand" "=r")
4410 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
4412 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4413 [(set_attr "type" "logics_shift_imm")]
4416 ;; zero_extend version of above
4417 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
4418 [(set (reg:CC_NZ CC_REGNUM)
4421 (match_operand:SI 1 "register_operand" "r")
4422 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4423 (match_operand:SI 3 "register_operand" "r"))
4425 (set (match_operand:DI 0 "register_operand" "=r")
4426 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
4429 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4430 [(set_attr "type" "logics_shift_imm")]
4433 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
4434 [(set (match_operand:GPI 0 "register_operand" "=r")
4435 (LOGICAL:GPI (SHIFT:GPI
4436 (match_operand:GPI 1 "register_operand" "r")
4437 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4438 (match_operand:GPI 3 "register_operand" "r")))]
4440 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4441 [(set_attr "type" "logic_shift_imm")]
4444 (define_insn "*<optab>_rol<mode>3"
4445 [(set (match_operand:GPI 0 "register_operand" "=r")
4446 (LOGICAL:GPI (rotate:GPI
4447 (match_operand:GPI 1 "register_operand" "r")
4448 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4449 (match_operand:GPI 3 "register_operand" "r")))]
4451 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
4452 [(set_attr "type" "logic_shift_imm")]
4455 ;; zero_extend versions of above
4456 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
4457 [(set (match_operand:DI 0 "register_operand" "=r")
4459 (LOGICAL:SI (SHIFT:SI
4460 (match_operand:SI 1 "register_operand" "r")
4461 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4462 (match_operand:SI 3 "register_operand" "r"))))]
4464 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4465 [(set_attr "type" "logic_shift_imm")]
4468 (define_insn "*<optab>_rolsi3_uxtw"
4469 [(set (match_operand:DI 0 "register_operand" "=r")
4471 (LOGICAL:SI (rotate:SI
4472 (match_operand:SI 1 "register_operand" "r")
4473 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4474 (match_operand:SI 3 "register_operand" "r"))))]
4476 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
4477 [(set_attr "type" "logic_shift_imm")]
4480 (define_insn "one_cmpl<mode>2"
4481 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4482 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
4487 [(set_attr "type" "logic_reg,neon_logic")
4488 (set_attr "arch" "*,simd")]
4491 (define_insn "*one_cmpl_<optab><mode>2"
4492 [(set (match_operand:GPI 0 "register_operand" "=r")
4493 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
4494 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
4496 "mvn\\t%<w>0, %<w>1, <shift> %2"
4497 [(set_attr "type" "logic_shift_imm")]
4500 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
4502 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
4503 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4504 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
4505 (match_operand:GPI 2 "register_operand" "r,w")))]
4508 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
4509 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
4510 [(set_attr "type" "logic_reg,neon_logic")
4511 (set_attr "arch" "*,simd")]
4514 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
4515 [(set (match_operand:DI 0 "register_operand" "=r")
4517 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
4518 (match_operand:SI 2 "register_operand" "r"))))]
4520 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
4521 [(set_attr "type" "logic_reg")]
4524 (define_insn "*xor_one_cmplsidi3_ze"
4525 [(set (match_operand:DI 0 "register_operand" "=r")
4527 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
4528 (match_operand:SI 2 "register_operand" "r")))))]
4530 "eon\\t%w0, %w1, %w2"
4531 [(set_attr "type" "logic_reg")]
4534 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
4535 ;; eon does not operate on SIMD registers so the vector variant must be split.
4536 (define_insn_and_split "*xor_one_cmpl<mode>3"
4537 [(set (match_operand:GPI 0 "register_operand" "=r,w")
4538 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
4539 (match_operand:GPI 2 "register_operand" "r,w"))))]
4542 eon\\t%<w>0, %<w>1, %<w>2
4544 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
4545 [(set (match_operand:GPI 0 "register_operand" "=w")
4546 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
4547 (match_operand:GPI 2 "register_operand" "w")))
4548 (set (match_dup 0) (not:GPI (match_dup 0)))]
4550 [(set_attr "type" "logic_reg,multiple")
4551 (set_attr "arch" "*,simd")]
4554 (define_insn "*and_one_cmpl<mode>3_compare0"
4555 [(set (reg:CC_NZ CC_REGNUM)
4558 (match_operand:GPI 1 "register_operand" "r"))
4559 (match_operand:GPI 2 "register_operand" "r"))
4561 (set (match_operand:GPI 0 "register_operand" "=r")
4562 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
4564 "bics\\t%<w>0, %<w>2, %<w>1"
4565 [(set_attr "type" "logics_reg")]
4568 ;; zero_extend version of above
4569 (define_insn "*and_one_cmplsi3_compare0_uxtw"
4570 [(set (reg:CC_NZ CC_REGNUM)
4573 (match_operand:SI 1 "register_operand" "r"))
4574 (match_operand:SI 2 "register_operand" "r"))
4576 (set (match_operand:DI 0 "register_operand" "=r")
4577 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
4579 "bics\\t%w0, %w2, %w1"
4580 [(set_attr "type" "logics_reg")]
4583 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
4584 [(set (reg:CC_NZ CC_REGNUM)
4587 (match_operand:GPI 0 "register_operand" "r"))
4588 (match_operand:GPI 1 "register_operand" "r"))
4591 "bics\\t<w>zr, %<w>1, %<w>0"
4592 [(set_attr "type" "logics_reg")]
4595 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
4596 [(set (match_operand:GPI 0 "register_operand" "=r")
4597 (LOGICAL:GPI (not:GPI
4599 (match_operand:GPI 1 "register_operand" "r")
4600 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
4601 (match_operand:GPI 3 "register_operand" "r")))]
4603 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4604 [(set_attr "type" "logic_shift_imm")]
4607 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
4608 [(set (match_operand:GPI 0 "register_operand" "=r")
4611 (match_operand:GPI 1 "register_operand" "r")
4612 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
4613 (match_operand:GPI 3 "register_operand" "r"))))]
4615 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4616 [(set_attr "type" "logic_shift_imm")]
4619 ;; Zero-extend version of the above.
4620 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
4621 [(set (match_operand:DI 0 "register_operand" "=r")
4625 (match_operand:SI 1 "register_operand" "r")
4626 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
4627 (match_operand:SI 3 "register_operand" "r")))))]
4629 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4630 [(set_attr "type" "logic_shift_imm")]
4633 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
4634 [(set (reg:CC_NZ CC_REGNUM)
4638 (match_operand:GPI 1 "register_operand" "r")
4639 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
4640 (match_operand:GPI 3 "register_operand" "r"))
4642 (set (match_operand:GPI 0 "register_operand" "=r")
4645 (match_dup 1) (match_dup 2))) (match_dup 3)))]
4647 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
4648 [(set_attr "type" "logics_shift_imm")]
4651 ;; zero_extend version of above
4652 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
4653 [(set (reg:CC_NZ CC_REGNUM)
4657 (match_operand:SI 1 "register_operand" "r")
4658 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
4659 (match_operand:SI 3 "register_operand" "r"))
4661 (set (match_operand:DI 0 "register_operand" "=r")
4662 (zero_extend:DI (and:SI
4664 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
4666 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
4667 [(set_attr "type" "logics_shift_imm")]
4670 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
4671 [(set (reg:CC_NZ CC_REGNUM)
4675 (match_operand:GPI 0 "register_operand" "r")
4676 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
4677 (match_operand:GPI 2 "register_operand" "r"))
4680 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
4681 [(set_attr "type" "logics_shift_imm")]
4684 (define_insn "clz<mode>2"
4685 [(set (match_operand:GPI 0 "register_operand" "=r")
4686 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
4688 "clz\\t%<w>0, %<w>1"
4689 [(set_attr "type" "clz")]
4692 (define_expand "ffs<mode>2"
4693 [(match_operand:GPI 0 "register_operand")
4694 (match_operand:GPI 1 "register_operand")]
4697 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
4698 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
4700 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
4701 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
4702 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
4707 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
4714 (define_expand "popcount<mode>2"
4715 [(match_operand:GPI 0 "register_operand")
4716 (match_operand:GPI 1 "register_operand")]
4719 rtx v = gen_reg_rtx (V8QImode);
4720 rtx v1 = gen_reg_rtx (V8QImode);
4721 rtx r = gen_reg_rtx (QImode);
4722 rtx in = operands[1];
4723 rtx out = operands[0];
4724 if(<MODE>mode == SImode)
4727 tmp = gen_reg_rtx (DImode);
4728 /* If we have SImode, zero extend to DImode, pop count does
4729 not change if we have extra zeros. */
4730 emit_insn (gen_zero_extendsidi2 (tmp, in));
4733 emit_move_insn (v, gen_lowpart (V8QImode, in));
4734 emit_insn (gen_popcountv8qi2 (v1, v));
4735 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
4736 emit_insn (gen_zero_extendqi<mode>2 (out, r));
4740 (define_insn "clrsb<mode>2"
4741 [(set (match_operand:GPI 0 "register_operand" "=r")
4742 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
4744 "cls\\t%<w>0, %<w>1"
4745 [(set_attr "type" "clz")]
4748 (define_insn "rbit<mode>2"
4749 [(set (match_operand:GPI 0 "register_operand" "=r")
4750 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
4752 "rbit\\t%<w>0, %<w>1"
4753 [(set_attr "type" "rbit")]
4756 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
4757 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
4758 ;; expression and split after reload to enable scheduling them apart if
4761 (define_insn_and_split "ctz<mode>2"
4762 [(set (match_operand:GPI 0 "register_operand" "=r")
4763 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
4769 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
4770 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
4774 (define_insn "*and<mode>_compare0"
4775 [(set (reg:CC_NZ CC_REGNUM)
4777 (match_operand:SHORT 0 "register_operand" "r")
4780 "tst\\t%<w>0, <short_mask>"
4781 [(set_attr "type" "alus_imm")]
4784 (define_insn "*ands<mode>_compare0"
4785 [(set (reg:CC_NZ CC_REGNUM)
4787 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
4789 (set (match_operand:GPI 0 "register_operand" "=r")
4790 (zero_extend:GPI (match_dup 1)))]
4792 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
4793 [(set_attr "type" "alus_imm")]
4796 (define_insn "*and<mode>3nr_compare0"
4797 [(set (reg:CC_NZ CC_REGNUM)
4799 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
4800 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
4806 [(set_attr "type" "logics_reg,logics_imm")]
4810 [(set (reg:CC_NZ CC_REGNUM)
4812 (and:GPI (match_operand:GPI 0 "register_operand")
4813 (match_operand:GPI 1 "aarch64_mov_imm_operand"))
4815 (clobber (match_operand:SI 2 "register_operand"))]
4817 [(set (match_dup 2) (match_dup 1))
4818 (set (reg:CC_NZ CC_REGNUM)
4820 (and:GPI (match_dup 0)
4825 (define_insn "*and<mode>3nr_compare0_zextract"
4826 [(set (reg:CC_NZ CC_REGNUM)
4828 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
4829 (match_operand:GPI 1 "const_int_operand" "n")
4830 (match_operand:GPI 2 "const_int_operand" "n"))
4832 "INTVAL (operands[1]) > 0
4833 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
4834 <= GET_MODE_BITSIZE (<MODE>mode))
4835 && aarch64_bitmask_imm (
4836 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
4841 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
4842 return "tst\\t%<w>0, %1";
4844 [(set_attr "type" "logics_shift_imm")]
4847 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
4848 [(set (reg:CC_NZ CC_REGNUM)
4851 (match_operand:GPI 0 "register_operand" "r")
4852 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
4853 (match_operand:GPI 2 "register_operand" "r"))
4856 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
4857 [(set_attr "type" "logics_shift_imm")]
4861 [(set (reg:CC_NZ CC_REGNUM)
4864 (match_operand:GPI 0 "register_operand")
4865 (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
4866 (match_operand:GPI 2 "aarch64_mov_imm_operand"))
4868 (clobber (match_operand:SI 3 "register_operand"))]
4870 [(set (match_dup 3) (match_dup 2))
4871 (set (reg:CC_NZ CC_REGNUM)
4880 ;; -------------------------------------------------------------------
4882 ;; -------------------------------------------------------------------
4884 (define_expand "<optab><mode>3"
4885 [(set (match_operand:GPI 0 "register_operand")
4886 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
4887 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4890 if (CONST_INT_P (operands[2]))
4892 operands[2] = GEN_INT (INTVAL (operands[2])
4893 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4895 if (operands[2] == const0_rtx)
4897 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4904 (define_expand "ashl<mode>3"
4905 [(set (match_operand:SHORT 0 "register_operand")
4906 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
4907 (match_operand:QI 2 "const_int_operand")))]
4910 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
4912 if (operands[2] == const0_rtx)
4914 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4920 (define_expand "rotr<mode>3"
4921 [(set (match_operand:GPI 0 "register_operand")
4922 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4923 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4926 if (CONST_INT_P (operands[2]))
4928 operands[2] = GEN_INT (INTVAL (operands[2])
4929 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4931 if (operands[2] == const0_rtx)
4933 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4940 (define_expand "rotl<mode>3"
4941 [(set (match_operand:GPI 0 "register_operand")
4942 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4943 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4946 /* (SZ - cnt) % SZ == -cnt % SZ */
4947 if (CONST_INT_P (operands[2]))
4949 operands[2] = GEN_INT ((-INTVAL (operands[2]))
4950 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4951 if (operands[2] == const0_rtx)
4953 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4958 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4963 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4964 ;; they truncate the shift/rotate amount by the size of the registers they
4965 ;; operate on: 32 for W-regs, 64 for X-regs. This allows us to optimise away
4966 ;; such redundant masking instructions. GCC can do that automatically when
4967 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4968 ;; because some of the SISD shift alternatives don't perform this truncations.
4969 ;; So this pattern exists to catch such cases.
4971 (define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
4972 [(set (match_operand:GPI 0 "register_operand" "=r")
4974 (match_operand:GPI 1 "register_operand" "r")
4975 (match_operator 4 "subreg_lowpart_operator"
4976 [(and:GPI (match_operand:GPI 2 "register_operand" "r")
4977 (match_operand 3 "const_int_operand" "n"))])))]
4978 "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
4979 "<shift>\t%<w>0, %<w>1, %<w>2"
4980 [(set_attr "type" "shift_reg")]
4983 (define_insn_and_split "*aarch64_<optab>_reg_<mode>3_neg_mask2"
4984 [(set (match_operand:GPI 0 "register_operand" "=&r")
4986 (match_operand:GPI 1 "register_operand" "r")
4987 (match_operator 4 "subreg_lowpart_operator"
4988 [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
4989 (match_operand 3 "const_int_operand" "n")))])))]
4990 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
4995 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4996 : lowpart_subreg (SImode, operands[0], <MODE>mode));
4997 emit_insn (gen_negsi2 (tmp, operands[2]));
4999 rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
5000 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
5001 SUBREG_BYTE (operands[4]));
5002 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
5007 (define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask"
5008 [(set (match_operand:GPI 0 "register_operand" "=&r")
5010 (match_operand:GPI 1 "register_operand" "r")
5011 (minus:QI (match_operand 2 "const_int_operand" "n")
5012 (match_operator 5 "subreg_lowpart_operator"
5013 [(and:SI (match_operand:SI 3 "register_operand" "r")
5014 (match_operand 4 "const_int_operand" "n"))]))))]
5015 "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
5016 && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
5021 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5024 emit_insn (gen_negsi2 (tmp, operands[3]));
5026 rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
5027 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
5028 SUBREG_BYTE (operands[5]));
5030 emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
5035 (define_insn "*aarch64_<optab>_reg_di3_mask2"
5036 [(set (match_operand:DI 0 "register_operand" "=r")
5038 (match_operand:DI 1 "register_operand" "r")
5039 (match_operator 4 "subreg_lowpart_operator"
5040 [(and:SI (match_operand:SI 2 "register_operand" "r")
5041 (match_operand 3 "const_int_operand" "n"))])))]
5042 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)"
5045 xop[0] = operands[0];
5046 xop[1] = operands[1];
5047 xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
5048 output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
5051 [(set_attr "type" "shift_reg")]
5054 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>3"
5055 [(set (match_operand:GPI 0 "register_operand" "=&r")
5057 (match_operand:GPI 1 "register_operand" "r")
5058 (minus:QI (match_operand 2 "const_int_operand" "n")
5059 (match_operand:QI 3 "register_operand" "r"))))]
5060 "INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
5065 rtx subreg_tmp = gen_lowpart (SImode, operands[3]);
5067 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
5068 : gen_lowpart (SImode, operands[0]));
5070 emit_insn (gen_negsi2 (tmp, subreg_tmp));
5072 rtx and_op = gen_rtx_AND (SImode, tmp,
5073 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1));
5075 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
5077 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp2));
5080 [(set_attr "length" "8")]
5083 ;; Logical left shift using SISD or Integer instruction
5084 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
5085 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
5087 (match_operand:GPI 1 "register_operand" "r,r,w,w")
5088 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
5091 lsl\t%<w>0, %<w>1, %2
5092 lsl\t%<w>0, %<w>1, %<w>2
5093 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5094 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
5095 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")
5096 (set_attr "arch" "*,*,simd,simd")]
5099 ;; Logical right shift using SISD or Integer instruction
5100 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
5101 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
5103 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
5104 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>"
5105 "Us<cmode>,r,Us<cmode_simd>,w,0")))]
5108 lsr\t%<w>0, %<w>1, %2
5109 lsr\t%<w>0, %<w>1, %<w>2
5110 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5113 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5114 (set_attr "arch" "*,*,simd,simd,simd")]
5118 [(set (match_operand:DI 0 "aarch64_simd_register")
5120 (match_operand:DI 1 "aarch64_simd_register")
5121 (match_operand:QI 2 "aarch64_simd_register")))]
5122 "TARGET_SIMD && reload_completed"
5124 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5126 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
5128 operands[3] = gen_lowpart (QImode, operands[0]);
5133 [(set (match_operand:SI 0 "aarch64_simd_register")
5135 (match_operand:SI 1 "aarch64_simd_register")
5136 (match_operand:QI 2 "aarch64_simd_register")))]
5137 "TARGET_SIMD && reload_completed"
5139 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5141 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
5143 operands[3] = gen_lowpart (QImode, operands[0]);
5147 ;; Arithmetic right shift using SISD or Integer instruction
5148 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
5149 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
5151 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
5152 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di"
5153 "Us<cmode>,r,Us<cmode_simd>,w,0")))]
5156 asr\t%<w>0, %<w>1, %2
5157 asr\t%<w>0, %<w>1, %<w>2
5158 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
5161 [(set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")
5162 (set_attr "arch" "*,*,simd,simd,simd")]
5166 [(set (match_operand:DI 0 "aarch64_simd_register")
5168 (match_operand:DI 1 "aarch64_simd_register")
5169 (match_operand:QI 2 "aarch64_simd_register")))]
5170 "TARGET_SIMD && reload_completed"
5172 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5174 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
5176 operands[3] = gen_lowpart (QImode, operands[0]);
5181 [(set (match_operand:SI 0 "aarch64_simd_register")
5183 (match_operand:SI 1 "aarch64_simd_register")
5184 (match_operand:QI 2 "aarch64_simd_register")))]
5185 "TARGET_SIMD && reload_completed"
5187 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
5189 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
5191 operands[3] = gen_lowpart (QImode, operands[0]);
5195 (define_insn "*aarch64_sisd_ushl"
5196 [(set (match_operand:DI 0 "register_operand" "=w")
5197 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
5198 (match_operand:QI 2 "register_operand" "w")]
5201 "ushl\t%d0, %d1, %d2"
5202 [(set_attr "type" "neon_shift_reg")]
5205 (define_insn "*aarch64_ushl_2s"
5206 [(set (match_operand:SI 0 "register_operand" "=w")
5207 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
5208 (match_operand:QI 2 "register_operand" "w")]
5211 "ushl\t%0.2s, %1.2s, %2.2s"
5212 [(set_attr "type" "neon_shift_reg")]
5215 (define_insn "*aarch64_sisd_sshl"
5216 [(set (match_operand:DI 0 "register_operand" "=w")
5217 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
5218 (match_operand:QI 2 "register_operand" "w")]
5221 "sshl\t%d0, %d1, %d2"
5222 [(set_attr "type" "neon_shift_reg")]
5225 (define_insn "*aarch64_sshl_2s"
5226 [(set (match_operand:SI 0 "register_operand" "=w")
5227 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
5228 (match_operand:QI 2 "register_operand" "w")]
5231 "sshl\t%0.2s, %1.2s, %2.2s"
5232 [(set_attr "type" "neon_shift_reg")]
5235 (define_insn "*aarch64_sisd_neg_qi"
5236 [(set (match_operand:QI 0 "register_operand" "=w")
5237 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
5241 [(set_attr "type" "neon_neg")]
5245 (define_insn "*ror<mode>3_insn"
5246 [(set (match_operand:GPI 0 "register_operand" "=r,r")
5248 (match_operand:GPI 1 "register_operand" "r,r")
5249 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
5252 ror\\t%<w>0, %<w>1, %2
5253 ror\\t%<w>0, %<w>1, %<w>2"
5254 [(set_attr "type" "rotate_imm,shift_reg")]
5257 ;; zero_extend version of above
5258 (define_insn "*<optab>si3_insn_uxtw"
5259 [(set (match_operand:DI 0 "register_operand" "=r,r")
5260 (zero_extend:DI (SHIFT:SI
5261 (match_operand:SI 1 "register_operand" "r,r")
5262 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
5265 <shift>\\t%w0, %w1, %2
5266 <shift>\\t%w0, %w1, %w2"
5267 [(set_attr "type" "bfx,shift_reg")]
5270 (define_insn "*<optab><mode>3_insn"
5271 [(set (match_operand:SHORT 0 "register_operand" "=r")
5272 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
5273 (match_operand 2 "const_int_operand" "n")))]
5274 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
5276 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5277 return "<bfshift>\t%w0, %w1, %2, %3";
5279 [(set_attr "type" "bfx")]
5282 (define_insn "*extr<mode>5_insn"
5283 [(set (match_operand:GPI 0 "register_operand" "=r")
5284 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5285 (match_operand 3 "const_int_operand" "n"))
5286 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
5287 (match_operand 4 "const_int_operand" "n"))))]
5288 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
5289 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
5290 "extr\\t%<w>0, %<w>1, %<w>2, %4"
5291 [(set_attr "type" "rotate_imm")]
5294 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
5295 ;; so we have to match both orderings.
5296 (define_insn "*extr<mode>5_insn_alt"
5297 [(set (match_operand:GPI 0 "register_operand" "=r")
5298 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
5299 (match_operand 4 "const_int_operand" "n"))
5300 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5301 (match_operand 3 "const_int_operand" "n"))))]
5302 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
5303 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
5304 == GET_MODE_BITSIZE (<MODE>mode))"
5305 "extr\\t%<w>0, %<w>1, %<w>2, %4"
5306 [(set_attr "type" "rotate_imm")]
5309 ;; zero_extend version of the above
5310 (define_insn "*extrsi5_insn_uxtw"
5311 [(set (match_operand:DI 0 "register_operand" "=r")
5313 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
5314 (match_operand 3 "const_int_operand" "n"))
5315 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
5316 (match_operand 4 "const_int_operand" "n")))))]
5317 "UINTVAL (operands[3]) < 32 &&
5318 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
5319 "extr\\t%w0, %w1, %w2, %4"
5320 [(set_attr "type" "rotate_imm")]
5323 (define_insn "*extrsi5_insn_uxtw_alt"
5324 [(set (match_operand:DI 0 "register_operand" "=r")
5326 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
5327 (match_operand 4 "const_int_operand" "n"))
5328 (ashift:SI (match_operand:SI 1 "register_operand" "r")
5329 (match_operand 3 "const_int_operand" "n")))))]
5330 "UINTVAL (operands[3]) < 32 &&
5331 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
5332 "extr\\t%w0, %w1, %w2, %4"
5333 [(set_attr "type" "rotate_imm")]
5336 (define_insn "*ror<mode>3_insn"
5337 [(set (match_operand:GPI 0 "register_operand" "=r")
5338 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
5339 (match_operand 2 "const_int_operand" "n")))]
5340 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
5342 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
5343 return "ror\\t%<w>0, %<w>1, %3";
5345 [(set_attr "type" "rotate_imm")]
5348 ;; zero_extend version of the above
5349 (define_insn "*rorsi3_insn_uxtw"
5350 [(set (match_operand:DI 0 "register_operand" "=r")
5352 (rotate:SI (match_operand:SI 1 "register_operand" "r")
5353 (match_operand 2 "const_int_operand" "n"))))]
5354 "UINTVAL (operands[2]) < 32"
5356 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
5357 return "ror\\t%w0, %w1, %3";
5359 [(set_attr "type" "rotate_imm")]
5362 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
5363 [(set (match_operand:GPI 0 "register_operand" "=r")
5365 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
5366 (match_operand 2 "const_int_operand" "n"))))]
5367 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5369 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5370 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5372 [(set_attr "type" "bfx")]
5375 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
5376 [(set (match_operand:GPI 0 "register_operand" "=r")
5378 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
5379 (match_operand 2 "const_int_operand" "n"))))]
5380 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5382 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5383 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5385 [(set_attr "type" "bfx")]
5388 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
5389 [(set (match_operand:GPI 0 "register_operand" "=r")
5391 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
5392 (match_operand 2 "const_int_operand" "n"))))]
5393 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
5395 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
5396 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5398 [(set_attr "type" "bfx")]
5401 ;; -------------------------------------------------------------------
5403 ;; -------------------------------------------------------------------
5405 (define_expand "<optab>"
5406 [(set (match_operand:DI 0 "register_operand" "=r")
5407 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
5409 "aarch64_simd_shift_imm_offset_di")
5410 (match_operand 3 "aarch64_simd_shift_imm_di")))]
5413 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5414 1, GET_MODE_BITSIZE (DImode) - 1))
5420 (define_insn "*<optab><mode>"
5421 [(set (match_operand:GPI 0 "register_operand" "=r")
5422 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
5424 "aarch64_simd_shift_imm_offset_<mode>" "n")
5426 "aarch64_simd_shift_imm_<mode>" "n")))]
5427 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5428 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
5429 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
5430 [(set_attr "type" "bfx")]
5433 ;; When the bit position and width add up to 32 we can use a W-reg LSR
5434 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
5436 [(set (match_operand:DI 0 "register_operand")
5437 (zero_extract:DI (match_operand:DI 1 "register_operand")
5439 "aarch64_simd_shift_imm_offset_di")
5441 "aarch64_simd_shift_imm_di")))]
5442 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
5443 GET_MODE_BITSIZE (DImode) - 1)
5444 && (INTVAL (operands[2]) + INTVAL (operands[3]))
5445 == GET_MODE_BITSIZE (SImode)"
5447 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
5449 operands[4] = gen_lowpart (SImode, operands[1]);
5453 ;; Bitfield Insert (insv)
5454 (define_expand "insv<mode>"
5455 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
5456 (match_operand 1 "const_int_operand")
5457 (match_operand 2 "const_int_operand"))
5458 (match_operand:GPI 3 "general_operand"))]
5461 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
5462 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
5463 rtx value = operands[3];
5465 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
5468 if (CONST_INT_P (value))
5470 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
5472 /* Prefer AND/OR for inserting all zeros or all ones. */
5473 if ((UINTVAL (value) & mask) == 0
5474 || (UINTVAL (value) & mask) == mask)
5477 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
5478 if (width == 16 && (pos % 16) == 0)
5481 operands[3] = force_reg (<MODE>mode, value);
5484 (define_insn "*insv_reg<mode>"
5485 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5486 (match_operand 1 "const_int_operand" "n")
5487 (match_operand 2 "const_int_operand" "n"))
5488 (match_operand:GPI 3 "register_operand" "r"))]
5489 "!(UINTVAL (operands[1]) == 0
5490 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
5491 > GET_MODE_BITSIZE (<MODE>mode)))"
5492 "bfi\\t%<w>0, %<w>3, %2, %1"
5493 [(set_attr "type" "bfm")]
5496 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
5497 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5498 (match_operand 1 "const_int_operand" "n")
5499 (match_operand 2 "const_int_operand" "n"))
5500 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
5501 "UINTVAL (operands[1]) <= <ALLX:sizen>"
5502 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
5503 [(set_attr "type" "bfm")]
5506 ;; Match a bfi instruction where the shift of OP3 means that we are
5507 ;; actually copying the least significant bits of OP3 into OP0 by way
5508 ;; of the AND masks and the IOR instruction. A similar instruction
5509 ;; with the two parts of the IOR swapped around was never triggered
5510 ;; in a bootstrap build and test of GCC so it was not included.
5512 (define_insn "*aarch64_bfi<GPI:mode>5_shift"
5513 [(set (match_operand:GPI 0 "register_operand" "=r")
5514 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5515 (match_operand:GPI 2 "const_int_operand" "n"))
5516 (and:GPI (ashift:GPI
5517 (match_operand:GPI 3 "register_operand" "r")
5518 (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n"))
5519 (match_operand:GPI 5 "const_int_operand" "n"))))]
5520 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]),
5521 UINTVAL (operands[4]),
5522 UINTVAL(operands[5]))"
5523 "bfi\t%<GPI:w>0, %<GPI:w>3, %4, %P5"
5524 [(set_attr "type" "bfm")]
5527 (define_insn "*aarch64_bfi<GPI:mode>5_shift_alt"
5528 [(set (match_operand:GPI 0 "register_operand" "=r")
5529 (ior:GPI (and:GPI (ashift:GPI
5530 (match_operand:GPI 1 "register_operand" "r")
5531 (match_operand:GPI 2 "aarch64_simd_shift_imm_<mode>" "n"))
5532 (match_operand:GPI 3 "const_int_operand" "n"))
5533 (and:GPI (match_operand:GPI 4 "register_operand" "0")
5534 (match_operand:GPI 5 "const_int_operand" "n"))))]
5535 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[5]),
5536 UINTVAL (operands[2]),
5537 UINTVAL(operands[3]))"
5538 "bfi\t%<GPI:w>0, %<GPI:w>1, %2, %P3"
5539 [(set_attr "type" "bfm")]
5542 ;; Like *aarch64_bfi<GPI:mode>5_shift but with no and of the ashift because
5543 ;; the shift is large enough to remove the need for an AND instruction.
5545 (define_insn "*aarch64_bfi<GPI:mode>4_noand"
5546 [(set (match_operand:GPI 0 "register_operand" "=r")
5547 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5548 (match_operand:GPI 2 "const_int_operand" "n"))
5550 (match_operand:GPI 3 "register_operand" "r")
5551 (match_operand:GPI 4 "aarch64_simd_shift_imm_<mode>" "n"))))]
5552 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]),
5553 UINTVAL (operands[4]),
5554 HOST_WIDE_INT_M1U << UINTVAL (operands[4]) )"
5556 operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[4]));
5557 return "bfi\t%<GPI:w>0, %<GPI:w>3, %4, %5";
5559 [(set_attr "type" "bfm")]
5562 (define_insn "*aarch64_bfi<GPI:mode>4_noand_alt"
5563 [(set (match_operand:GPI 0 "register_operand" "=r")
5564 (ior:GPI (ashift:GPI
5565 (match_operand:GPI 1 "register_operand" "r")
5566 (match_operand:GPI 2 "aarch64_simd_shift_imm_<mode>" "n"))
5567 (and:GPI (match_operand:GPI 3 "register_operand" "0")
5568 (match_operand:GPI 4 "const_int_operand" "n"))))]
5569 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[4]),
5570 UINTVAL (operands[2]),
5571 HOST_WIDE_INT_M1U << UINTVAL (operands[2]) )"
5573 operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - UINTVAL (operands[2]));
5574 return "bfi\t%<GPI:w>0, %<GPI:w>1, %2, %5";
5576 [(set_attr "type" "bfm")]
5579 ;; Like *aarch64_bfi<GPI:mode>5_shift but with no shifting, we are just
5580 ;; copying the least significant bits of OP3 to OP0. We need two versions
5581 ;; of the instruction to handle different checks on the constant values.
5583 (define_insn "*aarch64_bfi<GPI:mode>4_noshift"
5584 [(set (match_operand:GPI 0 "register_operand" "=r")
5585 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "0")
5586 (match_operand:GPI 2 "const_int_operand" "n"))
5587 (and:GPI (match_operand:GPI 3 "register_operand" "r")
5588 (match_operand:GPI 4 "const_int_operand" "n"))))]
5589 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]), 0,
5590 UINTVAL (operands[4]))"
5591 "bfi\t%<GPI:w>0, %<GPI:w>3, 0, %P4"
5592 [(set_attr "type" "bfm")]
5595 (define_insn "*aarch64_bfi<GPI:mode>4_noshift_alt"
5596 [(set (match_operand:GPI 0 "register_operand" "=r")
5597 (ior:GPI (and:GPI (match_operand:GPI 3 "register_operand" "r")
5598 (match_operand:GPI 4 "const_int_operand" "n"))
5599 (and:GPI (match_operand:GPI 1 "register_operand" "0")
5600 (match_operand:GPI 2 "const_int_operand" "n"))))]
5601 "aarch64_masks_and_shift_for_bfi_p (<MODE>mode, UINTVAL (operands[2]), 0,
5602 UINTVAL (operands[4]))"
5603 "bfi\t%<GPI:w>0, %<GPI:w>3, 0, %P4"
5604 [(set_attr "type" "bfm")]
5607 (define_insn "*extr_insv_lower_reg<mode>"
5608 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
5609 (match_operand 1 "const_int_operand" "n")
5611 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
5613 (match_operand 3 "const_int_operand" "n")))]
5614 "!(UINTVAL (operands[1]) == 0
5615 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
5616 > GET_MODE_BITSIZE (<MODE>mode)))"
5617 "bfxil\\t%<w>0, %<w>2, %3, %1"
5618 [(set_attr "type" "bfm")]
5621 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
5622 [(set (match_operand:GPI 0 "register_operand" "=r")
5623 (ashift:GPI (ANY_EXTEND:GPI
5624 (match_operand:ALLX 1 "register_operand" "r"))
5625 (match_operand 2 "const_int_operand" "n")))]
5626 "UINTVAL (operands[2]) < <GPI:sizen>"
5628 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
5629 ? GEN_INT (<ALLX:sizen>)
5630 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
5631 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
5633 [(set_attr "type" "bfx")]
5636 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
5638 (define_insn "*andim_ashift<mode>_bfiz"
5639 [(set (match_operand:GPI 0 "register_operand" "=r")
5640 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5641 (match_operand 2 "const_int_operand" "n"))
5642 (match_operand 3 "const_int_operand" "n")))]
5643 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
5644 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
5645 [(set_attr "type" "bfx")]
5648 ;; Match sbfiz pattern in a shift left + shift right operation.
5650 (define_insn "*ashift<mode>_extv_bfiz"
5651 [(set (match_operand:GPI 0 "register_operand" "=r")
5652 (ashift:GPI (sign_extract:GPI (match_operand:GPI 1 "register_operand" "r")
5653 (match_operand 2 "aarch64_simd_shift_imm_offset_<mode>" "n")
5655 (match_operand 3 "aarch64_simd_shift_imm_<mode>" "n")))]
5656 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
5657 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
5658 "sbfiz\\t%<w>0, %<w>1, %3, %2"
5659 [(set_attr "type" "bfx")]
5662 ;; When the bit position and width of the equivalent extraction add up to 32
5663 ;; we can use a W-reg LSL instruction taking advantage of the implicit
5664 ;; zero-extension of the X-reg.
5666 [(set (match_operand:DI 0 "register_operand")
5667 (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
5668 (match_operand 2 "const_int_operand"))
5669 (match_operand 3 "const_int_operand")))]
5670 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
5671 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
5672 == GET_MODE_BITSIZE (SImode)"
5674 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
5676 operands[4] = gen_lowpart (SImode, operands[1]);
5680 (define_insn "bswap<mode>2"
5681 [(set (match_operand:GPI 0 "register_operand" "=r")
5682 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
5684 "rev\\t%<w>0, %<w>1"
5685 [(set_attr "type" "rev")]
5688 (define_insn "bswaphi2"
5689 [(set (match_operand:HI 0 "register_operand" "=r")
5690 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
5693 [(set_attr "type" "rev")]
5696 (define_insn "*aarch64_bfxil<mode>"
5697 [(set (match_operand:GPI 0 "register_operand" "=r,r")
5698 (ior:GPI (and:GPI (match_operand:GPI 1 "register_operand" "r,0")
5699 (match_operand:GPI 3 "const_int_operand" "n, Ulc"))
5700 (and:GPI (match_operand:GPI 2 "register_operand" "0,r")
5701 (match_operand:GPI 4 "const_int_operand" "Ulc, n"))))]
5702 "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
5703 && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
5704 || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
5706 switch (which_alternative)
5709 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
5710 return "bfxil\\t%<w>0, %<w>1, 0, %3";
5712 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
5713 return "bfxil\\t%<w>0, %<w>2, 0, %3";
5718 [(set_attr "type" "bfm")]
5721 ; Zero-extended version of above (aarch64_bfxil)
5722 (define_insn "*aarch64_bfxilsi_uxtw"
5723 [(set (match_operand:DI 0 "register_operand" "=r,r")
5724 (zero_extend:DI (ior:SI (and:SI (match_operand:SI 1 "register_operand"
5726 (match_operand:SI 3 "const_int_operand" "n, Ulc"))
5727 (and:SI (match_operand:SI 2 "register_operand" "0,r")
5728 (match_operand:SI 4 "const_int_operand" "Ulc, n")))))]
5729 "(INTVAL (operands[3]) == ~INTVAL (operands[4]))
5730 && (aarch64_high_bits_all_ones_p (INTVAL (operands[3]))
5731 || aarch64_high_bits_all_ones_p (INTVAL (operands[4])))"
5733 switch (which_alternative)
5736 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[3])));
5737 return "bfxil\\t%0, %1, 0, %3";
5739 operands[3] = GEN_INT (ctz_hwi (~INTVAL (operands[4])));
5740 return "bfxil\\t%0, %2, 0, %3";
5745 [(set_attr "type" "bfm")]
5748 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
5749 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
5750 ;; each valid permutation.
5752 (define_insn "rev16<mode>2"
5753 [(set (match_operand:GPI 0 "register_operand" "=r")
5754 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
5756 (match_operand:GPI 3 "const_int_operand" "n"))
5757 (and:GPI (lshiftrt:GPI (match_dup 1)
5759 (match_operand:GPI 2 "const_int_operand" "n"))))]
5760 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
5761 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
5762 "rev16\\t%<w>0, %<w>1"
5763 [(set_attr "type" "rev")]
5766 (define_insn "rev16<mode>2_alt"
5767 [(set (match_operand:GPI 0 "register_operand" "=r")
5768 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
5770 (match_operand:GPI 2 "const_int_operand" "n"))
5771 (and:GPI (ashift:GPI (match_dup 1)
5773 (match_operand:GPI 3 "const_int_operand" "n"))))]
5774 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
5775 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
5776 "rev16\\t%<w>0, %<w>1"
5777 [(set_attr "type" "rev")]
5780 ;; zero_extend version of above
5781 (define_insn "*bswapsi2_uxtw"
5782 [(set (match_operand:DI 0 "register_operand" "=r")
5783 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
5786 [(set_attr "type" "rev")]
5789 ;; -------------------------------------------------------------------
5790 ;; Floating-point intrinsics
5791 ;; -------------------------------------------------------------------
5793 ;; frint floating-point round to integral standard patterns.
5794 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
5796 (define_insn "<frint_pattern><mode>2"
5797 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5798 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
5801 "frint<frint_suffix>\\t%<s>0, %<s>1"
5802 [(set_attr "type" "f_rint<stype>")]
5805 ;; frcvt floating-point round to integer and convert standard patterns.
5806 ;; Expands to lbtrunc, lceil, lfloor, lround.
5807 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
5808 [(set (match_operand:GPI 0 "register_operand" "=r")
5810 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
5813 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
5814 [(set_attr "type" "f_cvtf2i")]
5817 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
5818 [(set (match_operand:GPI 0 "register_operand" "=r")
5821 (match_operand:GPF 1 "register_operand" "w")
5822 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
5824 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
5825 GET_MODE_BITSIZE (<GPI:MODE>mode))"
5827 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
5829 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
5830 output_asm_insn (buf, operands);
5833 [(set_attr "type" "f_cvtf2i")]
5836 ;; fma - expand fma into patterns with the accumulator operand first since
5837 ;; reusing the accumulator results in better register allocation.
5838 ;; The register allocator considers copy preferences in operand order,
5839 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
5841 (define_expand "fma<mode>4"
5842 [(set (match_operand:GPF_F16 0 "register_operand")
5843 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand")
5844 (match_operand:GPF_F16 2 "register_operand")
5845 (match_operand:GPF_F16 3 "register_operand")))]
5849 (define_insn "*aarch64_fma<mode>4"
5850 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5851 (fma:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w")
5852 (match_operand:GPF_F16 3 "register_operand" "w")
5853 (match_operand:GPF_F16 1 "register_operand" "w")))]
5855 "fmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5856 [(set_attr "type" "fmac<stype>")]
5859 (define_expand "fnma<mode>4"
5860 [(set (match_operand:GPF_F16 0 "register_operand")
5862 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand"))
5863 (match_operand:GPF_F16 2 "register_operand")
5864 (match_operand:GPF_F16 3 "register_operand")))]
5868 (define_insn "*aarch64_fnma<mode>4"
5869 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5871 (neg:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w"))
5872 (match_operand:GPF_F16 3 "register_operand" "w")
5873 (match_operand:GPF_F16 1 "register_operand" "w")))]
5875 "fmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
5876 [(set_attr "type" "fmac<stype>")]
5880 (define_expand "fms<mode>4"
5881 [(set (match_operand:GPF 0 "register_operand")
5882 (fma:GPF (match_operand:GPF 1 "register_operand")
5883 (match_operand:GPF 2 "register_operand")
5884 (neg:GPF (match_operand:GPF 3 "register_operand"))))]
5888 (define_insn "*aarch64_fms<mode>4"
5889 [(set (match_operand:GPF 0 "register_operand" "=w")
5890 (fma:GPF (match_operand:GPF 2 "register_operand" "w")
5891 (match_operand:GPF 3 "register_operand" "w")
5892 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
5894 "fnmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
5895 [(set_attr "type" "fmac<s>")]
5898 (define_expand "fnms<mode>4"
5899 [(set (match_operand:GPF 0 "register_operand")
5900 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand"))
5901 (match_operand:GPF 2 "register_operand")
5902 (neg:GPF (match_operand:GPF 3 "register_operand"))))]
5906 (define_insn "*aarch64_fnms<mode>4"
5907 [(set (match_operand:GPF 0 "register_operand" "=w")
5908 (fma:GPF (neg:GPF (match_operand:GPF 2 "register_operand" "w"))
5909 (match_operand:GPF 3 "register_operand" "w")
5910 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
5912 "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5913 [(set_attr "type" "fmac<s>")]
5916 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
5917 (define_insn "*aarch64_fnmadd<mode>4"
5918 [(set (match_operand:GPF 0 "register_operand" "=w")
5919 (neg:GPF (fma:GPF (match_operand:GPF 2 "register_operand" "w")
5920 (match_operand:GPF 3 "register_operand" "w")
5921 (match_operand:GPF 1 "register_operand" "w"))))]
5922 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5923 "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5924 [(set_attr "type" "fmac<s>")]
5927 ;; -------------------------------------------------------------------
5928 ;; Floating-point conversions
5929 ;; -------------------------------------------------------------------
5931 (define_insn "extendsfdf2"
5932 [(set (match_operand:DF 0 "register_operand" "=w")
5933 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
5936 [(set_attr "type" "f_cvt")]
5939 (define_insn "extendhfsf2"
5940 [(set (match_operand:SF 0 "register_operand" "=w")
5941 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
5944 [(set_attr "type" "f_cvt")]
5947 (define_insn "extendhfdf2"
5948 [(set (match_operand:DF 0 "register_operand" "=w")
5949 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
5952 [(set_attr "type" "f_cvt")]
5955 (define_insn "truncdfsf2"
5956 [(set (match_operand:SF 0 "register_operand" "=w")
5957 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
5960 [(set_attr "type" "f_cvt")]
5963 (define_insn "truncsfhf2"
5964 [(set (match_operand:HF 0 "register_operand" "=w")
5965 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
5968 [(set_attr "type" "f_cvt")]
5971 (define_insn "truncdfhf2"
5972 [(set (match_operand:HF 0 "register_operand" "=w")
5973 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
5976 [(set_attr "type" "f_cvt")]
5979 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5980 ;; and making r = w more expensive
5982 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>2"
5983 [(set (match_operand:GPI 0 "register_operand" "=w,?r")
5984 (FIXUORS:GPI (match_operand:<FCVT_TARGET> 1 "register_operand" "w,w")))]
5987 fcvtz<su>\t%<s>0, %<s>1
5988 fcvtz<su>\t%<w>0, %<s>1"
5989 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5992 ;; Convert HF -> SI or DI
5994 (define_insn "<optab>_trunchf<GPI:mode>2"
5995 [(set (match_operand:GPI 0 "register_operand" "=r")
5996 (FIXUORS:GPI (match_operand:HF 1 "register_operand" "w")))]
5998 "fcvtz<su>\t%<w>0, %h1"
5999 [(set_attr "type" "f_cvtf2i")]
6002 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
6003 ;; input in a fp register and output in a integer register
6005 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>2"
6006 [(set (match_operand:GPI 0 "register_operand" "=r")
6007 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand" "w")))]
6009 "fcvtz<su>\t%<w>0, %<fpw>1"
6010 [(set_attr "type" "f_cvtf2i")]
6013 (define_insn "*fix_to_zero_extend<mode>di2"
6014 [(set (match_operand:DI 0 "register_operand" "=r")
6017 (match_operand:GPF 1 "register_operand" "w"))))]
6019 "fcvtzu\t%w0, %<s>1"
6020 [(set_attr "type" "f_cvtf2i")]
6023 (define_insn "<optab><fcvt_target><GPF:mode>2"
6024 [(set (match_operand:GPF 0 "register_operand" "=w,w")
6025 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,?r")))]
6028 <su_optab>cvtf\t%<GPF:s>0, %<s>1
6029 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
6030 [(set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")
6031 (set_attr "arch" "simd,fp")]
6034 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
6035 [(set (match_operand:GPF 0 "register_operand" "=w")
6036 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
6038 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
6039 [(set_attr "type" "f_cvti2f")]
6042 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
6043 ;; midend will arrange for an SImode conversion to HFmode to first go
6044 ;; through DFmode, then to HFmode. But first it will try converting
6045 ;; to DImode then down, which would match our DImode pattern below and
6046 ;; give very poor code-generation. So, we must provide our own emulation
6047 ;; of the mid-end logic.
6049 (define_insn "aarch64_fp16_<optab><mode>hf2"
6050 [(set (match_operand:HF 0 "register_operand" "=w")
6051 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
6053 "<su_optab>cvtf\t%h0, %<w>1"
6054 [(set_attr "type" "f_cvti2f")]
6057 (define_expand "<optab>sihf2"
6058 [(set (match_operand:HF 0 "register_operand")
6059 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
6062 if (TARGET_FP_F16INST)
6063 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
6066 rtx convert_target = gen_reg_rtx (DFmode);
6067 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
6068 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
6074 ;; For DImode there is no wide enough floating-point mode that we
6075 ;; can convert through natively (TFmode would work, but requires a library
6076 ;; call). However, we know that any value >= 65504 will be rounded
6077 ;; to infinity on conversion. This is well within the range of SImode, so
6079 ;; Saturate to SImode.
6080 ;; Convert from that to DFmode
6081 ;; Convert from that to HFmode (phew!).
6082 ;; Note that the saturation to SImode requires the SIMD extensions. If
6083 ;; we ever need to provide this pattern where the SIMD extensions are not
6084 ;; available, we would need a different approach.
6086 (define_expand "<optab>dihf2"
6087 [(set (match_operand:HF 0 "register_operand")
6088 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
6089 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
6091 if (TARGET_FP_F16INST)
6092 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
6095 rtx sat_target = gen_reg_rtx (SImode);
6096 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
6097 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
6104 ;; Convert between fixed-point and floating-point (scalar modes)
6106 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
6107 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
6108 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
6109 (match_operand:SI 2 "immediate_operand" "i, i")]
6113 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
6114 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
6115 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
6116 (set_attr "arch" "fp,simd")]
6119 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
6120 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
6121 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
6122 (match_operand:SI 2 "immediate_operand" "i, i")]
6126 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
6127 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
6128 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
6129 (set_attr "arch" "fp,simd")]
6132 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
6133 [(set (match_operand:GPI 0 "register_operand" "=r")
6134 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
6135 (match_operand:SI 2 "immediate_operand" "i")]
6138 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
6139 [(set_attr "type" "f_cvtf2i")]
6142 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
6143 [(set (match_operand:HF 0 "register_operand" "=w")
6144 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
6145 (match_operand:SI 2 "immediate_operand" "i")]
6148 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
6149 [(set_attr "type" "f_cvti2f")]
6152 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
6153 [(set (match_operand:HI 0 "register_operand" "=w")
6154 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
6155 (match_operand:SI 2 "immediate_operand" "i")]
6158 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
6159 [(set_attr "type" "neon_fp_to_int_s")]
6162 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
6163 [(set (match_operand:HF 0 "register_operand" "=w")
6164 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
6165 (match_operand:SI 2 "immediate_operand" "i")]
6168 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
6169 [(set_attr "type" "neon_int_to_fp_s")]
6172 ;; -------------------------------------------------------------------
6173 ;; Floating-point arithmetic
6174 ;; -------------------------------------------------------------------
6176 (define_insn "add<mode>3"
6177 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6179 (match_operand:GPF_F16 1 "register_operand" "w")
6180 (match_operand:GPF_F16 2 "register_operand" "w")))]
6182 "fadd\\t%<s>0, %<s>1, %<s>2"
6183 [(set_attr "type" "fadd<stype>")]
6186 (define_insn "sub<mode>3"
6187 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6189 (match_operand:GPF_F16 1 "register_operand" "w")
6190 (match_operand:GPF_F16 2 "register_operand" "w")))]
6192 "fsub\\t%<s>0, %<s>1, %<s>2"
6193 [(set_attr "type" "fadd<stype>")]
6196 (define_insn "mul<mode>3"
6197 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6199 (match_operand:GPF_F16 1 "register_operand" "w")
6200 (match_operand:GPF_F16 2 "register_operand" "w")))]
6202 "fmul\\t%<s>0, %<s>1, %<s>2"
6203 [(set_attr "type" "fmul<stype>")]
6206 (define_insn "*fnmul<mode>3"
6207 [(set (match_operand:GPF 0 "register_operand" "=w")
6209 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
6210 (match_operand:GPF 2 "register_operand" "w")))]
6211 "TARGET_FLOAT && !flag_rounding_math"
6212 "fnmul\\t%<s>0, %<s>1, %<s>2"
6213 [(set_attr "type" "fmul<s>")]
6216 (define_insn "*fnmul<mode>3"
6217 [(set (match_operand:GPF 0 "register_operand" "=w")
6219 (match_operand:GPF 1 "register_operand" "w")
6220 (match_operand:GPF 2 "register_operand" "w"))))]
6222 "fnmul\\t%<s>0, %<s>1, %<s>2"
6223 [(set_attr "type" "fmul<s>")]
6226 (define_expand "div<mode>3"
6227 [(set (match_operand:GPF_F16 0 "register_operand")
6228 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
6229 (match_operand:GPF_F16 2 "register_operand")))]
6232 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
6235 operands[1] = force_reg (<MODE>mode, operands[1]);
6238 (define_insn "*div<mode>3"
6239 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6240 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
6241 (match_operand:GPF_F16 2 "register_operand" "w")))]
6243 "fdiv\\t%<s>0, %<s>1, %<s>2"
6244 [(set_attr "type" "fdiv<stype>")]
6247 (define_insn "neg<mode>2"
6248 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6249 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6251 "fneg\\t%<s>0, %<s>1"
6252 [(set_attr "type" "ffarith<stype>")]
6255 (define_expand "sqrt<mode>2"
6256 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6257 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6260 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
6264 (define_insn "*sqrt<mode>2"
6265 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6266 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6268 "fsqrt\\t%<s>0, %<s>1"
6269 [(set_attr "type" "fsqrt<stype>")]
6272 (define_insn "abs<mode>2"
6273 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6274 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
6276 "fabs\\t%<s>0, %<s>1"
6277 [(set_attr "type" "ffarith<stype>")]
6280 ;; Given that smax/smin do not specify the result when either input is NaN,
6281 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
6284 (define_insn "smax<mode>3"
6285 [(set (match_operand:GPF 0 "register_operand" "=w")
6286 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
6287 (match_operand:GPF 2 "register_operand" "w")))]
6289 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
6290 [(set_attr "type" "f_minmax<s>")]
6293 (define_insn "smin<mode>3"
6294 [(set (match_operand:GPF 0 "register_operand" "=w")
6295 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
6296 (match_operand:GPF 2 "register_operand" "w")))]
6298 "fminnm\\t%<s>0, %<s>1, %<s>2"
6299 [(set_attr "type" "f_minmax<s>")]
6302 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
6303 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
6304 ;; which implement the IEEE fmax ()/fmin () functions.
6305 (define_insn "<maxmin_uns><mode>3"
6306 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
6307 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
6308 (match_operand:GPF_F16 2 "register_operand" "w")]
6311 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
6312 [(set_attr "type" "f_minmax<stype>")]
6315 (define_expand "lrint<GPF:mode><GPI:mode>2"
6316 [(match_operand:GPI 0 "register_operand")
6317 (match_operand:GPF 1 "register_operand")]
6319 && ((GET_MODE_SIZE (<GPF:MODE>mode) <= GET_MODE_SIZE (<GPI:MODE>mode))
6320 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
6322 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
6323 emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1]));
6324 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt));
6329 ;; For copysign (x, y), we want to generate:
6331 ;; LDR d2, #(1 << 63)
6332 ;; BSL v2.8b, [y], [x]
6334 ;; or another, equivalent, sequence using one of BSL/BIT/BIF. Because
6335 ;; we expect these operations to nearly always operate on
6336 ;; floating-point values, we do not want the operation to be
6337 ;; simplified into a bit-field insert operation that operates on the
6338 ;; integer side, since typically that would involve three inter-bank
6339 ;; register copies. As we do not expect copysign to be followed by
6340 ;; other logical operations on the result, it seems preferable to keep
6341 ;; this as an unspec operation, rather than exposing the underlying
6342 ;; logic to the compiler.
6344 (define_expand "copysign<GPF:mode>3"
6345 [(match_operand:GPF 0 "register_operand")
6346 (match_operand:GPF 1 "register_operand")
6347 (match_operand:GPF 2 "register_operand")]
6348 "TARGET_FLOAT && TARGET_SIMD"
6350 rtx bitmask = gen_reg_rtx (<V_INT_EQUIV>mode);
6351 emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U
6352 << (GET_MODE_BITSIZE (<MODE>mode) - 1)));
6353 emit_insn (gen_copysign<mode>3_insn (operands[0], operands[1], operands[2],
6359 (define_insn "copysign<GPF:mode>3_insn"
6360 [(set (match_operand:GPF 0 "register_operand" "=w,w,w,r")
6361 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w,0,w,r")
6362 (match_operand:GPF 2 "register_operand" "w,w,0,0")
6363 (match_operand:<V_INT_EQUIV> 3 "register_operand" "0,w,w,X")]
6365 "TARGET_FLOAT && TARGET_SIMD"
6367 bsl\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>
6368 bit\\t%0.<Vbtype>, %2.<Vbtype>, %3.<Vbtype>
6369 bif\\t%0.<Vbtype>, %1.<Vbtype>, %3.<Vbtype>
6370 bfxil\\t%<w1>0, %<w1>1, #0, <sizem1>"
6371 [(set_attr "type" "neon_bsl<q>,neon_bsl<q>,neon_bsl<q>,bfm")]
6375 ;; For xorsign (x, y), we want to generate:
6378 ;; AND v3.8B, v1.8B, v2.8B
6379 ;; EOR v0.8B, v0.8B, v3.8B
6382 (define_expand "xorsign<mode>3"
6383 [(match_operand:GPF 0 "register_operand")
6384 (match_operand:GPF 1 "register_operand")
6385 (match_operand:GPF 2 "register_operand")]
6386 "TARGET_FLOAT && TARGET_SIMD"
6389 machine_mode imode = <V_INT_EQUIV>mode;
6390 rtx mask = gen_reg_rtx (imode);
6391 rtx op1x = gen_reg_rtx (imode);
6392 rtx op2x = gen_reg_rtx (imode);
6394 int bits = GET_MODE_BITSIZE (<MODE>mode) - 1;
6395 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
6398 emit_insn (gen_and<v_int_equiv>3 (op2x, mask,
6399 lowpart_subreg (imode, operands[2],
6401 emit_insn (gen_xor<v_int_equiv>3 (op1x,
6402 lowpart_subreg (imode, operands[1],
6405 emit_move_insn (operands[0],
6406 lowpart_subreg (<MODE>mode, op1x, imode));
6411 ;; -------------------------------------------------------------------
6413 ;; -------------------------------------------------------------------
6414 ;; Reload Scalar Floating point modes from constant pool.
6415 ;; The AArch64 port doesn't have __int128 constant move support.
6416 (define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
6417 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
6418 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
6419 (clobber (match_operand:P 2 "register_operand" "=&r"))]
6422 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
6423 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
6428 ;; Reload Vector modes from constant pool.
6429 (define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
6430 [(set (match_operand:VALL 0 "register_operand" "=w")
6431 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
6432 (clobber (match_operand:P 2 "register_operand" "=&r"))]
6435 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
6436 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
6441 (define_expand "@aarch64_reload_mov<mode>"
6442 [(set (match_operand:TX 0 "register_operand" "=w")
6443 (match_operand:TX 1 "register_operand" "w"))
6444 (clobber (match_operand:DI 2 "register_operand" "=&r"))
6448 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
6449 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
6450 gen_aarch64_movtilow_tilow (op0, op1);
6451 gen_aarch64_movdi_tihigh (operands[2], op1);
6452 gen_aarch64_movtihigh_di (op0, operands[2]);
6457 ;; The following secondary reload helpers patterns are invoked
6458 ;; after or during reload as we don't want these patterns to start
6459 ;; kicking in during the combiner.
6461 (define_insn "@aarch64_movdi_<mode>low"
6462 [(set (match_operand:DI 0 "register_operand" "=r")
6463 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
6464 (const_int 64) (const_int 0)))]
6465 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6467 [(set_attr "type" "f_mrc")
6468 (set_attr "length" "4")
6471 (define_insn "@aarch64_movdi_<mode>high"
6472 [(set (match_operand:DI 0 "register_operand" "=r")
6473 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
6474 (const_int 64) (const_int 64)))]
6475 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6476 "fmov\\t%x0, %1.d[1]"
6477 [(set_attr "type" "f_mrc")
6478 (set_attr "length" "4")
6481 (define_insn "@aarch64_mov<mode>high_di"
6482 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
6483 (const_int 64) (const_int 64))
6484 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
6485 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6486 "fmov\\t%0.d[1], %x1"
6487 [(set_attr "type" "f_mcr")
6488 (set_attr "length" "4")
6491 (define_insn "@aarch64_mov<mode>low_di"
6492 [(set (match_operand:TX 0 "register_operand" "=w")
6493 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
6494 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6496 [(set_attr "type" "f_mcr")
6497 (set_attr "length" "4")
6500 (define_insn "aarch64_movtilow_tilow"
6501 [(set (match_operand:TI 0 "register_operand" "=w")
6503 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
6504 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
6506 [(set_attr "type" "fmov")
6507 (set_attr "length" "4")
6510 ;; There is a deliberate reason why the parameters of high and lo_sum's
6511 ;; don't have modes for ADRP and ADD instructions. This is to allow high
6512 ;; and lo_sum's to be used with the labels defining the jump tables in
6515 (define_expand "add_losym"
6516 [(set (match_operand 0 "register_operand" "=r")
6517 (lo_sum (match_operand 1 "register_operand" "r")
6518 (match_operand 2 "aarch64_valid_symref" "S")))]
6521 machine_mode mode = GET_MODE (operands[0]);
6523 emit_insn ((mode == DImode
6525 : gen_add_losym_si) (operands[0],
6531 (define_insn "add_losym_<mode>"
6532 [(set (match_operand:P 0 "register_operand" "=r")
6533 (lo_sum:P (match_operand:P 1 "register_operand" "r")
6534 (match_operand 2 "aarch64_valid_symref" "S")))]
6536 "add\\t%<w>0, %<w>1, :lo12:%c2"
6537 [(set_attr "type" "alu_imm")]
6540 (define_insn "ldr_got_small_<mode>"
6541 [(set (match_operand:PTR 0 "register_operand" "=r")
6542 (unspec:PTR [(mem:PTR (lo_sum:PTR
6543 (match_operand:PTR 1 "register_operand" "r")
6544 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
6545 UNSPEC_GOTSMALLPIC))]
6547 "ldr\\t%<w>0, [%1, #:got_lo12:%c2]"
6548 [(set_attr "type" "load_<ldst_sz>")]
6551 (define_insn "ldr_got_small_sidi"
6552 [(set (match_operand:DI 0 "register_operand" "=r")
6554 (unspec:SI [(mem:SI (lo_sum:DI
6555 (match_operand:DI 1 "register_operand" "r")
6556 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
6557 UNSPEC_GOTSMALLPIC)))]
6559 "ldr\\t%w0, [%1, #:got_lo12:%c2]"
6560 [(set_attr "type" "load_4")]
6563 (define_insn "ldr_got_small_28k_<mode>"
6564 [(set (match_operand:PTR 0 "register_operand" "=r")
6565 (unspec:PTR [(mem:PTR (lo_sum:PTR
6566 (match_operand:PTR 1 "register_operand" "r")
6567 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
6568 UNSPEC_GOTSMALLPIC28K))]
6570 "ldr\\t%<w>0, [%1, #:<got_modifier>:%c2]"
6571 [(set_attr "type" "load_<ldst_sz>")]
6574 (define_insn "ldr_got_small_28k_sidi"
6575 [(set (match_operand:DI 0 "register_operand" "=r")
6577 (unspec:SI [(mem:SI (lo_sum:DI
6578 (match_operand:DI 1 "register_operand" "r")
6579 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
6580 UNSPEC_GOTSMALLPIC28K)))]
6582 "ldr\\t%w0, [%1, #:gotpage_lo14:%c2]"
6583 [(set_attr "type" "load_4")]
6586 (define_insn "ldr_got_tiny"
6587 [(set (match_operand:DI 0 "register_operand" "=r")
6588 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
6589 UNSPEC_GOTTINYPIC))]
6592 [(set_attr "type" "load_8")]
6595 (define_insn "aarch64_load_tp_hard"
6596 [(set (match_operand:DI 0 "register_operand" "=r")
6597 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
6599 "mrs\\t%0, tpidr_el0"
6600 [(set_attr "type" "mrs")]
6603 ;; The TLS ABI specifically requires that the compiler does not schedule
6604 ;; instructions in the TLS stubs, in order to enable linker relaxation.
6605 ;; Therefore we treat the stubs as an atomic sequence.
6606 (define_expand "tlsgd_small_<mode>"
6607 [(parallel [(set (match_operand 0 "register_operand" "")
6608 (call (mem:DI (match_dup 2)) (const_int 1)))
6609 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
6610 (clobber (reg:DI LR_REGNUM))])]
6613 operands[2] = aarch64_tls_get_addr ();
6616 (define_insn "*tlsgd_small_<mode>"
6617 [(set (match_operand 0 "register_operand" "")
6618 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
6619 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
6620 (clobber (reg:DI LR_REGNUM))
6623 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
6624 [(set_attr "type" "call")
6625 (set_attr "length" "16")])
6627 (define_insn "tlsie_small_<mode>"
6628 [(set (match_operand:PTR 0 "register_operand" "=r")
6629 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
6630 UNSPEC_GOTSMALLTLS))]
6632 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
6633 [(set_attr "type" "load_4")
6634 (set_attr "length" "8")]
6637 (define_insn "tlsie_small_sidi"
6638 [(set (match_operand:DI 0 "register_operand" "=r")
6640 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
6641 UNSPEC_GOTSMALLTLS)))]
6643 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
6644 [(set_attr "type" "load_4")
6645 (set_attr "length" "8")]
6648 (define_insn "tlsie_tiny_<mode>"
6649 [(set (match_operand:PTR 0 "register_operand" "=&r")
6650 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
6651 (match_operand:PTR 2 "register_operand" "r")]
6652 UNSPEC_GOTTINYTLS))]
6654 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
6655 [(set_attr "type" "multiple")
6656 (set_attr "length" "8")]
6659 (define_insn "tlsie_tiny_sidi"
6660 [(set (match_operand:DI 0 "register_operand" "=&r")
6662 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
6663 (match_operand:DI 2 "register_operand" "r")
6665 UNSPEC_GOTTINYTLS)))]
6667 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
6668 [(set_attr "type" "multiple")
6669 (set_attr "length" "8")]
6672 (define_insn "tlsle12_<mode>"
6673 [(set (match_operand:P 0 "register_operand" "=r")
6674 (unspec:P [(match_operand:P 1 "register_operand" "r")
6675 (match_operand 2 "aarch64_tls_le_symref" "S")]
6678 "add\\t%<w>0, %<w>1, #%L2";
6679 [(set_attr "type" "alu_sreg")
6680 (set_attr "length" "4")]
6683 (define_insn "tlsle24_<mode>"
6684 [(set (match_operand:P 0 "register_operand" "=r")
6685 (unspec:P [(match_operand:P 1 "register_operand" "r")
6686 (match_operand 2 "aarch64_tls_le_symref" "S")]
6689 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
6690 [(set_attr "type" "multiple")
6691 (set_attr "length" "8")]
6694 (define_insn "tlsle32_<mode>"
6695 [(set (match_operand:P 0 "register_operand" "=r")
6696 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
6699 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
6700 [(set_attr "type" "multiple")
6701 (set_attr "length" "8")]
6704 (define_insn "tlsle48_<mode>"
6705 [(set (match_operand:P 0 "register_operand" "=r")
6706 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
6709 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
6710 [(set_attr "type" "multiple")
6711 (set_attr "length" "12")]
6714 (define_expand "tlsdesc_small_<mode>"
6715 [(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
6719 emit_insn (gen_tlsdesc_small_sve_<mode> (operands[0]));
6721 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
6726 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
6728 (define_insn "tlsdesc_small_advsimd_<mode>"
6729 [(set (reg:PTR R0_REGNUM)
6730 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
6732 (clobber (reg:DI LR_REGNUM))
6733 (clobber (reg:CC CC_REGNUM))
6734 (clobber (match_scratch:DI 1 "=r"))]
6735 "TARGET_TLS_DESC && !TARGET_SVE"
6736 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
6737 [(set_attr "type" "call")
6738 (set_attr "length" "16")])
6740 ;; For SVE, model tlsdesc calls as clobbering the lower 128 bits of
6741 ;; all vector registers, and clobber all predicate registers, on
6742 ;; top of the usual R0 and LR.
6743 (define_insn "tlsdesc_small_sve_<mode>"
6744 [(set (reg:PTR R0_REGNUM)
6745 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
6747 (clobber (reg:DI LR_REGNUM))
6748 (clobber (reg:CC CC_REGNUM))
6749 (clobber_high (reg:TI V0_REGNUM))
6750 (clobber_high (reg:TI V1_REGNUM))
6751 (clobber_high (reg:TI V2_REGNUM))
6752 (clobber_high (reg:TI V3_REGNUM))
6753 (clobber_high (reg:TI V4_REGNUM))
6754 (clobber_high (reg:TI V5_REGNUM))
6755 (clobber_high (reg:TI V6_REGNUM))
6756 (clobber_high (reg:TI V7_REGNUM))
6757 (clobber_high (reg:TI V8_REGNUM))
6758 (clobber_high (reg:TI V9_REGNUM))
6759 (clobber_high (reg:TI V10_REGNUM))
6760 (clobber_high (reg:TI V11_REGNUM))
6761 (clobber_high (reg:TI V12_REGNUM))
6762 (clobber_high (reg:TI V13_REGNUM))
6763 (clobber_high (reg:TI V14_REGNUM))
6764 (clobber_high (reg:TI V15_REGNUM))
6765 (clobber_high (reg:TI V16_REGNUM))
6766 (clobber_high (reg:TI V17_REGNUM))
6767 (clobber_high (reg:TI V18_REGNUM))
6768 (clobber_high (reg:TI V19_REGNUM))
6769 (clobber_high (reg:TI V20_REGNUM))
6770 (clobber_high (reg:TI V21_REGNUM))
6771 (clobber_high (reg:TI V22_REGNUM))
6772 (clobber_high (reg:TI V23_REGNUM))
6773 (clobber_high (reg:TI V24_REGNUM))
6774 (clobber_high (reg:TI V25_REGNUM))
6775 (clobber_high (reg:TI V26_REGNUM))
6776 (clobber_high (reg:TI V27_REGNUM))
6777 (clobber_high (reg:TI V28_REGNUM))
6778 (clobber_high (reg:TI V29_REGNUM))
6779 (clobber_high (reg:TI V30_REGNUM))
6780 (clobber_high (reg:TI V31_REGNUM))
6781 (clobber (reg:VNx2BI P0_REGNUM))
6782 (clobber (reg:VNx2BI P1_REGNUM))
6783 (clobber (reg:VNx2BI P2_REGNUM))
6784 (clobber (reg:VNx2BI P3_REGNUM))
6785 (clobber (reg:VNx2BI P4_REGNUM))
6786 (clobber (reg:VNx2BI P5_REGNUM))
6787 (clobber (reg:VNx2BI P6_REGNUM))
6788 (clobber (reg:VNx2BI P7_REGNUM))
6789 (clobber (reg:VNx2BI P8_REGNUM))
6790 (clobber (reg:VNx2BI P9_REGNUM))
6791 (clobber (reg:VNx2BI P10_REGNUM))
6792 (clobber (reg:VNx2BI P11_REGNUM))
6793 (clobber (reg:VNx2BI P12_REGNUM))
6794 (clobber (reg:VNx2BI P13_REGNUM))
6795 (clobber (reg:VNx2BI P14_REGNUM))
6796 (clobber (reg:VNx2BI P15_REGNUM))
6797 (clobber (match_scratch:DI 1 "=r"))]
6798 "TARGET_TLS_DESC && TARGET_SVE"
6799 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
6800 [(set_attr "type" "call")
6801 (set_attr "length" "16")])
6803 (define_insn "stack_tie"
6804 [(set (mem:BLK (scratch))
6805 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
6806 (match_operand:DI 1 "register_operand" "rk")]
6810 [(set_attr "length" "0")]
6813 ;; Pointer authentication patterns are always provided. In architecture
6814 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
6815 ;; This lets the user write portable software which authenticates pointers
6816 ;; when run on something which implements ARMv8.3-A, and which runs
6817 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
6820 ;; Signing/Authenticating R30 using SP as the salt.
6822 (define_insn "<pauth_mnem_prefix>sp"
6823 [(set (reg:DI R30_REGNUM)
6824 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
6826 "hint\t<pauth_hint_num> // <pauth_mnem_prefix>sp";
6829 ;; Signing/Authenticating X17 using X16 as the salt.
6831 (define_insn "<pauth_mnem_prefix>1716"
6832 [(set (reg:DI R17_REGNUM)
6833 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
6835 "hint\t<pauth_hint_num> // <pauth_mnem_prefix>1716";
6838 ;; Stripping the signature in R30.
6840 (define_insn "xpaclri"
6841 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
6843 "hint\t7 // xpaclri"
6846 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6847 ;; all of memory. This blocks insns from being moved across this point.
6849 (define_insn "blockage"
6850 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
6853 [(set_attr "length" "0")
6854 (set_attr "type" "block")]
6857 (define_insn "probe_stack_range"
6858 [(set (match_operand:DI 0 "register_operand" "=rk")
6859 (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
6860 (match_operand:DI 2 "register_operand" "r")]
6861 UNSPECV_PROBE_STACK_RANGE))]
6864 return aarch64_output_probe_stack_range (operands[0], operands[2]);
6866 [(set_attr "length" "32")]
6869 ;; This instruction is used to generate the stack clash stack adjustment and
6870 ;; probing loop. We can't change the control flow during prologue and epilogue
6871 ;; code generation. So we must emit a volatile unspec and expand it later on.
6873 (define_insn "@probe_sve_stack_clash_<mode>"
6874 [(set (match_operand:P 0 "register_operand" "=rk")
6875 (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
6876 (match_operand:P 2 "register_operand" "r")
6877 (match_operand:P 3 "const_int_operand" "n")
6878 (match_operand:P 4 "aarch64_plus_immediate" "L")]
6879 UNSPECV_PROBE_STACK_RANGE))]
6882 return aarch64_output_probe_sve_stack_clash (operands[0], operands[2],
6883 operands[3], operands[4]);
6885 [(set_attr "length" "28")]
6888 ;; Named pattern for expanding thread pointer reference.
6889 (define_expand "get_thread_pointerdi"
6890 [(match_operand:DI 0 "register_operand" "=r")]
6893 rtx tmp = aarch64_load_tp (operands[0]);
6894 if (tmp != operands[0])
6895 emit_move_insn (operands[0], tmp);
6899 ;; Named patterns for stack smashing protection.
6900 (define_expand "stack_protect_set"
6901 [(match_operand 0 "memory_operand")
6902 (match_operand 1 "memory_operand")]
6905 machine_mode mode = GET_MODE (operands[0]);
6906 if (aarch64_stack_protector_guard != SSP_GLOBAL)
6908 /* Generate access through the system register. */
6909 rtx tmp_reg = gen_reg_rtx (mode);
6912 emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
6913 emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
6914 GEN_INT (aarch64_stack_protector_guard_offset)));
6918 emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
6919 emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
6920 GEN_INT (aarch64_stack_protector_guard_offset)));
6923 operands[1] = gen_rtx_MEM (mode, tmp_reg);
6926 emit_insn ((mode == DImode
6927 ? gen_stack_protect_set_di
6928 : gen_stack_protect_set_si) (operands[0], operands[1]));
6932 (define_insn "reg_stack_protect_address_<mode>"
6933 [(set (match_operand:PTR 0 "register_operand" "=r")
6934 (unspec:PTR [(const_int 0)]
6935 UNSPEC_SSP_SYSREG))]
6936 "aarch64_stack_protector_guard != SSP_GLOBAL"
6939 snprintf (buf, 150, "mrs\\t%%<w>0, %s",
6940 aarch64_stack_protector_guard_reg_str);
6941 output_asm_insn (buf, operands);
6944 [(set_attr "type" "mrs")])
6946 (define_insn "stack_protect_set_<mode>"
6947 [(set (match_operand:PTR 0 "memory_operand" "=m")
6948 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
6950 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
6952 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
6953 [(set_attr "length" "12")
6954 (set_attr "type" "multiple")])
6956 (define_expand "stack_protect_test"
6957 [(match_operand 0 "memory_operand")
6958 (match_operand 1 "memory_operand")
6963 machine_mode mode = GET_MODE (operands[0]);
6965 result = gen_reg_rtx(mode);
6966 if (aarch64_stack_protector_guard != SSP_GLOBAL)
6968 /* Generate access through the system register. The
6969 sequence we want here is the access
6970 of the stack offset to come with
6971 mrs scratch_reg, <system_register>
6972 add scratch_reg, scratch_reg, :lo12:offset. */
6973 rtx tmp_reg = gen_reg_rtx (mode);
6976 emit_insn (gen_reg_stack_protect_address_di (tmp_reg));
6977 emit_insn (gen_adddi3 (tmp_reg, tmp_reg,
6978 GEN_INT (aarch64_stack_protector_guard_offset)));
6982 emit_insn (gen_reg_stack_protect_address_si (tmp_reg));
6983 emit_insn (gen_addsi3 (tmp_reg, tmp_reg,
6984 GEN_INT (aarch64_stack_protector_guard_offset)));
6987 operands[1] = gen_rtx_MEM (mode, tmp_reg);
6989 emit_insn ((mode == DImode
6990 ? gen_stack_protect_test_di
6991 : gen_stack_protect_test_si) (result,
6996 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
6997 result, const0_rtx, operands[2]));
6999 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
7000 result, const0_rtx, operands[2]));
7004 (define_insn "stack_protect_test_<mode>"
7005 [(set (match_operand:PTR 0 "register_operand" "=r")
7006 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
7007 (match_operand:PTR 2 "memory_operand" "m")]
7009 (clobber (match_scratch:PTR 3 "=&r"))]
7011 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
7012 [(set_attr "length" "12")
7013 (set_attr "type" "multiple")])
7015 ;; Write Floating-point Control Register.
7016 (define_insn "set_fpcr"
7017 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
7020 [(set_attr "type" "mrs")])
7022 ;; Read Floating-point Control Register.
7023 (define_insn "get_fpcr"
7024 [(set (match_operand:SI 0 "register_operand" "=r")
7025 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
7028 [(set_attr "type" "mrs")])
7030 ;; Write Floating-point Status Register.
7031 (define_insn "set_fpsr"
7032 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
7035 [(set_attr "type" "mrs")])
7037 ;; Read Floating-point Status Register.
7038 (define_insn "get_fpsr"
7039 [(set (match_operand:SI 0 "register_operand" "=r")
7040 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
7043 [(set_attr "type" "mrs")])
7046 ;; Define the subtract-one-and-jump insns so loop.c
7047 ;; knows what to generate.
7048 (define_expand "doloop_end"
7049 [(use (match_operand 0 "" "")) ; loop pseudo
7050 (use (match_operand 1 "" ""))] ; label
7051 "optimize > 0 && flag_modulo_sched"
7060 /* Currently SMS relies on the do-loop pattern to recognize loops
7061 where (1) the control part consists of all insns defining and/or
7062 using a certain 'count' register and (2) the loop count can be
7063 adjusted by modifying this register prior to the loop.
7064 ??? The possible introduction of a new block to initialize the
7065 new IV can potentially affect branch optimizations. */
7067 if (GET_MODE (operands[0]) != DImode)
7071 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
7073 cmp = XVECEXP (PATTERN (insn), 0, 0);
7074 cc_reg = SET_DEST (cmp);
7075 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
7076 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
7077 emit_jump_insn (gen_rtx_SET (pc_rtx,
7078 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
7083 ;; Track speculation through conditional branches. We assume that
7084 ;; SPECULATION_TRACKER_REGNUM is reserved for this purpose when necessary.
7085 (define_insn "speculation_tracker"
7086 [(set (reg:DI SPECULATION_TRACKER_REGNUM)
7087 (unspec:DI [(reg:DI SPECULATION_TRACKER_REGNUM) (match_operand 0)]
7088 UNSPEC_SPECULATION_TRACKER))]
7091 operands[1] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7092 output_asm_insn ("csel\\t%1, %1, xzr, %m0", operands);
7095 [(set_attr "type" "csel")]
7098 ;; BTI <target> instructions
7099 (define_insn "bti_noarg"
7100 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_NOARG)]
7103 [(set_attr "type" "no_insn")]
7106 (define_insn "bti_c"
7107 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_C)]
7110 [(set_attr "type" "no_insn")]
7113 (define_insn "bti_j"
7114 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_J)]
7117 [(set_attr "type" "no_insn")]
7120 (define_insn "bti_jc"
7121 [(unspec_volatile [(const_int 0)] UNSPECV_BTI_JC)]
7123 "hint\t38 // bti jc"
7124 [(set_attr "type" "no_insn")]
7127 ;; Helper for aarch64.c code.
7128 (define_expand "set_clobber_cc_nzc"
7129 [(parallel [(set (match_operand 0)
7131 (clobber (reg:CC_NZC CC_REGNUM))])])
7133 ;; Hard speculation barrier.
7134 (define_insn "speculation_barrier"
7135 [(unspec_volatile [(const_int 0)] UNSPECV_SPECULATION_BARRIER)]
7138 [(set_attr "length" "8")
7139 (set_attr "type" "block")
7140 (set_attr "speculation_barrier" "true")]
7143 ;; Support for __builtin_speculation_safe_value when we have speculation
7144 ;; tracking enabled. Use the speculation tracker to decide whether to
7145 ;; copy operand 1 to the target, or to copy the fail value (operand 2).
7146 (define_expand "@despeculate_copy<ALLI_TI:mode>"
7147 [(set (match_operand:ALLI_TI 0 "register_operand" "=r")
7148 (unspec_volatile:ALLI_TI
7149 [(match_operand:ALLI_TI 1 "register_operand" "r")
7150 (match_operand:ALLI_TI 2 "aarch64_reg_or_zero" "rZ")
7151 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7152 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7156 if (operands[2] == const0_rtx)
7159 if (<MODE>mode == TImode)
7160 tracker = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7162 tracker = gen_rtx_REG (<MODE>mode, SPECULATION_TRACKER_REGNUM);
7164 emit_insn (gen_despeculate_simple<mode> (operands[0], operands[1],
7172 ;; Patterns to match despeculate_copy<mode>. Note that "hint 0x14" is the
7173 ;; encoding for CSDB, but will work in older versions of the assembler.
7174 (define_insn "*despeculate_copy<ALLI:mode>_insn"
7175 [(set (match_operand:ALLI 0 "register_operand" "=r")
7176 (unspec_volatile:ALLI
7177 [(match_operand:ALLI 1 "register_operand" "r")
7178 (match_operand:ALLI 2 "aarch64_reg_or_zero" "rZ")
7179 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7180 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7183 operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7184 output_asm_insn ("cmp\\t%3, #0\;csel\\t%<w>0, %<w>1, %<w>2, ne\;hint\t0x14 // csdb",
7188 [(set_attr "length" "12")
7189 (set_attr "type" "block")
7190 (set_attr "speculation_barrier" "true")]
7193 ;; Pattern to match despeculate_copyti
7194 (define_insn "*despeculate_copyti_insn"
7195 [(set (match_operand:TI 0 "register_operand" "=r")
7197 [(match_operand:TI 1 "register_operand" "r")
7198 (match_operand:TI 2 "aarch64_reg_or_zero" "rZ")
7199 (use (reg:DI SPECULATION_TRACKER_REGNUM))
7200 (clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
7203 operands[3] = gen_rtx_REG (DImode, SPECULATION_TRACKER_REGNUM);
7205 ("cmp\\t%3, #0\;csel\\t%0, %1, %2, ne\;csel\\t%H0, %H1, %H2, ne\;hint\t0x14 // csdb",
7209 [(set_attr "length" "16")
7210 (set_attr "type" "block")
7211 (set_attr "speculation_barrier" "true")]
7214 (define_insn "despeculate_simple<ALLI:mode>"
7215 [(set (match_operand:ALLI 0 "register_operand" "=r")
7216 (unspec_volatile:ALLI
7217 [(match_operand:ALLI 1 "register_operand" "r")
7218 (use (match_operand:ALLI 2 "register_operand" ""))]
7219 UNSPECV_SPECULATION_BARRIER))]
7221 "and\\t%<w>0, %<w>1, %<w>2\;hint\t0x14 // csdb"
7222 [(set_attr "type" "block")
7223 (set_attr "length" "8")
7224 (set_attr "speculation_barrier" "true")]
7227 (define_insn "despeculate_simpleti"
7228 [(set (match_operand:TI 0 "register_operand" "=r")
7230 [(match_operand:TI 1 "register_operand" "r")
7231 (use (match_operand:DI 2 "register_operand" ""))]
7232 UNSPECV_SPECULATION_BARRIER))]
7234 "and\\t%0, %1, %2\;and\\t%H0, %H1, %2\;hint\t0x14 // csdb"
7235 [(set_attr "type" "block")
7236 (set_attr "length" "12")
7237 (set_attr "speculation_barrier" "true")]
7241 (include "aarch64-simd.md")
7243 ;; Atomic Operations
7244 (include "atomics.md")
7246 ;; ldp/stp peephole patterns
7247 (include "aarch64-ldpstp.md")
7250 (include "aarch64-sve.md")
7253 (include "aarch64-sve2.md")