1 ;; Machine description for AArch64 architecture.
2 ;; Copyright (C) 2009-2018 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/>.
69 (LAST_SAVED_REGNUM 63)
73 ;; Defined only to make the DWARF description simpler.
94 (define_c_enum "unspec" [
120 UNSPEC_GOTSMALLPIC28K
200 (define_c_enum "unspecv" [
201 UNSPECV_EH_RETURN ; Represent EH_RETURN
202 UNSPECV_GET_FPCR ; Represent fetch of FPCR content.
203 UNSPECV_SET_FPCR ; Represent assign of FPCR content.
204 UNSPECV_GET_FPSR ; Represent fetch of FPSR content.
205 UNSPECV_SET_FPSR ; Represent assign of FPSR content.
206 UNSPECV_BLOCKAGE ; Represent a blockage
207 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
211 ;; If further include files are added the defintion of MD_INCLUDES
214 (include "constraints.md")
215 (include "predicates.md")
216 (include "iterators.md")
218 ;; -------------------------------------------------------------------
219 ;; Instruction types and attributes
220 ;; -------------------------------------------------------------------
222 ; The "type" attribute is included here from AArch32 backend to be able
223 ; to share pipeline descriptions.
224 (include "../arm/types.md")
226 ;; It is important to set the fp or simd attributes to yes when a pattern
227 ;; alternative uses the FP or SIMD register files, usually signified by use of
228 ;; the 'w' constraint. This will ensure that the alternative will be
229 ;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd
230 ;; architecture extensions. If all the alternatives in a pattern use the
231 ;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT
234 ;; Attribute that specifies whether or not the instruction touches fp
235 ;; registers. When this is set to yes for an alternative, that alternative
236 ;; will be disabled when !TARGET_FLOAT.
237 (define_attr "fp" "no,yes" (const_string "no"))
239 ;; Attribute that specifies whether or not the instruction touches half
240 ;; precision fp registers. When this is set to yes for an alternative,
241 ;; that alternative will be disabled when !TARGET_FP_F16INST.
242 (define_attr "fp16" "no,yes" (const_string "no"))
244 ;; Attribute that specifies whether or not the instruction touches simd
245 ;; registers. When this is set to yes for an alternative, that alternative
246 ;; will be disabled when !TARGET_SIMD.
247 (define_attr "simd" "no,yes" (const_string "no"))
249 ;; Attribute that specifies whether or not the instruction uses SVE.
250 ;; When this is set to yes for an alternative, that alternative
251 ;; will be disabled when !TARGET_SVE.
252 (define_attr "sve" "no,yes" (const_string "no"))
254 (define_attr "length" ""
257 ;; Attribute that controls whether an alternative is enabled or not.
258 ;; Currently it is only used to disable alternatives which touch fp or simd
259 ;; registers when -mgeneral-regs-only is specified.
260 (define_attr "enabled" "no,yes"
262 (and (eq_attr "fp" "yes")
263 (eq (symbol_ref "TARGET_FLOAT") (const_int 0)))
264 (and (eq_attr "simd" "yes")
265 (eq (symbol_ref "TARGET_SIMD") (const_int 0)))
266 (and (eq_attr "fp16" "yes")
267 (eq (symbol_ref "TARGET_FP_F16INST") (const_int 0)))
268 (and (eq_attr "sve" "yes")
269 (eq (symbol_ref "TARGET_SVE") (const_int 0))))
271 ] (const_string "yes")))
273 ;; Attribute that specifies whether we are dealing with a branch to a
274 ;; label that is far away, i.e. further away than the maximum/minimum
275 ;; representable in a signed 21-bits number.
278 (define_attr "far_branch" "" (const_int 0))
280 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
281 ;; no predicated insns.
282 (define_attr "predicated" "yes,no" (const_string "no"))
284 ;; -------------------------------------------------------------------
285 ;; Pipeline descriptions and scheduling
286 ;; -------------------------------------------------------------------
289 (include "aarch64-tune.md")
292 (include "../arm/cortex-a53.md")
293 (include "../arm/cortex-a57.md")
294 (include "../arm/exynos-m1.md")
295 (include "falkor.md")
296 (include "thunderx.md")
297 (include "../arm/xgene1.md")
298 (include "thunderx2t99.md")
300 ;; -------------------------------------------------------------------
301 ;; Jumps and other miscellaneous insns
302 ;; -------------------------------------------------------------------
304 (define_insn "indirect_jump"
305 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
308 [(set_attr "type" "branch")]
312 [(set (pc) (label_ref (match_operand 0 "" "")))]
315 [(set_attr "type" "branch")]
318 (define_expand "cbranch<mode>4"
319 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
320 [(match_operand:GPI 1 "register_operand" "")
321 (match_operand:GPI 2 "aarch64_plus_operand" "")])
322 (label_ref (match_operand 3 "" ""))
326 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
328 operands[2] = const0_rtx;
332 (define_expand "cbranch<mode>4"
333 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
334 [(match_operand:GPF 1 "register_operand" "")
335 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
336 (label_ref (match_operand 3 "" ""))
340 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
342 operands[2] = const0_rtx;
346 (define_expand "cbranchcc4"
347 [(set (pc) (if_then_else
348 (match_operator 0 "aarch64_comparison_operator"
349 [(match_operand 1 "cc_register" "")
350 (match_operand 2 "const0_operand")])
351 (label_ref (match_operand 3 "" ""))
356 (define_insn "ccmp<mode>"
357 [(set (match_operand:CC 1 "cc_register" "")
359 (match_operator 4 "aarch64_comparison_operator"
360 [(match_operand 0 "cc_register" "")
363 (match_operand:GPI 2 "register_operand" "r,r,r")
364 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn"))
365 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
368 ccmp\\t%<w>2, %<w>3, %k5, %m4
369 ccmp\\t%<w>2, %3, %k5, %m4
370 ccmn\\t%<w>2, #%n3, %k5, %m4"
371 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
374 (define_insn "fccmp<mode>"
375 [(set (match_operand:CCFP 1 "cc_register" "")
377 (match_operator 4 "aarch64_comparison_operator"
378 [(match_operand 0 "cc_register" "")
381 (match_operand:GPF 2 "register_operand" "w")
382 (match_operand:GPF 3 "register_operand" "w"))
383 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
385 "fccmp\\t%<s>2, %<s>3, %k5, %m4"
386 [(set_attr "type" "fccmp<s>")]
389 (define_insn "fccmpe<mode>"
390 [(set (match_operand:CCFPE 1 "cc_register" "")
392 (match_operator 4 "aarch64_comparison_operator"
393 [(match_operand 0 "cc_register" "")
396 (match_operand:GPF 2 "register_operand" "w")
397 (match_operand:GPF 3 "register_operand" "w"))
398 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))]
400 "fccmpe\\t%<s>2, %<s>3, %k5, %m4"
401 [(set_attr "type" "fccmp<s>")]
404 ;; Expansion of signed mod by a power of 2 using CSNEG.
405 ;; For x0 % n where n is a power of 2 produce:
407 ;; and x0, x0, #(n - 1)
408 ;; and x1, x1, #(n - 1)
409 ;; csneg x0, x0, x1, mi
411 (define_expand "mod<mode>3"
412 [(match_operand:GPI 0 "register_operand" "")
413 (match_operand:GPI 1 "register_operand" "")
414 (match_operand:GPI 2 "const_int_operand" "")]
417 HOST_WIDE_INT val = INTVAL (operands[2]);
420 || exact_log2 (val) <= 0
421 || !aarch64_bitmask_imm (val - 1, <MODE>mode))
424 rtx mask = GEN_INT (val - 1);
426 /* In the special case of x0 % 2 we can do the even shorter:
432 rtx masked = gen_reg_rtx (<MODE>mode);
433 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
434 emit_insn (gen_and<mode>3 (masked, operands[1], mask));
435 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
436 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked));
440 rtx neg_op = gen_reg_rtx (<MODE>mode);
441 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1]));
443 /* Extract the condition register and mode. */
444 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
445 rtx cc_reg = SET_DEST (cmp);
446 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx);
448 rtx masked_pos = gen_reg_rtx (<MODE>mode);
449 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask));
451 rtx masked_neg = gen_reg_rtx (<MODE>mode);
452 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask));
454 emit_insn (gen_csneg3<mode>_insn (operands[0], cond,
455 masked_neg, masked_pos));
460 (define_insn "condjump"
461 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
462 [(match_operand 1 "cc_register" "") (const_int 0)])
463 (label_ref (match_operand 2 "" ""))
467 if (get_attr_length (insn) == 8)
468 return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
472 [(set_attr "type" "branch")
474 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
475 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
478 (set (attr "far_branch")
479 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
480 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
485 ;; For a 24-bit immediate CST we can optimize the compare for equality
486 ;; and branch sequence from:
488 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
492 ;; sub x0, x1, #(CST & 0xfff000)
493 ;; subs x0, x0, #(CST & 0x000fff)
495 (define_insn_and_split "*compare_condjump<mode>"
496 [(set (pc) (if_then_else (EQL
497 (match_operand:GPI 0 "register_operand" "r")
498 (match_operand:GPI 1 "aarch64_imm24" "n"))
499 (label_ref:P (match_operand 2 "" ""))
501 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode)
502 && !aarch64_plus_operand (operands[1], <MODE>mode)
503 && !reload_completed"
508 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff;
509 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000;
510 rtx tmp = gen_reg_rtx (<MODE>mode);
511 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm)));
512 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
513 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
514 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
515 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2]));
520 (define_expand "casesi"
521 [(match_operand:SI 0 "register_operand" "") ; Index
522 (match_operand:SI 1 "const_int_operand" "") ; Lower bound
523 (match_operand:SI 2 "const_int_operand" "") ; Total range
524 (match_operand:DI 3 "" "") ; Table label
525 (match_operand:DI 4 "" "")] ; Out of range label
528 if (operands[1] != const0_rtx)
530 rtx reg = gen_reg_rtx (SImode);
532 /* Canonical RTL says that if you have:
536 then this should be emitted as:
540 The use of trunc_int_for_mode ensures that the resulting
541 constant can be represented in SImode, this is important
542 for the corner case where operand[1] is INT_MIN. */
544 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode));
546 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate)
547 (operands[1], SImode))
548 operands[1] = force_reg (SImode, operands[1]);
549 emit_insn (gen_addsi3 (reg, operands[0], operands[1]));
553 if (!aarch64_plus_operand (operands[2], SImode))
554 operands[2] = force_reg (SImode, operands[2]);
555 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx,
557 operands[0], operands[2], operands[4]));
559 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3]));
560 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0],
566 (define_insn "casesi_dispatch"
569 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r")
570 (match_operand:SI 1 "register_operand" "r")]
572 (clobber (reg:CC CC_REGNUM))
573 (clobber (match_scratch:DI 3 "=r"))
574 (clobber (match_scratch:DI 4 "=r"))
575 (use (label_ref (match_operand 2 "" "")))])]
578 return aarch64_output_casesi (operands);
580 [(set_attr "length" "16")
581 (set_attr "type" "branch")]
585 [(unspec[(const_int 0)] UNSPEC_NOP)]
588 [(set_attr "type" "no_insn")]
591 (define_insn "prefetch"
592 [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
593 (match_operand:QI 1 "const_int_operand" "")
594 (match_operand:QI 2 "const_int_operand" ""))]
597 const char * pftype[2][4] =
599 {"prfm\\tPLDL1STRM, %0",
600 "prfm\\tPLDL3KEEP, %0",
601 "prfm\\tPLDL2KEEP, %0",
602 "prfm\\tPLDL1KEEP, %0"},
603 {"prfm\\tPSTL1STRM, %0",
604 "prfm\\tPSTL3KEEP, %0",
605 "prfm\\tPSTL2KEEP, %0",
606 "prfm\\tPSTL1KEEP, %0"},
609 int locality = INTVAL (operands[2]);
611 gcc_assert (IN_RANGE (locality, 0, 3));
613 /* PRFM accepts the same addresses as a 64-bit LDR so wrap
614 the address into a DImode MEM so that aarch64_print_operand knows
616 operands[0] = gen_rtx_MEM (DImode, operands[0]);
617 return pftype[INTVAL(operands[1])][locality];
619 [(set_attr "type" "load_4")]
623 [(trap_if (const_int 1) (const_int 8))]
626 [(set_attr "type" "trap")])
628 (define_expand "prologue"
629 [(clobber (const_int 0))]
632 aarch64_expand_prologue ();
637 (define_expand "epilogue"
638 [(clobber (const_int 0))]
641 aarch64_expand_epilogue (false);
646 (define_expand "sibcall_epilogue"
647 [(clobber (const_int 0))]
650 aarch64_expand_epilogue (true);
655 (define_insn "*do_return"
659 if (aarch64_return_address_signing_enabled ()
661 && !crtl->calls_eh_return)
666 [(set_attr "type" "branch")]
669 (define_expand "return"
671 "aarch64_use_return_insn_p ()"
675 (define_insn "simple_return"
679 [(set_attr "type" "branch")]
682 (define_insn "*cb<optab><mode>1"
683 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r")
685 (label_ref (match_operand 1 "" ""))
689 if (get_attr_length (insn) == 8)
690 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, ");
692 return "<cbz>\\t%<w>0, %l1";
694 [(set_attr "type" "branch")
696 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
697 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
700 (set (attr "far_branch")
701 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
702 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
707 (define_insn "*tb<optab><mode>1"
708 [(set (pc) (if_then_else
709 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
712 "aarch64_simd_shift_imm_<mode>" "n"))
714 (label_ref (match_operand 2 "" ""))
716 (clobber (reg:CC CC_REGNUM))]
719 if (get_attr_length (insn) == 8)
721 if (get_attr_far_branch (insn) == 1)
722 return aarch64_gen_far_branch (operands, 2, "Ltb",
723 "<inv_tb>\\t%<w>0, %1, ");
726 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1]));
727 return "tst\t%<w>0, %1\;<bcond>\t%l2";
731 return "<tbz>\t%<w>0, %1, %l2";
733 [(set_attr "type" "branch")
735 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768))
736 (lt (minus (match_dup 2) (pc)) (const_int 32764)))
739 (set (attr "far_branch")
740 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576))
741 (lt (minus (match_dup 2) (pc)) (const_int 1048572)))
747 (define_insn "*cb<optab><mode>1"
748 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r")
750 (label_ref (match_operand 1 "" ""))
752 (clobber (reg:CC CC_REGNUM))]
755 if (get_attr_length (insn) == 8)
757 if (get_attr_far_branch (insn) == 1)
758 return aarch64_gen_far_branch (operands, 1, "Ltb",
759 "<inv_tb>\\t%<w>0, <sizem1>, ");
763 uint64_t val = ((uint64_t) 1)
764 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1);
765 sprintf (buf, "tst\t%%<w>0, %" PRId64, val);
766 output_asm_insn (buf, operands);
767 return "<bcond>\t%l1";
771 return "<tbz>\t%<w>0, <sizem1>, %l1";
773 [(set_attr "type" "branch")
775 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
776 (lt (minus (match_dup 1) (pc)) (const_int 32764)))
779 (set (attr "far_branch")
780 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576))
781 (lt (minus (match_dup 1) (pc)) (const_int 1048572)))
786 ;; -------------------------------------------------------------------
787 ;; Subroutine calls and sibcalls
788 ;; -------------------------------------------------------------------
790 (define_expand "call"
791 [(parallel [(call (match_operand 0 "memory_operand" "")
792 (match_operand 1 "general_operand" ""))
793 (use (match_operand 2 "" ""))
794 (clobber (reg:DI LR_REGNUM))])]
798 aarch64_expand_call (NULL_RTX, operands[0], false);
803 (define_insn "*call_insn"
804 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
805 (match_operand 1 "" ""))
806 (clobber (reg:DI LR_REGNUM))]
811 [(set_attr "type" "call, call")]
814 (define_expand "call_value"
815 [(parallel [(set (match_operand 0 "" "")
816 (call (match_operand 1 "memory_operand" "")
817 (match_operand 2 "general_operand" "")))
818 (use (match_operand 3 "" ""))
819 (clobber (reg:DI LR_REGNUM))])]
823 aarch64_expand_call (operands[0], operands[1], false);
828 (define_insn "*call_value_insn"
829 [(set (match_operand 0 "" "")
830 (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
831 (match_operand 2 "" "")))
832 (clobber (reg:DI LR_REGNUM))]
837 [(set_attr "type" "call, call")]
840 (define_expand "sibcall"
841 [(parallel [(call (match_operand 0 "memory_operand" "")
842 (match_operand 1 "general_operand" ""))
844 (use (match_operand 2 "" ""))])]
847 aarch64_expand_call (NULL_RTX, operands[0], true);
852 (define_expand "sibcall_value"
853 [(parallel [(set (match_operand 0 "" "")
854 (call (match_operand 1 "memory_operand" "")
855 (match_operand 2 "general_operand" "")))
857 (use (match_operand 3 "" ""))])]
860 aarch64_expand_call (operands[0], operands[1], true);
865 (define_insn "*sibcall_insn"
866 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf"))
867 (match_operand 1 "" ""))
869 "SIBLING_CALL_P (insn)"
873 [(set_attr "type" "branch, branch")]
876 (define_insn "*sibcall_value_insn"
877 [(set (match_operand 0 "" "")
879 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf"))
880 (match_operand 2 "" "")))
882 "SIBLING_CALL_P (insn)"
886 [(set_attr "type" "branch, branch")]
889 ;; Call subroutine returning any type.
891 (define_expand "untyped_call"
892 [(parallel [(call (match_operand 0 "")
895 (match_operand 2 "")])]
900 emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
902 for (i = 0; i < XVECLEN (operands[2], 0); i++)
904 rtx set = XVECEXP (operands[2], 0, i);
905 emit_move_insn (SET_DEST (set), SET_SRC (set));
908 /* The optimizer does not know that the call sets the function value
909 registers we stored in the result block. We avoid problems by
910 claiming that all hard registers are used and clobbered at this
912 emit_insn (gen_blockage ());
916 ;; -------------------------------------------------------------------
918 ;; -------------------------------------------------------------------
920 (define_expand "mov<mode>"
921 [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
922 (match_operand:SHORT 1 "general_operand" ""))]
925 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
926 operands[1] = force_reg (<MODE>mode, operands[1]);
928 if (GET_CODE (operands[1]) == CONST_POLY_INT)
930 aarch64_expand_mov_immediate (operands[0], operands[1]);
936 (define_insn "*mov<mode>_aarch64"
937 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, w,r ,r,w, m,m,r,w,w")
938 (match_operand:SHORT 1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m,m,rZ,w,w,r,w"))]
939 "(register_operand (operands[0], <MODE>mode)
940 || aarch64_reg_or_zero (operands[1], <MODE>mode))"
942 switch (which_alternative)
945 return "mov\t%w0, %w1";
947 return "mov\t%w0, %1";
949 return aarch64_output_scalar_simd_mov_immediate (operands[1],
952 return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
954 return "ldr<size>\t%w0, %1";
956 return "ldr\t%<size>0, %1";
958 return "str<size>\t%w1, %0";
960 return "str\t%<size>1, %0";
962 return "umov\t%w0, %1.<v>[0]";
964 return "dup\t%0.<Vallxd>, %w1";
966 return "dup\t%<Vetype>0, %1.<v>[0]";
971 ;; The "mov_imm" type for CNT is just a placeholder.
972 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4,
973 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup")
974 (set_attr "simd" "*,*,yes,*,*,*,*,*,yes,yes,yes")
975 (set_attr "sve" "*,*,*,yes,*,*,*,*,*,*,*")]
978 (define_expand "mov<mode>"
979 [(set (match_operand:GPI 0 "nonimmediate_operand" "")
980 (match_operand:GPI 1 "general_operand" ""))]
983 if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
984 && <MODE>mode == DImode
985 && aarch64_split_dimode_const_store (operands[0], operands[1]))
988 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
989 operands[1] = force_reg (<MODE>mode, operands[1]);
991 /* FIXME: RR we still need to fix up what we are doing with
992 symbol_refs and other types of constants. */
993 if (CONSTANT_P (operands[1])
994 && !CONST_INT_P (operands[1]))
996 aarch64_expand_mov_immediate (operands[0], operands[1]);
1002 (define_insn_and_split "*movsi_aarch64"
1003 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w")
1004 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Ds"))]
1005 "(register_operand (operands[0], SImode)
1006 || aarch64_reg_or_zero (operands[1], SImode))"
1013 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1023 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);"
1024 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode)
1025 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1028 aarch64_expand_mov_immediate (operands[0], operands[1]);
1031 ;; The "mov_imm" type for CNT is just a placeholder.
1032 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4,
1033 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move")
1034 (set_attr "fp" "*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1035 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
1036 (set_attr "sve" "*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
1039 (define_insn_and_split "*movdi_aarch64"
1040 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w")
1041 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))]
1042 "(register_operand (operands[0], DImode)
1043 || aarch64_reg_or_zero (operands[1], DImode))"
1051 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]);
1061 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);"
1062 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode))
1063 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))"
1066 aarch64_expand_mov_immediate (operands[0], operands[1]);
1069 ;; The "mov_imm" type for CNTD is just a placeholder.
1070 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm,
1071 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov,
1073 (set_attr "fp" "*,*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*")
1074 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes")
1075 (set_attr "sve" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")]
1078 (define_insn "insv_imm<mode>"
1079 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
1081 (match_operand:GPI 1 "const_int_operand" "n"))
1082 (match_operand:GPI 2 "const_int_operand" "n"))]
1083 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode)
1084 && UINTVAL (operands[1]) % 16 == 0"
1085 "movk\\t%<w>0, %X2, lsl %1"
1086 [(set_attr "type" "mov_imm")]
1089 (define_expand "movti"
1090 [(set (match_operand:TI 0 "nonimmediate_operand" "")
1091 (match_operand:TI 1 "general_operand" ""))]
1094 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
1095 operands[1] = force_reg (TImode, operands[1]);
1097 if (GET_CODE (operands[1]) == CONST_POLY_INT)
1099 emit_move_insn (gen_lowpart (DImode, operands[0]),
1100 gen_lowpart (DImode, operands[1]));
1101 emit_move_insn (gen_highpart (DImode, operands[0]), const0_rtx);
1107 (define_insn "*movti_aarch64"
1108 [(set (match_operand:TI 0
1109 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m")
1111 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))]
1112 "(register_operand (operands[0], TImode)
1113 || aarch64_reg_or_zero (operands[1], TImode))"
1118 mov\\t%0.16b, %1.16b
1124 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \
1125 load_16,store_16,store_16,\
1127 (set_attr "length" "8,8,8,4,4,4,4,4,4")
1128 (set_attr "simd" "*,*,*,yes,*,*,*,*,*")
1129 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")]
1132 ;; Split a TImode register-register or register-immediate move into
1133 ;; its component DImode pieces, taking care to handle overlapping
1134 ;; source and dest registers.
1136 [(set (match_operand:TI 0 "register_operand" "")
1137 (match_operand:TI 1 "aarch64_reg_or_imm" ""))]
1138 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1141 aarch64_split_128bit_move (operands[0], operands[1]);
1145 (define_expand "mov<mode>"
1146 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
1147 (match_operand:GPF_TF_F16 1 "general_operand" ""))]
1152 aarch64_err_no_fpadvsimd (<MODE>mode, "code");
1156 if (GET_CODE (operands[0]) == MEM
1157 && ! (GET_CODE (operands[1]) == CONST_DOUBLE
1158 && aarch64_float_const_zero_rtx_p (operands[1])))
1159 operands[1] = force_reg (<MODE>mode, operands[1]);
1163 (define_insn "*movhf_aarch64"
1164 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r")
1165 (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))]
1166 "TARGET_FLOAT && (register_operand (operands[0], HFmode)
1167 || aarch64_reg_or_fp_zero (operands[1], HFmode))"
1172 mov\\t%0.h[0], %1.h[0]
1174 * return aarch64_output_scalar_simd_mov_immediate (operands[1], HImode);
1180 [(set_attr "type" "neon_move,f_mcr,neon_to_gp,neon_move,fconsts, \
1181 neon_move,f_loads,f_stores,load_4,store_4,mov_reg")
1182 (set_attr "simd" "yes,*,yes,yes,*,yes,*,*,*,*,*")
1183 (set_attr "fp16" "*,yes,*,*,yes,*,*,*,*,*,*")]
1186 (define_insn "*movsf_aarch64"
1187 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r")
1188 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
1189 "TARGET_FLOAT && (register_operand (operands[0], SFmode)
1190 || aarch64_reg_or_fp_zero (operands[1], SFmode))"
1197 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);
1204 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\
1205 f_loads,f_stores,load_4,store_4,mov_reg,\
1207 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1210 (define_insn "*movdf_aarch64"
1211 [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r")
1212 (match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
1213 "TARGET_FLOAT && (register_operand (operands[0], DFmode)
1214 || aarch64_reg_or_fp_zero (operands[1], DFmode))"
1221 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);
1228 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\
1229 f_loadd,f_stored,load_8,store_8,mov_reg,\
1231 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")]
1235 [(set (match_operand:GPF_HF 0 "nonimmediate_operand")
1236 (match_operand:GPF_HF 1 "general_operand"))]
1237 "can_create_pseudo_p ()
1238 && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode)
1239 && !aarch64_float_const_representable_p (operands[1])
1240 && aarch64_float_const_rtx_p (operands[1])"
1243 unsigned HOST_WIDE_INT ival;
1244 if (!aarch64_reinterpret_float_as_int (operands[1], &ival))
1247 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode);
1248 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode));
1249 emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp));
1254 (define_insn "*movtf_aarch64"
1255 [(set (match_operand:TF 0
1256 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
1258 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
1259 "TARGET_FLOAT && (register_operand (operands[0], TFmode)
1260 || aarch64_reg_or_fp_zero (operands[1], TFmode))"
1262 mov\\t%0.16b, %1.16b
1273 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\
1274 f_loadd,f_stored,load_16,store_16,store_16")
1275 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4")
1276 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")]
1280 [(set (match_operand:TF 0 "register_operand" "")
1281 (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
1282 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
1285 aarch64_split_128bit_move (operands[0], operands[1]);
1292 ;; 2 is size of move in bytes
1295 (define_expand "movmemdi"
1296 [(match_operand:BLK 0 "memory_operand")
1297 (match_operand:BLK 1 "memory_operand")
1298 (match_operand:DI 2 "immediate_operand")
1299 (match_operand:DI 3 "immediate_operand")]
1302 if (aarch64_expand_movmem (operands))
1308 ;; Operands 1 and 3 are tied together by the final condition; so we allow
1309 ;; fairly lax checking on the second memory operation.
1310 (define_insn "load_pair_sw_<SX:mode><SX2:mode>"
1311 [(set (match_operand:SX 0 "register_operand" "=r,w")
1312 (match_operand:SX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1313 (set (match_operand:SX2 2 "register_operand" "=r,w")
1314 (match_operand:SX2 3 "memory_operand" "m,m"))]
1315 "rtx_equal_p (XEXP (operands[3], 0),
1316 plus_constant (Pmode,
1317 XEXP (operands[1], 0),
1318 GET_MODE_SIZE (<SX:MODE>mode)))"
1322 [(set_attr "type" "load_8,neon_load1_2reg")
1323 (set_attr "fp" "*,yes")]
1326 ;; Storing different modes that can still be merged
1327 (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
1328 [(set (match_operand:DX 0 "register_operand" "=r,w")
1329 (match_operand:DX 1 "aarch64_mem_pair_operand" "Ump,Ump"))
1330 (set (match_operand:DX2 2 "register_operand" "=r,w")
1331 (match_operand:DX2 3 "memory_operand" "m,m"))]
1332 "rtx_equal_p (XEXP (operands[3], 0),
1333 plus_constant (Pmode,
1334 XEXP (operands[1], 0),
1335 GET_MODE_SIZE (<DX:MODE>mode)))"
1339 [(set_attr "type" "load_16,neon_load1_2reg")
1340 (set_attr "fp" "*,yes")]
1343 ;; Operands 0 and 2 are tied together by the final condition; so we allow
1344 ;; fairly lax checking on the second memory operation.
1345 (define_insn "store_pair_sw_<SX:mode><SX2:mode>"
1346 [(set (match_operand:SX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1347 (match_operand:SX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1348 (set (match_operand:SX2 2 "memory_operand" "=m,m")
1349 (match_operand:SX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1350 "rtx_equal_p (XEXP (operands[2], 0),
1351 plus_constant (Pmode,
1352 XEXP (operands[0], 0),
1353 GET_MODE_SIZE (<SX:MODE>mode)))"
1357 [(set_attr "type" "store_8,neon_store1_2reg")
1358 (set_attr "fp" "*,yes")]
1361 ;; Storing different modes that can still be merged
1362 (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
1363 [(set (match_operand:DX 0 "aarch64_mem_pair_operand" "=Ump,Ump")
1364 (match_operand:DX 1 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))
1365 (set (match_operand:DX2 2 "memory_operand" "=m,m")
1366 (match_operand:DX2 3 "aarch64_reg_zero_or_fp_zero" "rYZ,w"))]
1367 "rtx_equal_p (XEXP (operands[2], 0),
1368 plus_constant (Pmode,
1369 XEXP (operands[0], 0),
1370 GET_MODE_SIZE (<DX:MODE>mode)))"
1374 [(set_attr "type" "store_16,neon_store1_2reg")
1375 (set_attr "fp" "*,yes")]
1378 ;; Load pair with post-index writeback. This is primarily used in function
1380 (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
1382 [(set (match_operand:P 0 "register_operand" "=k")
1383 (plus:P (match_operand:P 1 "register_operand" "0")
1384 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1385 (set (match_operand:GPI 2 "register_operand" "=r")
1386 (mem:GPI (match_dup 1)))
1387 (set (match_operand:GPI 3 "register_operand" "=r")
1388 (mem:GPI (plus:P (match_dup 1)
1389 (match_operand:P 5 "const_int_operand" "n"))))])]
1390 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)"
1391 "ldp\\t%<w>2, %<w>3, [%1], %4"
1392 [(set_attr "type" "load_<ldpstp_sz>")]
1395 (define_insn "loadwb_pair<GPF:mode>_<P:mode>"
1397 [(set (match_operand:P 0 "register_operand" "=k")
1398 (plus:P (match_operand:P 1 "register_operand" "0")
1399 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1400 (set (match_operand:GPF 2 "register_operand" "=w")
1401 (mem:GPF (match_dup 1)))
1402 (set (match_operand:GPF 3 "register_operand" "=w")
1403 (mem:GPF (plus:P (match_dup 1)
1404 (match_operand:P 5 "const_int_operand" "n"))))])]
1405 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
1406 "ldp\\t%<w>2, %<w>3, [%1], %4"
1407 [(set_attr "type" "neon_load1_2reg")]
1410 ;; Store pair with pre-index writeback. This is primarily used in function
1412 (define_insn "storewb_pair<GPI:mode>_<P:mode>"
1414 [(set (match_operand:P 0 "register_operand" "=&k")
1415 (plus:P (match_operand:P 1 "register_operand" "0")
1416 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1417 (set (mem:GPI (plus:P (match_dup 0)
1419 (match_operand:GPI 2 "register_operand" "r"))
1420 (set (mem:GPI (plus:P (match_dup 0)
1421 (match_operand:P 5 "const_int_operand" "n")))
1422 (match_operand:GPI 3 "register_operand" "r"))])]
1423 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)"
1424 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1425 [(set_attr "type" "store_<ldpstp_sz>")]
1428 (define_insn "storewb_pair<GPF:mode>_<P:mode>"
1430 [(set (match_operand:P 0 "register_operand" "=&k")
1431 (plus:P (match_operand:P 1 "register_operand" "0")
1432 (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
1433 (set (mem:GPF (plus:P (match_dup 0)
1435 (match_operand:GPF 2 "register_operand" "w"))
1436 (set (mem:GPF (plus:P (match_dup 0)
1437 (match_operand:P 5 "const_int_operand" "n")))
1438 (match_operand:GPF 3 "register_operand" "w"))])]
1439 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
1440 "stp\\t%<w>2, %<w>3, [%0, %4]!"
1441 [(set_attr "type" "neon_store1_2reg<q>")]
1444 ;; -------------------------------------------------------------------
1445 ;; Sign/Zero extension
1446 ;; -------------------------------------------------------------------
1448 (define_expand "<optab>sidi2"
1449 [(set (match_operand:DI 0 "register_operand")
1450 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))]
1454 (define_insn "*extendsidi2_aarch64"
1455 [(set (match_operand:DI 0 "register_operand" "=r,r")
1456 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1461 [(set_attr "type" "extend,load_4")]
1464 (define_insn "*load_pair_extendsidi2_aarch64"
1465 [(set (match_operand:DI 0 "register_operand" "=r")
1466 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1467 (set (match_operand:DI 2 "register_operand" "=r")
1468 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1469 "rtx_equal_p (XEXP (operands[3], 0),
1470 plus_constant (Pmode,
1471 XEXP (operands[1], 0),
1472 GET_MODE_SIZE (SImode)))"
1473 "ldpsw\\t%0, %2, %1"
1474 [(set_attr "type" "load_8")]
1477 (define_insn "*zero_extendsidi2_aarch64"
1478 [(set (match_operand:DI 0 "register_operand" "=r,r")
1479 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1484 [(set_attr "type" "extend,load_4")]
1487 (define_insn "*load_pair_zero_extendsidi2_aarch64"
1488 [(set (match_operand:DI 0 "register_operand" "=r")
1489 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump")))
1490 (set (match_operand:DI 2 "register_operand" "=r")
1491 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
1492 "rtx_equal_p (XEXP (operands[3], 0),
1493 plus_constant (Pmode,
1494 XEXP (operands[1], 0),
1495 GET_MODE_SIZE (SImode)))"
1496 "ldp\\t%w0, %w2, %1"
1497 [(set_attr "type" "load_8")]
1500 (define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2"
1501 [(set (match_operand:GPI 0 "register_operand")
1502 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
1506 (define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64"
1507 [(set (match_operand:GPI 0 "register_operand" "=r,r")
1508 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1511 sxt<SHORT:size>\t%<GPI:w>0, %w1
1512 ldrs<SHORT:size>\t%<GPI:w>0, %1"
1513 [(set_attr "type" "extend,load_4")]
1516 (define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64"
1517 [(set (match_operand:GPI 0 "register_operand" "=r,r,w")
1518 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))]
1521 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask>
1522 ldr<SHORT:size>\t%w0, %1
1523 ldr\t%<SHORT:size>0, %1"
1524 [(set_attr "type" "logic_imm,load_4,load_4")]
1527 (define_expand "<optab>qihi2"
1528 [(set (match_operand:HI 0 "register_operand")
1529 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))]
1533 (define_insn "*extendqihi2_aarch64"
1534 [(set (match_operand:HI 0 "register_operand" "=r,r")
1535 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1540 [(set_attr "type" "extend,load_4")]
1543 (define_insn "*zero_extendqihi2_aarch64"
1544 [(set (match_operand:HI 0 "register_operand" "=r,r")
1545 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1550 [(set_attr "type" "logic_imm,load_4")]
1553 ;; -------------------------------------------------------------------
1554 ;; Simple arithmetic
1555 ;; -------------------------------------------------------------------
1557 (define_expand "add<mode>3"
1559 (match_operand:GPI 0 "register_operand" "")
1560 (plus:GPI (match_operand:GPI 1 "register_operand" "")
1561 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "")))]
1564 /* If operands[1] is a subreg extract the inner RTX. */
1565 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]);
1567 /* If the constant is too large for a single instruction and isn't frame
1568 based, split off the immediate so it is available for CSE. */
1569 if (!aarch64_plus_immediate (operands[2], <MODE>mode)
1570 && can_create_pseudo_p ()
1572 || !REGNO_PTR_FRAME_P (REGNO (op1))))
1573 operands[2] = force_reg (<MODE>mode, operands[2]);
1574 /* Expand polynomial additions now if the destination is the stack
1575 pointer, since we don't want to use that as a temporary. */
1576 else if (operands[0] == stack_pointer_rtx
1577 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode))
1579 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
1580 operands[2], NULL_RTX, NULL_RTX);
1585 (define_insn "*add<mode>3_aarch64"
1587 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,rk")
1589 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,rk")
1590 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uav")))]
1593 add\\t%<w>0, %<w>1, %2
1594 add\\t%<w>0, %<w>1, %<w>2
1595 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>
1596 sub\\t%<w>0, %<w>1, #%n2
1598 * return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]);"
1599 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1600 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm")
1601 (set_attr "simd" "*,*,yes,*,*,*")]
1604 ;; zero_extend version of above
1605 (define_insn "*addsi3_aarch64_uxtw"
1607 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r")
1609 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk")
1610 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))]
1615 sub\\t%w0, %w1, #%n2
1617 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")]
1620 ;; If there's a free register, and we can load the constant with a
1621 ;; single instruction, do so. This has a chance to improve scheduling.
1623 [(match_scratch:GPI 3 "r")
1624 (set (match_operand:GPI 0 "register_operand")
1626 (match_operand:GPI 1 "register_operand")
1627 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1628 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)"
1629 [(set (match_dup 3) (match_dup 2))
1630 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))]
1634 [(match_scratch:SI 3 "r")
1635 (set (match_operand:DI 0 "register_operand")
1638 (match_operand:SI 1 "register_operand")
1639 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1640 "aarch64_move_imm (INTVAL (operands[2]), SImode)"
1641 [(set (match_dup 3) (match_dup 2))
1642 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))]
1645 ;; After peephole2 has had a chance to run, split any remaining long
1646 ;; additions into two add immediates.
1648 [(set (match_operand:GPI 0 "register_operand")
1650 (match_operand:GPI 1 "register_operand")
1651 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))]
1652 "epilogue_completed"
1653 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))
1654 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))]
1656 HOST_WIDE_INT i = INTVAL (operands[2]);
1657 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1658 operands[3] = GEN_INT (i - s);
1659 operands[4] = GEN_INT (s);
1663 ;; Match addition of polynomial offsets that require one temporary, for which
1664 ;; we can use the early-clobbered destination register. This is a separate
1665 ;; pattern so that the early clobber doesn't affect register allocation
1666 ;; for other forms of addition. However, we still need to provide an
1667 ;; all-register alternative, in case the offset goes out of range after
1668 ;; elimination. For completeness we might as well provide all GPR-based
1669 ;; alternatives from the main pattern.
1671 ;; We don't have a pattern for additions requiring two temporaries since at
1672 ;; present LRA doesn't allow new scratches to be added during elimination.
1673 ;; Such offsets should be rare anyway.
1675 ;; ??? But if we added LRA support for new scratches, much of the ugliness
1676 ;; here would go away. We could just handle all polynomial constants in
1678 (define_insn_and_split "*add<mode>3_poly_1"
1680 (match_operand:GPI 0 "register_operand" "=r,r,r,r,r,&r")
1682 (match_operand:GPI 1 "register_operand" "%rk,rk,rk,rk,rk,rk")
1683 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uat")))]
1684 "TARGET_SVE && operands[0] != stack_pointer_rtx"
1686 add\\t%<w>0, %<w>1, %2
1687 add\\t%<w>0, %<w>1, %<w>2
1688 sub\\t%<w>0, %<w>1, #%n2
1690 * return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]);
1692 "&& epilogue_completed
1693 && !reg_overlap_mentioned_p (operands[0], operands[1])
1694 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)"
1697 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1],
1698 operands[2], operands[0], NULL_RTX);
1701 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder.
1702 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,multiple")]
1706 [(set (match_operand:DI 0 "register_operand")
1709 (match_operand:SI 1 "register_operand")
1710 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))]
1711 "epilogue_completed"
1712 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3)))
1713 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))]
1715 HOST_WIDE_INT i = INTVAL (operands[2]);
1716 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
1717 operands[3] = GEN_INT (i - s);
1718 operands[4] = GEN_INT (s);
1719 operands[5] = gen_lowpart (SImode, operands[0]);
1723 (define_expand "addti3"
1724 [(set (match_operand:TI 0 "register_operand" "")
1725 (plus:TI (match_operand:TI 1 "register_operand" "")
1726 (match_operand:TI 2 "register_operand" "")))]
1729 rtx low = gen_reg_rtx (DImode);
1730 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]),
1731 gen_lowpart (DImode, operands[2])));
1733 rtx high = gen_reg_rtx (DImode);
1734 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]),
1735 gen_highpart (DImode, operands[2])));
1737 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1738 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1742 (define_insn "add<mode>3_compare0"
1743 [(set (reg:CC_NZ CC_REGNUM)
1745 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r")
1746 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J"))
1748 (set (match_operand:GPI 0 "register_operand" "=r,r,r")
1749 (plus:GPI (match_dup 1) (match_dup 2)))]
1752 adds\\t%<w>0, %<w>1, %<w>2
1753 adds\\t%<w>0, %<w>1, %2
1754 subs\\t%<w>0, %<w>1, #%n2"
1755 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1758 ;; zero_extend version of above
1759 (define_insn "*addsi3_compare0_uxtw"
1760 [(set (reg:CC_NZ CC_REGNUM)
1762 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r")
1763 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J"))
1765 (set (match_operand:DI 0 "register_operand" "=r,r,r")
1766 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
1769 adds\\t%w0, %w1, %w2
1771 subs\\t%w0, %w1, #%n2"
1772 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
1775 (define_insn "*add<mode>3_compareC_cconly_imm"
1776 [(set (reg:CC_C CC_REGNUM)
1779 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r"))
1780 (match_operand:<DWI> 2 "const_scalar_int_operand" ""))
1784 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))]
1785 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2],
1786 <MODE>mode, operands[1])"
1790 [(set_attr "type" "alus_imm")]
1793 (define_insn "*add<mode>3_compareC_cconly"
1794 [(set (reg:CC_C CC_REGNUM)
1797 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r"))
1798 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")))
1799 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))]
1801 "cmn\\t%<w>0, %<w>1"
1802 [(set_attr "type" "alus_sreg")]
1805 (define_insn "*add<mode>3_compareC_imm"
1806 [(set (reg:CC_C CC_REGNUM)
1809 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r"))
1810 (match_operand:<DWI> 3 "const_scalar_int_operand" ""))
1814 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J")))))
1815 (set (match_operand:GPI 0 "register_operand" "=r,r")
1816 (plus:GPI (match_dup 1) (match_dup 2)))]
1817 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3],
1818 <MODE>mode, operands[2])"
1820 adds\\t%<w>0, %<w>1, %2
1821 subs\\t%<w>0, %<w>1, #%n2"
1822 [(set_attr "type" "alus_imm")]
1825 (define_insn "add<mode>3_compareC"
1826 [(set (reg:CC_C CC_REGNUM)
1829 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))
1830 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r")))
1832 (plus:GPI (match_dup 1) (match_dup 2)))))
1833 (set (match_operand:GPI 0 "register_operand" "=r")
1834 (plus:GPI (match_dup 1) (match_dup 2)))]
1836 "adds\\t%<w>0, %<w>1, %<w>2"
1837 [(set_attr "type" "alus_sreg")]
1840 (define_insn "*adds_shift_imm_<mode>"
1841 [(set (reg:CC_NZ CC_REGNUM)
1843 (plus:GPI (ASHIFT:GPI
1844 (match_operand:GPI 1 "register_operand" "r")
1845 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
1846 (match_operand:GPI 3 "register_operand" "r"))
1848 (set (match_operand:GPI 0 "register_operand" "=r")
1849 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))
1852 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2"
1853 [(set_attr "type" "alus_shift_imm")]
1856 (define_insn "*subs_shift_imm_<mode>"
1857 [(set (reg:CC_NZ CC_REGNUM)
1859 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1861 (match_operand:GPI 2 "register_operand" "r")
1862 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n")))
1864 (set (match_operand:GPI 0 "register_operand" "=r")
1865 (minus:GPI (match_dup 1)
1866 (ASHIFT:GPI (match_dup 2) (match_dup 3))))]
1868 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3"
1869 [(set_attr "type" "alus_shift_imm")]
1872 (define_insn "*adds_mul_imm_<mode>"
1873 [(set (reg:CC_NZ CC_REGNUM)
1876 (match_operand:GPI 1 "register_operand" "r")
1877 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
1878 (match_operand:GPI 3 "register_operand" "r"))
1880 (set (match_operand:GPI 0 "register_operand" "=r")
1881 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2))
1884 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2"
1885 [(set_attr "type" "alus_shift_imm")]
1888 (define_insn "*subs_mul_imm_<mode>"
1889 [(set (reg:CC_NZ CC_REGNUM)
1891 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1893 (match_operand:GPI 2 "register_operand" "r")
1894 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n")))
1896 (set (match_operand:GPI 0 "register_operand" "=r")
1897 (minus:GPI (match_dup 1)
1898 (mult:GPI (match_dup 2) (match_dup 3))))]
1900 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3"
1901 [(set_attr "type" "alus_shift_imm")]
1904 (define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>"
1905 [(set (reg:CC_NZ CC_REGNUM)
1908 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
1909 (match_operand:GPI 2 "register_operand" "r"))
1911 (set (match_operand:GPI 0 "register_operand" "=r")
1912 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))]
1914 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
1915 [(set_attr "type" "alus_ext")]
1918 (define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>"
1919 [(set (reg:CC_NZ CC_REGNUM)
1921 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1923 (match_operand:ALLX 2 "register_operand" "r")))
1925 (set (match_operand:GPI 0 "register_operand" "=r")
1926 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))]
1928 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
1929 [(set_attr "type" "alus_ext")]
1932 (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>"
1933 [(set (reg:CC_NZ CC_REGNUM)
1935 (plus:GPI (ashift:GPI
1937 (match_operand:ALLX 1 "register_operand" "r"))
1938 (match_operand 2 "aarch64_imm3" "Ui3"))
1939 (match_operand:GPI 3 "register_operand" "r"))
1941 (set (match_operand:GPI 0 "register_operand" "=rk")
1942 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1))
1946 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
1947 [(set_attr "type" "alus_ext")]
1950 (define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>"
1951 [(set (reg:CC_NZ CC_REGNUM)
1953 (minus:GPI (match_operand:GPI 1 "register_operand" "r")
1956 (match_operand:ALLX 2 "register_operand" "r"))
1957 (match_operand 3 "aarch64_imm3" "Ui3")))
1959 (set (match_operand:GPI 0 "register_operand" "=rk")
1960 (minus:GPI (match_dup 1)
1961 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2))
1964 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
1965 [(set_attr "type" "alus_ext")]
1968 (define_insn "*adds_<optab><mode>_multp2"
1969 [(set (reg:CC_NZ CC_REGNUM)
1971 (plus:GPI (ANY_EXTRACT:GPI
1972 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1973 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1974 (match_operand 3 "const_int_operand" "n")
1976 (match_operand:GPI 4 "register_operand" "r"))
1978 (set (match_operand:GPI 0 "register_operand" "=r")
1979 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2))
1983 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
1984 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
1985 [(set_attr "type" "alus_ext")]
1988 (define_insn "*subs_<optab><mode>_multp2"
1989 [(set (reg:CC_NZ CC_REGNUM)
1991 (minus:GPI (match_operand:GPI 4 "register_operand" "r")
1993 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
1994 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
1995 (match_operand 3 "const_int_operand" "n")
1998 (set (match_operand:GPI 0 "register_operand" "=r")
1999 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI
2000 (mult:GPI (match_dup 1) (match_dup 2))
2003 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2004 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2005 [(set_attr "type" "alus_ext")]
2008 (define_insn "*add<mode>3nr_compare0"
2009 [(set (reg:CC_NZ CC_REGNUM)
2011 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r")
2012 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J"))
2019 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
2022 (define_insn "aarch64_sub<mode>_compare0"
2023 [(set (reg:CC_NZ CC_REGNUM)
2025 (minus:GPI (match_operand:GPI 0 "register_operand" "r")
2026 (match_operand:GPI 1 "aarch64_plus_operand" "r"))
2029 "cmp\\t%<w>0, %<w>1"
2030 [(set_attr "type" "alus_sreg")]
2033 (define_insn "*compare_neg<mode>"
2034 [(set (reg:CC_Z CC_REGNUM)
2036 (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
2037 (match_operand:GPI 1 "register_operand" "r")))]
2039 "cmn\\t%<w>1, %<w>0"
2040 [(set_attr "type" "alus_sreg")]
2043 (define_insn "*add_<shift>_<mode>"
2044 [(set (match_operand:GPI 0 "register_operand" "=r")
2045 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
2046 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
2047 (match_operand:GPI 3 "register_operand" "r")))]
2049 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2050 [(set_attr "type" "alu_shift_imm")]
2053 ;; zero_extend version of above
2054 (define_insn "*add_<shift>_si_uxtw"
2055 [(set (match_operand:DI 0 "register_operand" "=r")
2057 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r")
2058 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
2059 (match_operand:SI 3 "register_operand" "r"))))]
2061 "add\\t%w0, %w3, %w1, <shift> %2"
2062 [(set_attr "type" "alu_shift_imm")]
2065 (define_insn "*add_mul_imm_<mode>"
2066 [(set (match_operand:GPI 0 "register_operand" "=r")
2067 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2068 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))
2069 (match_operand:GPI 3 "register_operand" "r")))]
2071 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2072 [(set_attr "type" "alu_shift_imm")]
2075 (define_insn "*add_<optab><ALLX:mode>_<GPI:mode>"
2076 [(set (match_operand:GPI 0 "register_operand" "=rk")
2077 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r"))
2078 (match_operand:GPI 2 "register_operand" "r")))]
2080 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>"
2081 [(set_attr "type" "alu_ext")]
2084 ;; zero_extend version of above
2085 (define_insn "*add_<optab><SHORT:mode>_si_uxtw"
2086 [(set (match_operand:DI 0 "register_operand" "=rk")
2088 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r"))
2089 (match_operand:GPI 2 "register_operand" "r"))))]
2091 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>"
2092 [(set_attr "type" "alu_ext")]
2095 (define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>"
2096 [(set (match_operand:GPI 0 "register_operand" "=rk")
2097 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI
2098 (match_operand:ALLX 1 "register_operand" "r"))
2099 (match_operand 2 "aarch64_imm3" "Ui3"))
2100 (match_operand:GPI 3 "register_operand" "r")))]
2102 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2"
2103 [(set_attr "type" "alu_ext")]
2106 ;; zero_extend version of above
2107 (define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw"
2108 [(set (match_operand:DI 0 "register_operand" "=rk")
2110 (plus:SI (ashift:SI (ANY_EXTEND:SI
2111 (match_operand:SHORT 1 "register_operand" "r"))
2112 (match_operand 2 "aarch64_imm3" "Ui3"))
2113 (match_operand:SI 3 "register_operand" "r"))))]
2115 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2"
2116 [(set_attr "type" "alu_ext")]
2119 (define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>"
2120 [(set (match_operand:GPI 0 "register_operand" "=rk")
2121 (plus:GPI (mult:GPI (ANY_EXTEND:GPI
2122 (match_operand:ALLX 1 "register_operand" "r"))
2123 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2124 (match_operand:GPI 3 "register_operand" "r")))]
2126 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2"
2127 [(set_attr "type" "alu_ext")]
2130 ;; zero_extend version of above
2131 (define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw"
2132 [(set (match_operand:DI 0 "register_operand" "=rk")
2133 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI
2134 (match_operand:SHORT 1 "register_operand" "r"))
2135 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2136 (match_operand:SI 3 "register_operand" "r"))))]
2138 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2"
2139 [(set_attr "type" "alu_ext")]
2142 (define_insn "*add_<optab><mode>_multp2"
2143 [(set (match_operand:GPI 0 "register_operand" "=rk")
2144 (plus:GPI (ANY_EXTRACT:GPI
2145 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2146 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2147 (match_operand 3 "const_int_operand" "n")
2149 (match_operand:GPI 4 "register_operand" "r")))]
2150 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2151 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2152 [(set_attr "type" "alu_ext")]
2155 ;; zero_extend version of above
2156 (define_insn "*add_<optab>si_multp2_uxtw"
2157 [(set (match_operand:DI 0 "register_operand" "=rk")
2159 (plus:SI (ANY_EXTRACT:SI
2160 (mult:SI (match_operand:SI 1 "register_operand" "r")
2161 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2162 (match_operand 3 "const_int_operand" "n")
2164 (match_operand:SI 4 "register_operand" "r"))))]
2165 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2166 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2167 [(set_attr "type" "alu_ext")]
2170 (define_expand "add<mode>3_carryin"
2171 [(set (match_operand:GPI 0 "register_operand")
2174 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0))
2175 (match_operand:GPI 1 "aarch64_reg_or_zero"))
2176 (match_operand:GPI 2 "aarch64_reg_or_zero")))]
2181 ;; Note that add with carry with two zero inputs is matched by cset,
2182 ;; and that add with carry with one zero input is matched by cinc.
2184 (define_insn "*add<mode>3_carryin"
2185 [(set (match_operand:GPI 0 "register_operand" "=r")
2188 (match_operand:GPI 3 "aarch64_carry_operation" "")
2189 (match_operand:GPI 1 "register_operand" "r"))
2190 (match_operand:GPI 2 "register_operand" "r")))]
2192 "adc\\t%<w>0, %<w>1, %<w>2"
2193 [(set_attr "type" "adc_reg")]
2196 ;; zero_extend version of above
2197 (define_insn "*addsi3_carryin_uxtw"
2198 [(set (match_operand:DI 0 "register_operand" "=r")
2202 (match_operand:SI 3 "aarch64_carry_operation" "")
2203 (match_operand:SI 1 "register_operand" "r"))
2204 (match_operand:SI 2 "register_operand" "r"))))]
2206 "adc\\t%w0, %w1, %w2"
2207 [(set_attr "type" "adc_reg")]
2210 (define_insn "*add_uxt<mode>_shift2"
2211 [(set (match_operand:GPI 0 "register_operand" "=rk")
2213 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2214 (match_operand 2 "aarch64_imm3" "Ui3"))
2215 (match_operand 3 "const_int_operand" "n"))
2216 (match_operand:GPI 4 "register_operand" "r")))]
2217 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2219 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]),
2220 INTVAL (operands[3])));
2221 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2222 [(set_attr "type" "alu_ext")]
2225 ;; zero_extend version of above
2226 (define_insn "*add_uxtsi_shift2_uxtw"
2227 [(set (match_operand:DI 0 "register_operand" "=rk")
2230 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2231 (match_operand 2 "aarch64_imm3" "Ui3"))
2232 (match_operand 3 "const_int_operand" "n"))
2233 (match_operand:SI 4 "register_operand" "r"))))]
2234 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0"
2236 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2237 INTVAL (operands[3])));
2238 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";"
2239 [(set_attr "type" "alu_ext")]
2242 (define_insn "*add_uxt<mode>_multp2"
2243 [(set (match_operand:GPI 0 "register_operand" "=rk")
2245 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2246 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2247 (match_operand 3 "const_int_operand" "n"))
2248 (match_operand:GPI 4 "register_operand" "r")))]
2249 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2251 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2252 INTVAL (operands[3])));
2253 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2254 [(set_attr "type" "alu_ext")]
2257 ;; zero_extend version of above
2258 (define_insn "*add_uxtsi_multp2_uxtw"
2259 [(set (match_operand:DI 0 "register_operand" "=rk")
2262 (mult:SI (match_operand:SI 1 "register_operand" "r")
2263 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2264 (match_operand 3 "const_int_operand" "n"))
2265 (match_operand:SI 4 "register_operand" "r"))))]
2266 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0"
2268 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2269 INTVAL (operands[3])));
2270 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";"
2271 [(set_attr "type" "alu_ext")]
2274 (define_insn "subsi3"
2275 [(set (match_operand:SI 0 "register_operand" "=rk")
2276 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2277 (match_operand:SI 2 "register_operand" "r")))]
2279 "sub\\t%w0, %w1, %w2"
2280 [(set_attr "type" "alu_sreg")]
2283 ;; zero_extend version of above
2284 (define_insn "*subsi3_uxtw"
2285 [(set (match_operand:DI 0 "register_operand" "=rk")
2287 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2288 (match_operand:SI 2 "register_operand" "r"))))]
2290 "sub\\t%w0, %w1, %w2"
2291 [(set_attr "type" "alu_sreg")]
2294 (define_insn "subdi3"
2295 [(set (match_operand:DI 0 "register_operand" "=rk,w")
2296 (minus:DI (match_operand:DI 1 "register_operand" "rk,w")
2297 (match_operand:DI 2 "register_operand" "r,w")))]
2301 sub\\t%d0, %d1, %d2"
2302 [(set_attr "type" "alu_sreg, neon_sub")
2303 (set_attr "simd" "*,yes")]
2306 (define_expand "subti3"
2307 [(set (match_operand:TI 0 "register_operand" "")
2308 (minus:TI (match_operand:TI 1 "register_operand" "")
2309 (match_operand:TI 2 "register_operand" "")))]
2312 rtx low = gen_reg_rtx (DImode);
2313 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]),
2314 gen_lowpart (DImode, operands[2])));
2316 rtx high = gen_reg_rtx (DImode);
2317 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]),
2318 gen_highpart (DImode, operands[2])));
2320 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
2321 emit_move_insn (gen_highpart (DImode, operands[0]), high);
2325 (define_insn "*sub<mode>3_compare0"
2326 [(set (reg:CC_NZ CC_REGNUM)
2327 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r")
2328 (match_operand:GPI 2 "register_operand" "r"))
2330 (set (match_operand:GPI 0 "register_operand" "=r")
2331 (minus:GPI (match_dup 1) (match_dup 2)))]
2333 "subs\\t%<w>0, %<w>1, %<w>2"
2334 [(set_attr "type" "alus_sreg")]
2337 ;; zero_extend version of above
2338 (define_insn "*subsi3_compare0_uxtw"
2339 [(set (reg:CC_NZ CC_REGNUM)
2340 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r")
2341 (match_operand:SI 2 "register_operand" "r"))
2343 (set (match_operand:DI 0 "register_operand" "=r")
2344 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))]
2346 "subs\\t%w0, %w1, %w2"
2347 [(set_attr "type" "alus_sreg")]
2350 (define_insn "sub<mode>3_compare1"
2351 [(set (reg:CC CC_REGNUM)
2353 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2354 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))
2355 (set (match_operand:GPI 0 "register_operand" "=r")
2356 (minus:GPI (match_dup 1) (match_dup 2)))]
2358 "subs\\t%<w>0, %<w>1, %<w>2"
2359 [(set_attr "type" "alus_sreg")]
2362 (define_insn "sub<mode>3_compare1_imm"
2363 [(set (reg:CC CC_REGNUM)
2365 (match_operand:GPI 1 "register_operand" "r")
2366 (match_operand:GPI 3 "const_int_operand" "n")))
2367 (set (match_operand:GPI 0 "register_operand" "=r")
2368 (plus:GPI (match_dup 1)
2369 (match_operand:GPI 2 "aarch64_sub_immediate" "J")))]
2370 "INTVAL (operands[3]) == -INTVAL (operands[2])"
2371 "subs\\t%<w>0, %<w>1, #%n2"
2372 [(set_attr "type" "alus_sreg")]
2376 [(set (match_operand:GPI 0 "register_operand")
2377 (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
2378 (match_operand:GPI 2 "aarch64_reg_or_zero")))
2379 (set (reg:CC CC_REGNUM)
2383 "!reg_overlap_mentioned_p (operands[0], operands[1])
2384 && !reg_overlap_mentioned_p (operands[0], operands[2])"
2387 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
2393 ;; Same as the above peephole but with the compare and minus in
2394 ;; swapped order. The restriction on overlap between operand 0
2395 ;; and operands 1 and 2 doesn't apply here.
2397 [(set (reg:CC CC_REGNUM)
2399 (match_operand:GPI 1 "aarch64_reg_or_zero")
2400 (match_operand:GPI 2 "aarch64_reg_or_zero")))
2401 (set (match_operand:GPI 0 "register_operand")
2402 (minus:GPI (match_dup 1)
2407 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1],
2414 [(set (match_operand:GPI 0 "register_operand")
2415 (plus:GPI (match_operand:GPI 1 "register_operand")
2416 (match_operand:GPI 2 "aarch64_sub_immediate")))
2417 (set (reg:CC CC_REGNUM)
2420 (match_operand:GPI 3 "const_int_operand")))]
2421 "!reg_overlap_mentioned_p (operands[0], operands[1])
2422 && INTVAL (operands[3]) == -INTVAL (operands[2])"
2425 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
2426 operands[2], operands[3]));
2431 ;; Same as the above peephole but with the compare and minus in
2432 ;; swapped order. The restriction on overlap between operand 0
2433 ;; and operands 1 doesn't apply here.
2435 [(set (reg:CC CC_REGNUM)
2437 (match_operand:GPI 1 "register_operand")
2438 (match_operand:GPI 3 "const_int_operand")))
2439 (set (match_operand:GPI 0 "register_operand")
2440 (plus:GPI (match_dup 1)
2441 (match_operand:GPI 2 "aarch64_sub_immediate")))]
2442 "INTVAL (operands[3]) == -INTVAL (operands[2])"
2445 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1],
2446 operands[2], operands[3]));
2451 (define_insn "*sub_<shift>_<mode>"
2452 [(set (match_operand:GPI 0 "register_operand" "=r")
2453 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2455 (match_operand:GPI 1 "register_operand" "r")
2456 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2458 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2"
2459 [(set_attr "type" "alu_shift_imm")]
2462 ;; zero_extend version of above
2463 (define_insn "*sub_<shift>_si_uxtw"
2464 [(set (match_operand:DI 0 "register_operand" "=r")
2466 (minus:SI (match_operand:SI 3 "register_operand" "r")
2468 (match_operand:SI 1 "register_operand" "r")
2469 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2471 "sub\\t%w0, %w3, %w1, <shift> %2"
2472 [(set_attr "type" "alu_shift_imm")]
2475 (define_insn "*sub_mul_imm_<mode>"
2476 [(set (match_operand:GPI 0 "register_operand" "=r")
2477 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2479 (match_operand:GPI 1 "register_operand" "r")
2480 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2482 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2"
2483 [(set_attr "type" "alu_shift_imm")]
2486 ;; zero_extend version of above
2487 (define_insn "*sub_mul_imm_si_uxtw"
2488 [(set (match_operand:DI 0 "register_operand" "=r")
2490 (minus:SI (match_operand:SI 3 "register_operand" "r")
2492 (match_operand:SI 1 "register_operand" "r")
2493 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2495 "sub\\t%w0, %w3, %w1, lsl %p2"
2496 [(set_attr "type" "alu_shift_imm")]
2499 (define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>"
2500 [(set (match_operand:GPI 0 "register_operand" "=rk")
2501 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2503 (match_operand:ALLX 2 "register_operand" "r"))))]
2505 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>"
2506 [(set_attr "type" "alu_ext")]
2509 ;; zero_extend version of above
2510 (define_insn "*sub_<optab><SHORT:mode>_si_uxtw"
2511 [(set (match_operand:DI 0 "register_operand" "=rk")
2513 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2515 (match_operand:SHORT 2 "register_operand" "r")))))]
2517 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>"
2518 [(set_attr "type" "alu_ext")]
2521 (define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>"
2522 [(set (match_operand:GPI 0 "register_operand" "=rk")
2523 (minus:GPI (match_operand:GPI 1 "register_operand" "rk")
2524 (ashift:GPI (ANY_EXTEND:GPI
2525 (match_operand:ALLX 2 "register_operand" "r"))
2526 (match_operand 3 "aarch64_imm3" "Ui3"))))]
2528 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3"
2529 [(set_attr "type" "alu_ext")]
2532 ;; zero_extend version of above
2533 (define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw"
2534 [(set (match_operand:DI 0 "register_operand" "=rk")
2536 (minus:SI (match_operand:SI 1 "register_operand" "rk")
2537 (ashift:SI (ANY_EXTEND:SI
2538 (match_operand:SHORT 2 "register_operand" "r"))
2539 (match_operand 3 "aarch64_imm3" "Ui3")))))]
2541 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3"
2542 [(set_attr "type" "alu_ext")]
2545 (define_insn "*sub_<optab><mode>_multp2"
2546 [(set (match_operand:GPI 0 "register_operand" "=rk")
2547 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2549 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2550 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2551 (match_operand 3 "const_int_operand" "n")
2553 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])"
2554 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2"
2555 [(set_attr "type" "alu_ext")]
2558 ;; zero_extend version of above
2559 (define_insn "*sub_<optab>si_multp2_uxtw"
2560 [(set (match_operand:DI 0 "register_operand" "=rk")
2562 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2564 (mult:SI (match_operand:SI 1 "register_operand" "r")
2565 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2566 (match_operand 3 "const_int_operand" "n")
2568 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])"
2569 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2"
2570 [(set_attr "type" "alu_ext")]
2573 ;; The hardware description is op1 + ~op2 + C.
2574 ;; = op1 + (-op2 + 1) + (1 - !C)
2575 ;; = op1 - op2 - 1 + 1 - !C
2576 ;; = op1 - op2 - !C.
2577 ;; We describe the latter.
2579 (define_insn "*sub<mode>3_carryin0"
2580 [(set (match_operand:GPI 0 "register_operand" "=r")
2582 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2583 (match_operand:GPI 2 "aarch64_borrow_operation" "")))]
2585 "sbc\\t%<w>0, %<w>1, <w>zr"
2586 [(set_attr "type" "adc_reg")]
2589 ;; zero_extend version of the above
2590 (define_insn "*subsi3_carryin_uxtw"
2591 [(set (match_operand:DI 0 "register_operand" "=r")
2594 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2595 (match_operand:SI 2 "aarch64_borrow_operation" ""))))]
2597 "sbc\\t%w0, %w1, wzr"
2598 [(set_attr "type" "adc_reg")]
2601 (define_expand "sub<mode>3_carryin"
2602 [(set (match_operand:GPI 0 "register_operand")
2605 (match_operand:GPI 1 "aarch64_reg_or_zero")
2606 (match_operand:GPI 2 "register_operand"))
2607 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))]
2612 (define_insn "*sub<mode>3_carryin"
2613 [(set (match_operand:GPI 0 "register_operand" "=r")
2616 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2617 (match_operand:GPI 2 "register_operand" "r"))
2618 (match_operand:GPI 3 "aarch64_borrow_operation" "")))]
2621 "sbc\\t%<w>0, %<w>1, %<w>2"
2622 [(set_attr "type" "adc_reg")]
2625 ;; zero_extend version of the above
2626 (define_insn "*subsi3_carryin_uxtw"
2627 [(set (match_operand:DI 0 "register_operand" "=r")
2631 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2632 (match_operand:SI 2 "register_operand" "r"))
2633 (match_operand:SI 3 "aarch64_borrow_operation" ""))))]
2636 "sbc\\t%w0, %w1, %w2"
2637 [(set_attr "type" "adc_reg")]
2640 (define_insn "*sub<mode>3_carryin_alt"
2641 [(set (match_operand:GPI 0 "register_operand" "=r")
2644 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
2645 (match_operand:GPI 3 "aarch64_borrow_operation" ""))
2646 (match_operand:GPI 2 "register_operand" "r")))]
2648 "sbc\\t%<w>0, %<w>1, %<w>2"
2649 [(set_attr "type" "adc_reg")]
2652 ;; zero_extend version of the above
2653 (define_insn "*subsi3_carryin_alt_uxtw"
2654 [(set (match_operand:DI 0 "register_operand" "=r")
2658 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ")
2659 (match_operand:SI 3 "aarch64_borrow_operation" ""))
2660 (match_operand:SI 2 "register_operand" "r"))))]
2662 "sbc\\t%w0, %w1, %w2"
2663 [(set_attr "type" "adc_reg")]
2666 (define_insn "*sub_uxt<mode>_shift2"
2667 [(set (match_operand:GPI 0 "register_operand" "=rk")
2668 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2670 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
2671 (match_operand 2 "aarch64_imm3" "Ui3"))
2672 (match_operand 3 "const_int_operand" "n"))))]
2673 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2675 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2676 INTVAL (operands[3])));
2677 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";"
2678 [(set_attr "type" "alu_ext")]
2681 ;; zero_extend version of above
2682 (define_insn "*sub_uxtsi_shift2_uxtw"
2683 [(set (match_operand:DI 0 "register_operand" "=rk")
2685 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2687 (ashift:SI (match_operand:SI 1 "register_operand" "r")
2688 (match_operand 2 "aarch64_imm3" "Ui3"))
2689 (match_operand 3 "const_int_operand" "n")))))]
2690 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0"
2692 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]),
2693 INTVAL (operands[3])));
2694 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";"
2695 [(set_attr "type" "alu_ext")]
2698 (define_insn "*sub_uxt<mode>_multp2"
2699 [(set (match_operand:GPI 0 "register_operand" "=rk")
2700 (minus:GPI (match_operand:GPI 4 "register_operand" "rk")
2702 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2703 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2704 (match_operand 3 "const_int_operand" "n"))))]
2705 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2707 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2708 INTVAL (operands[3])));
2709 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";"
2710 [(set_attr "type" "alu_ext")]
2713 ;; zero_extend version of above
2714 (define_insn "*sub_uxtsi_multp2_uxtw"
2715 [(set (match_operand:DI 0 "register_operand" "=rk")
2717 (minus:SI (match_operand:SI 4 "register_operand" "rk")
2719 (mult:SI (match_operand:SI 1 "register_operand" "r")
2720 (match_operand 2 "aarch64_pwr_imm3" "Up3"))
2721 (match_operand 3 "const_int_operand" "n")))))]
2722 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0"
2724 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),
2725 INTVAL (operands[3])));
2726 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";"
2727 [(set_attr "type" "alu_ext")]
2730 (define_expand "abs<mode>2"
2731 [(match_operand:GPI 0 "register_operand" "")
2732 (match_operand:GPI 1 "register_operand" "")]
2735 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
2736 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx);
2737 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1]));
2742 (define_insn "neg<mode>2"
2743 [(set (match_operand:GPI 0 "register_operand" "=r,w")
2744 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
2748 neg\\t%<rtn>0<vas>, %<rtn>1<vas>"
2749 [(set_attr "type" "alu_sreg, neon_neg<q>")
2750 (set_attr "simd" "*,yes")]
2753 ;; zero_extend version of above
2754 (define_insn "*negsi2_uxtw"
2755 [(set (match_operand:DI 0 "register_operand" "=r")
2756 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))]
2759 [(set_attr "type" "alu_sreg")]
2762 (define_insn "*ngc<mode>"
2763 [(set (match_operand:GPI 0 "register_operand" "=r")
2765 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" ""))
2766 (match_operand:GPI 1 "register_operand" "r")))]
2768 "ngc\\t%<w>0, %<w>1"
2769 [(set_attr "type" "adc_reg")]
2772 (define_insn "*ngcsi_uxtw"
2773 [(set (match_operand:DI 0 "register_operand" "=r")
2776 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" ""))
2777 (match_operand:SI 1 "register_operand" "r"))))]
2780 [(set_attr "type" "adc_reg")]
2783 (define_insn "neg<mode>2_compare0"
2784 [(set (reg:CC_NZ CC_REGNUM)
2785 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2787 (set (match_operand:GPI 0 "register_operand" "=r")
2788 (neg:GPI (match_dup 1)))]
2790 "negs\\t%<w>0, %<w>1"
2791 [(set_attr "type" "alus_sreg")]
2794 ;; zero_extend version of above
2795 (define_insn "*negsi2_compare0_uxtw"
2796 [(set (reg:CC_NZ CC_REGNUM)
2797 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r"))
2799 (set (match_operand:DI 0 "register_operand" "=r")
2800 (zero_extend:DI (neg:SI (match_dup 1))))]
2803 [(set_attr "type" "alus_sreg")]
2806 (define_insn "*neg_<shift><mode>3_compare0"
2807 [(set (reg:CC_NZ CC_REGNUM)
2809 (neg:GPI (ASHIFT:GPI
2810 (match_operand:GPI 1 "register_operand" "r")
2811 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
2813 (set (match_operand:GPI 0 "register_operand" "=r")
2814 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))]
2816 "negs\\t%<w>0, %<w>1, <shift> %2"
2817 [(set_attr "type" "alus_shift_imm")]
2820 (define_insn "*neg_<shift>_<mode>2"
2821 [(set (match_operand:GPI 0 "register_operand" "=r")
2822 (neg:GPI (ASHIFT:GPI
2823 (match_operand:GPI 1 "register_operand" "r")
2824 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
2826 "neg\\t%<w>0, %<w>1, <shift> %2"
2827 [(set_attr "type" "alu_shift_imm")]
2830 ;; zero_extend version of above
2831 (define_insn "*neg_<shift>_si2_uxtw"
2832 [(set (match_operand:DI 0 "register_operand" "=r")
2835 (match_operand:SI 1 "register_operand" "r")
2836 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))]
2838 "neg\\t%w0, %w1, <shift> %2"
2839 [(set_attr "type" "alu_shift_imm")]
2842 (define_insn "*neg_mul_imm_<mode>2"
2843 [(set (match_operand:GPI 0 "register_operand" "=r")
2845 (match_operand:GPI 1 "register_operand" "r")
2846 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))]
2848 "neg\\t%<w>0, %<w>1, lsl %p2"
2849 [(set_attr "type" "alu_shift_imm")]
2852 ;; zero_extend version of above
2853 (define_insn "*neg_mul_imm_si2_uxtw"
2854 [(set (match_operand:DI 0 "register_operand" "=r")
2857 (match_operand:SI 1 "register_operand" "r")
2858 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))]
2860 "neg\\t%w0, %w1, lsl %p2"
2861 [(set_attr "type" "alu_shift_imm")]
2864 (define_insn "mul<mode>3"
2865 [(set (match_operand:GPI 0 "register_operand" "=r")
2866 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2867 (match_operand:GPI 2 "register_operand" "r")))]
2869 "mul\\t%<w>0, %<w>1, %<w>2"
2870 [(set_attr "type" "mul")]
2873 ;; zero_extend version of above
2874 (define_insn "*mulsi3_uxtw"
2875 [(set (match_operand:DI 0 "register_operand" "=r")
2877 (mult:SI (match_operand:SI 1 "register_operand" "r")
2878 (match_operand:SI 2 "register_operand" "r"))))]
2880 "mul\\t%w0, %w1, %w2"
2881 [(set_attr "type" "mul")]
2884 (define_insn "madd<mode>"
2885 [(set (match_operand:GPI 0 "register_operand" "=r")
2886 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2887 (match_operand:GPI 2 "register_operand" "r"))
2888 (match_operand:GPI 3 "register_operand" "r")))]
2890 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3"
2891 [(set_attr "type" "mla")]
2894 ;; zero_extend version of above
2895 (define_insn "*maddsi_uxtw"
2896 [(set (match_operand:DI 0 "register_operand" "=r")
2898 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
2899 (match_operand:SI 2 "register_operand" "r"))
2900 (match_operand:SI 3 "register_operand" "r"))))]
2902 "madd\\t%w0, %w1, %w2, %w3"
2903 [(set_attr "type" "mla")]
2906 (define_insn "*msub<mode>"
2907 [(set (match_operand:GPI 0 "register_operand" "=r")
2908 (minus:GPI (match_operand:GPI 3 "register_operand" "r")
2909 (mult:GPI (match_operand:GPI 1 "register_operand" "r")
2910 (match_operand:GPI 2 "register_operand" "r"))))]
2913 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3"
2914 [(set_attr "type" "mla")]
2917 ;; zero_extend version of above
2918 (define_insn "*msubsi_uxtw"
2919 [(set (match_operand:DI 0 "register_operand" "=r")
2921 (minus:SI (match_operand:SI 3 "register_operand" "r")
2922 (mult:SI (match_operand:SI 1 "register_operand" "r")
2923 (match_operand:SI 2 "register_operand" "r")))))]
2926 "msub\\t%w0, %w1, %w2, %w3"
2927 [(set_attr "type" "mla")]
2930 (define_insn "*mul<mode>_neg"
2931 [(set (match_operand:GPI 0 "register_operand" "=r")
2932 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r"))
2933 (match_operand:GPI 2 "register_operand" "r")))]
2936 "mneg\\t%<w>0, %<w>1, %<w>2"
2937 [(set_attr "type" "mul")]
2940 ;; zero_extend version of above
2941 (define_insn "*mulsi_neg_uxtw"
2942 [(set (match_operand:DI 0 "register_operand" "=r")
2944 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r"))
2945 (match_operand:SI 2 "register_operand" "r"))))]
2948 "mneg\\t%w0, %w1, %w2"
2949 [(set_attr "type" "mul")]
2952 (define_insn "<su_optab>mulsidi3"
2953 [(set (match_operand:DI 0 "register_operand" "=r")
2954 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2955 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2957 "<su>mull\\t%0, %w1, %w2"
2958 [(set_attr "type" "<su>mull")]
2961 (define_insn "<su_optab>maddsidi4"
2962 [(set (match_operand:DI 0 "register_operand" "=r")
2964 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2965 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
2966 (match_operand:DI 3 "register_operand" "r")))]
2968 "<su>maddl\\t%0, %w1, %w2, %3"
2969 [(set_attr "type" "<su>mlal")]
2972 (define_insn "<su_optab>msubsidi4"
2973 [(set (match_operand:DI 0 "register_operand" "=r")
2975 (match_operand:DI 3 "register_operand" "r")
2976 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
2978 (match_operand:SI 2 "register_operand" "r")))))]
2980 "<su>msubl\\t%0, %w1, %w2, %3"
2981 [(set_attr "type" "<su>mlal")]
2984 (define_insn "*<su_optab>mulsidi_neg"
2985 [(set (match_operand:DI 0 "register_operand" "=r")
2987 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")))
2988 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))]
2990 "<su>mnegl\\t%0, %w1, %w2"
2991 [(set_attr "type" "<su>mull")]
2994 (define_expand "<su_optab>mulditi3"
2995 [(set (match_operand:TI 0 "register_operand")
2996 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand"))
2997 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))]
3000 rtx low = gen_reg_rtx (DImode);
3001 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
3003 rtx high = gen_reg_rtx (DImode);
3004 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
3006 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
3007 emit_move_insn (gen_highpart (DImode, operands[0]), high);
3011 ;; The default expansion of multi3 using umuldi3_highpart will perform
3012 ;; the additions in an order that fails to combine into two madd insns.
3013 (define_expand "multi3"
3014 [(set (match_operand:TI 0 "register_operand")
3015 (mult:TI (match_operand:TI 1 "register_operand")
3016 (match_operand:TI 2 "register_operand")))]
3019 rtx l0 = gen_reg_rtx (DImode);
3020 rtx l1 = gen_lowpart (DImode, operands[1]);
3021 rtx l2 = gen_lowpart (DImode, operands[2]);
3022 rtx h0 = gen_reg_rtx (DImode);
3023 rtx h1 = gen_highpart (DImode, operands[1]);
3024 rtx h2 = gen_highpart (DImode, operands[2]);
3026 emit_insn (gen_muldi3 (l0, l1, l2));
3027 emit_insn (gen_umuldi3_highpart (h0, l1, l2));
3028 emit_insn (gen_madddi (h0, h1, l2, h0));
3029 emit_insn (gen_madddi (h0, l1, h2, h0));
3031 emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
3032 emit_move_insn (gen_highpart (DImode, operands[0]), h0);
3036 (define_insn "<su>muldi3_highpart"
3037 [(set (match_operand:DI 0 "register_operand" "=r")
3041 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r"))
3042 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r")))
3045 "<su>mulh\\t%0, %1, %2"
3046 [(set_attr "type" "<su>mull")]
3049 (define_insn "<su_optab>div<mode>3"
3050 [(set (match_operand:GPI 0 "register_operand" "=r")
3051 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r")
3052 (match_operand:GPI 2 "register_operand" "r")))]
3054 "<su>div\\t%<w>0, %<w>1, %<w>2"
3055 [(set_attr "type" "<su>div")]
3058 ;; zero_extend version of above
3059 (define_insn "*<su_optab>divsi3_uxtw"
3060 [(set (match_operand:DI 0 "register_operand" "=r")
3062 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r")
3063 (match_operand:SI 2 "register_operand" "r"))))]
3065 "<su>div\\t%w0, %w1, %w2"
3066 [(set_attr "type" "<su>div")]
3069 ;; -------------------------------------------------------------------
3071 ;; -------------------------------------------------------------------
3073 (define_insn "cmp<mode>"
3074 [(set (reg:CC CC_REGNUM)
3075 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r")
3076 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))]
3082 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")]
3085 (define_insn "fcmp<mode>"
3086 [(set (reg:CCFP CC_REGNUM)
3087 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w")
3088 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3092 fcmp\\t%<s>0, %<s>1"
3093 [(set_attr "type" "fcmp<s>")]
3096 (define_insn "fcmpe<mode>"
3097 [(set (reg:CCFPE CC_REGNUM)
3098 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w")
3099 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))]
3103 fcmpe\\t%<s>0, %<s>1"
3104 [(set_attr "type" "fcmp<s>")]
3107 (define_insn "*cmp_swp_<shift>_reg<mode>"
3108 [(set (reg:CC_SWP CC_REGNUM)
3109 (compare:CC_SWP (ASHIFT:GPI
3110 (match_operand:GPI 0 "register_operand" "r")
3111 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
3112 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))]
3114 "cmp\\t%<w>2, %<w>0, <shift> %1"
3115 [(set_attr "type" "alus_shift_imm")]
3118 (define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>"
3119 [(set (reg:CC_SWP CC_REGNUM)
3120 (compare:CC_SWP (ANY_EXTEND:GPI
3121 (match_operand:ALLX 0 "register_operand" "r"))
3122 (match_operand:GPI 1 "register_operand" "r")))]
3124 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>"
3125 [(set_attr "type" "alus_ext")]
3128 (define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>"
3129 [(set (reg:CC_SWP CC_REGNUM)
3130 (compare:CC_SWP (ashift:GPI
3132 (match_operand:ALLX 0 "register_operand" "r"))
3133 (match_operand 1 "aarch64_imm3" "Ui3"))
3134 (match_operand:GPI 2 "register_operand" "r")))]
3136 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1"
3137 [(set_attr "type" "alus_ext")]
3140 ;; -------------------------------------------------------------------
3141 ;; Store-flag and conditional select insns
3142 ;; -------------------------------------------------------------------
3144 (define_expand "cstore<mode>4"
3145 [(set (match_operand:SI 0 "register_operand" "")
3146 (match_operator:SI 1 "aarch64_comparison_operator"
3147 [(match_operand:GPI 2 "register_operand" "")
3148 (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
3151 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3153 operands[3] = const0_rtx;
3157 (define_expand "cstorecc4"
3158 [(set (match_operand:SI 0 "register_operand")
3159 (match_operator 1 "aarch64_comparison_operator_mode"
3160 [(match_operand 2 "cc_register")
3161 (match_operand 3 "const0_operand")]))]
3164 emit_insn (gen_rtx_SET (operands[0], operands[1]));
3169 (define_expand "cstore<mode>4"
3170 [(set (match_operand:SI 0 "register_operand" "")
3171 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3172 [(match_operand:GPF 2 "register_operand" "")
3173 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
3176 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3178 operands[3] = const0_rtx;
3182 (define_insn "aarch64_cstore<mode>"
3183 [(set (match_operand:ALLI 0 "register_operand" "=r")
3184 (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3185 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3188 [(set_attr "type" "csel")]
3191 ;; For a 24-bit immediate CST we can optimize the compare for equality
3192 ;; and branch sequence from:
3194 ;; movk x0, #imm2, lsl 16 /* x0 contains CST. */
3197 ;; into the shorter:
3198 ;; sub x0, x1, #(CST & 0xfff000)
3199 ;; subs x0, x0, #(CST & 0x000fff)
3200 ;; cset x2, <ne, eq>.
3201 (define_insn_and_split "*compare_cstore<mode>_insn"
3202 [(set (match_operand:GPI 0 "register_operand" "=r")
3203 (EQL:GPI (match_operand:GPI 1 "register_operand" "r")
3204 (match_operand:GPI 2 "aarch64_imm24" "n")))
3205 (clobber (reg:CC CC_REGNUM))]
3206 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)
3207 && !aarch64_plus_operand (operands[2], <MODE>mode)
3208 && !reload_completed"
3213 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff;
3214 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000;
3215 rtx tmp = gen_reg_rtx (<MODE>mode);
3216 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm)));
3217 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm)));
3218 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM);
3219 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx);
3220 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg));
3223 [(set_attr "type" "csel")]
3226 ;; zero_extend version of the above
3227 (define_insn "*cstoresi_insn_uxtw"
3228 [(set (match_operand:DI 0 "register_operand" "=r")
3230 (match_operator:SI 1 "aarch64_comparison_operator_mode"
3231 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3234 [(set_attr "type" "csel")]
3237 (define_insn "cstore<mode>_neg"
3238 [(set (match_operand:ALLI 0 "register_operand" "=r")
3239 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode"
3240 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3242 "csetm\\t%<w>0, %m1"
3243 [(set_attr "type" "csel")]
3246 ;; zero_extend version of the above
3247 (define_insn "*cstoresi_neg_uxtw"
3248 [(set (match_operand:DI 0 "register_operand" "=r")
3250 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode"
3251 [(match_operand 2 "cc_register" "") (const_int 0)]))))]
3254 [(set_attr "type" "csel")]
3257 (define_expand "cmov<mode>6"
3258 [(set (match_operand:GPI 0 "register_operand" "")
3260 (match_operator 1 "aarch64_comparison_operator"
3261 [(match_operand:GPI 2 "register_operand" "")
3262 (match_operand:GPI 3 "aarch64_plus_operand" "")])
3263 (match_operand:GPI 4 "register_operand" "")
3264 (match_operand:GPI 5 "register_operand" "")))]
3267 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3269 operands[3] = const0_rtx;
3273 (define_expand "cmov<mode>6"
3274 [(set (match_operand:GPF 0 "register_operand" "")
3276 (match_operator 1 "aarch64_comparison_operator"
3277 [(match_operand:GPF 2 "register_operand" "")
3278 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
3279 (match_operand:GPF 4 "register_operand" "")
3280 (match_operand:GPF 5 "register_operand" "")))]
3283 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
3285 operands[3] = const0_rtx;
3289 (define_insn "*cmov<mode>_insn"
3290 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r")
3292 (match_operator 1 "aarch64_comparison_operator"
3293 [(match_operand 2 "cc_register" "") (const_int 0)])
3294 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3295 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))]
3296 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3297 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3298 ;; Final two alternatives should be unreachable, but included for completeness
3300 csel\\t%<w>0, %<w>3, %<w>4, %m1
3301 csinv\\t%<w>0, %<w>3, <w>zr, %m1
3302 csinv\\t%<w>0, %<w>4, <w>zr, %M1
3303 csinc\\t%<w>0, %<w>3, <w>zr, %m1
3304 csinc\\t%<w>0, %<w>4, <w>zr, %M1
3307 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3310 ;; zero_extend version of above
3311 (define_insn "*cmovsi_insn_uxtw"
3312 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r")
3315 (match_operator 1 "aarch64_comparison_operator"
3316 [(match_operand 2 "cc_register" "") (const_int 0)])
3317 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1")
3318 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))]
3319 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx)
3320 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))"
3321 ;; Final two alternatives should be unreachable, but included for completeness
3323 csel\\t%w0, %w3, %w4, %m1
3324 csinv\\t%w0, %w3, wzr, %m1
3325 csinv\\t%w0, %w4, wzr, %M1
3326 csinc\\t%w0, %w3, wzr, %m1
3327 csinc\\t%w0, %w4, wzr, %M1
3330 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")]
3333 (define_insn "*cmovdi_insn_uxtw"
3334 [(set (match_operand:DI 0 "register_operand" "=r")
3336 (match_operator 1 "aarch64_comparison_operator"
3337 [(match_operand 2 "cc_register" "") (const_int 0)])
3338 (zero_extend:DI (match_operand:SI 3 "register_operand" "r"))
3339 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))]
3341 "csel\\t%w0, %w3, %w4, %m1"
3342 [(set_attr "type" "csel")]
3345 (define_insn "*cmov<mode>_insn"
3346 [(set (match_operand:GPF 0 "register_operand" "=w")
3348 (match_operator 1 "aarch64_comparison_operator"
3349 [(match_operand 2 "cc_register" "") (const_int 0)])
3350 (match_operand:GPF 3 "register_operand" "w")
3351 (match_operand:GPF 4 "register_operand" "w")))]
3353 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1"
3354 [(set_attr "type" "fcsel")]
3357 (define_expand "mov<mode>cc"
3358 [(set (match_operand:ALLI 0 "register_operand" "")
3359 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
3360 (match_operand:ALLI 2 "register_operand" "")
3361 (match_operand:ALLI 3 "register_operand" "")))]
3365 enum rtx_code code = GET_CODE (operands[1]);
3367 if (code == UNEQ || code == LTGT)
3370 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3371 XEXP (operands[1], 1));
3372 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3376 (define_expand "mov<GPF:mode><GPI:mode>cc"
3377 [(set (match_operand:GPI 0 "register_operand" "")
3378 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3379 (match_operand:GPF 2 "register_operand" "")
3380 (match_operand:GPF 3 "register_operand" "")))]
3384 enum rtx_code code = GET_CODE (operands[1]);
3386 if (code == UNEQ || code == LTGT)
3389 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3390 XEXP (operands[1], 1));
3391 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3395 (define_expand "mov<mode>cc"
3396 [(set (match_operand:GPF 0 "register_operand" "")
3397 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
3398 (match_operand:GPF 2 "register_operand" "")
3399 (match_operand:GPF 3 "register_operand" "")))]
3403 enum rtx_code code = GET_CODE (operands[1]);
3405 if (code == UNEQ || code == LTGT)
3408 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3409 XEXP (operands[1], 1));
3410 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3414 (define_expand "<neg_not_op><mode>cc"
3415 [(set (match_operand:GPI 0 "register_operand" "")
3416 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
3417 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
3418 (match_operand:GPI 3 "register_operand" "")))]
3422 enum rtx_code code = GET_CODE (operands[1]);
3424 if (code == UNEQ || code == LTGT)
3427 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
3428 XEXP (operands[1], 1));
3429 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
3433 ;; CRC32 instructions.
3434 (define_insn "aarch64_<crc_variant>"
3435 [(set (match_operand:SI 0 "register_operand" "=r")
3436 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
3437 (match_operand:<crc_mode> 2 "register_operand" "r")]
3441 if (GET_MODE_BITSIZE (<crc_mode>mode) >= 64)
3442 return "<crc_variant>\\t%w0, %w1, %x2";
3444 return "<crc_variant>\\t%w0, %w1, %w2";
3446 [(set_attr "type" "crc")]
3449 (define_insn "*csinc2<mode>_insn"
3450 [(set (match_operand:GPI 0 "register_operand" "=r")
3451 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "")
3452 (match_operand:GPI 1 "register_operand" "r")))]
3454 "cinc\\t%<w>0, %<w>1, %m2"
3455 [(set_attr "type" "csel")]
3458 (define_insn "csinc3<mode>_insn"
3459 [(set (match_operand:GPI 0 "register_operand" "=r")
3461 (match_operand 1 "aarch64_comparison_operation" "")
3462 (plus:GPI (match_operand:GPI 2 "register_operand" "r")
3464 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3466 "csinc\\t%<w>0, %<w>3, %<w>2, %M1"
3467 [(set_attr "type" "csel")]
3470 (define_insn "*csinv3<mode>_insn"
3471 [(set (match_operand:GPI 0 "register_operand" "=r")
3473 (match_operand 1 "aarch64_comparison_operation" "")
3474 (not:GPI (match_operand:GPI 2 "register_operand" "r"))
3475 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3477 "csinv\\t%<w>0, %<w>3, %<w>2, %M1"
3478 [(set_attr "type" "csel")]
3481 (define_insn "csneg3_uxtw_insn"
3482 [(set (match_operand:DI 0 "register_operand" "=r")
3485 (match_operand 1 "aarch64_comparison_operation" "")
3486 (neg:SI (match_operand:SI 2 "register_operand" "r"))
3487 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))]
3489 "csneg\\t%w0, %w3, %w2, %M1"
3490 [(set_attr "type" "csel")]
3493 (define_insn "csneg3<mode>_insn"
3494 [(set (match_operand:GPI 0 "register_operand" "=r")
3496 (match_operand 1 "aarch64_comparison_operation" "")
3497 (neg:GPI (match_operand:GPI 2 "register_operand" "r"))
3498 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))]
3500 "csneg\\t%<w>0, %<w>3, %<w>2, %M1"
3501 [(set_attr "type" "csel")]
3504 ;; If X can be loaded by a single CNT[BHWD] instruction,
3508 ;; is equivalent to:
3510 ;; TMP = UQDEC[BHWD] (B, X)
3513 ;; Defining the pattern this way means that:
3515 ;; A = UMAX (B, X) - X
3519 ;; TMP1 = UQDEC[BHWD] (B, X)
3523 ;; which combine can optimize to:
3525 ;; A = UQDEC[BHWD] (B, X)
3527 ;; We don't use match_operand predicates because the order of the operands
3528 ;; can vary: the CNT[BHWD] constant will come first if the other operand is
3529 ;; a simpler constant (such as a CONST_INT), otherwise it will come second.
3530 (define_expand "umax<mode>3"
3531 [(set (match_operand:GPI 0 "register_operand")
3532 (umax:GPI (match_operand:GPI 1 "")
3533 (match_operand:GPI 2 "")))]
3536 if (aarch64_sve_cnt_immediate (operands[1], <MODE>mode))
3537 std::swap (operands[1], operands[2]);
3538 else if (!aarch64_sve_cnt_immediate (operands[2], <MODE>mode))
3540 rtx temp = gen_reg_rtx (<MODE>mode);
3541 operands[1] = force_reg (<MODE>mode, operands[1]);
3542 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[1], operands[2]));
3543 emit_insn (gen_add<mode>3 (operands[0], temp, operands[2]));
3548 ;; Saturating unsigned subtraction of a CNT[BHWD] immediate.
3549 (define_insn "aarch64_uqdec<mode>"
3550 [(set (match_operand:GPI 0 "register_operand" "=r")
3552 (umax:GPI (match_operand:GPI 1 "register_operand" "0")
3553 (match_operand:GPI 2 "aarch64_sve_cnt_immediate" "Usv"))
3557 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>0", operands[2]);
3561 ;; -------------------------------------------------------------------
3562 ;; Logical operations
3563 ;; -------------------------------------------------------------------
3566 (define_insn_and_split "*aarch64_and<mode>_imm2"
3567 [(set (match_operand:GPI 0 "register_operand" "=rk")
3568 (and:GPI (match_operand:GPI 1 "register_operand" "%r")
3569 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))]
3575 HOST_WIDE_INT val = INTVAL (operands[2]);
3576 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val));
3577 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val));
3579 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1));
3580 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2));
3585 (define_insn "<optab><mode>3"
3586 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w")
3587 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w")
3588 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))]
3591 <logical>\\t%<w>0, %<w>1, %<w>2
3592 <logical>\\t%<w>0, %<w>1, %2
3593 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
3594 [(set_attr "type" "logic_reg,logic_imm,neon_logic")
3595 (set_attr "simd" "*,*,yes")]
3598 ;; zero_extend version of above
3599 (define_insn "*<optab>si3_uxtw"
3600 [(set (match_operand:DI 0 "register_operand" "=r,rk")
3602 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r")
3603 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))]
3606 <logical>\\t%w0, %w1, %w2
3607 <logical>\\t%w0, %w1, %2"
3608 [(set_attr "type" "logic_reg,logic_imm")]
3611 (define_insn "*and<mode>3_compare0"
3612 [(set (reg:CC_NZ CC_REGNUM)
3614 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r")
3615 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>"))
3617 (set (match_operand:GPI 0 "register_operand" "=r,r")
3618 (and:GPI (match_dup 1) (match_dup 2)))]
3621 ands\\t%<w>0, %<w>1, %<w>2
3622 ands\\t%<w>0, %<w>1, %2"
3623 [(set_attr "type" "logics_reg,logics_imm")]
3626 ;; zero_extend version of above
3627 (define_insn "*andsi3_compare0_uxtw"
3628 [(set (reg:CC_NZ CC_REGNUM)
3630 (and:SI (match_operand:SI 1 "register_operand" "%r,r")
3631 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))
3633 (set (match_operand:DI 0 "register_operand" "=r,r")
3634 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
3637 ands\\t%w0, %w1, %w2
3638 ands\\t%w0, %w1, %2"
3639 [(set_attr "type" "logics_reg,logics_imm")]
3642 (define_insn "*and_<SHIFT:optab><mode>3_compare0"
3643 [(set (reg:CC_NZ CC_REGNUM)
3646 (match_operand:GPI 1 "register_operand" "r")
3647 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3648 (match_operand:GPI 3 "register_operand" "r"))
3650 (set (match_operand:GPI 0 "register_operand" "=r")
3651 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))]
3653 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3654 [(set_attr "type" "logics_shift_imm")]
3657 ;; zero_extend version of above
3658 (define_insn "*and_<SHIFT:optab>si3_compare0_uxtw"
3659 [(set (reg:CC_NZ CC_REGNUM)
3662 (match_operand:SI 1 "register_operand" "r")
3663 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3664 (match_operand:SI 3 "register_operand" "r"))
3666 (set (match_operand:DI 0 "register_operand" "=r")
3667 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2))
3670 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3671 [(set_attr "type" "logics_shift_imm")]
3674 (define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3"
3675 [(set (match_operand:GPI 0 "register_operand" "=r")
3676 (LOGICAL:GPI (SHIFT:GPI
3677 (match_operand:GPI 1 "register_operand" "r")
3678 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3679 (match_operand:GPI 3 "register_operand" "r")))]
3681 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3682 [(set_attr "type" "logic_shift_imm")]
3685 (define_insn "*<optab>_rol<mode>3"
3686 [(set (match_operand:GPI 0 "register_operand" "=r")
3687 (LOGICAL:GPI (rotate:GPI
3688 (match_operand:GPI 1 "register_operand" "r")
3689 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3690 (match_operand:GPI 3 "register_operand" "r")))]
3692 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)"
3693 [(set_attr "type" "logic_shift_imm")]
3696 ;; zero_extend versions of above
3697 (define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw"
3698 [(set (match_operand:DI 0 "register_operand" "=r")
3700 (LOGICAL:SI (SHIFT:SI
3701 (match_operand:SI 1 "register_operand" "r")
3702 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3703 (match_operand:SI 3 "register_operand" "r"))))]
3705 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3706 [(set_attr "type" "logic_shift_imm")]
3709 (define_insn "*<optab>_rolsi3_uxtw"
3710 [(set (match_operand:DI 0 "register_operand" "=r")
3712 (LOGICAL:SI (rotate:SI
3713 (match_operand:SI 1 "register_operand" "r")
3714 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3715 (match_operand:SI 3 "register_operand" "r"))))]
3717 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)"
3718 [(set_attr "type" "logic_shift_imm")]
3721 (define_insn "one_cmpl<mode>2"
3722 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3723 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))]
3728 [(set_attr "type" "logic_reg,neon_logic")
3729 (set_attr "simd" "*,yes")]
3732 (define_insn "*one_cmpl_<optab><mode>2"
3733 [(set (match_operand:GPI 0 "register_operand" "=r")
3734 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r")
3735 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))]
3737 "mvn\\t%<w>0, %<w>1, <shift> %2"
3738 [(set_attr "type" "logic_shift_imm")]
3741 ;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b).
3743 (define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3"
3744 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3745 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w"))
3746 (match_operand:GPI 2 "register_operand" "r,w")))]
3749 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1
3750 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>"
3751 [(set_attr "type" "logic_reg,neon_logic")
3752 (set_attr "simd" "*,yes")]
3755 (define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze"
3756 [(set (match_operand:DI 0 "register_operand" "=r")
3758 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
3759 (match_operand:SI 2 "register_operand" "r"))))]
3761 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1"
3762 [(set_attr "type" "logic_reg")]
3765 (define_insn "*xor_one_cmplsidi3_ze"
3766 [(set (match_operand:DI 0 "register_operand" "=r")
3768 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r")
3769 (match_operand:SI 2 "register_operand" "r")))))]
3771 "eon\\t%w0, %w1, %w2"
3772 [(set_attr "type" "logic_reg")]
3775 ;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)).
3776 ;; eon does not operate on SIMD registers so the vector variant must be split.
3777 (define_insn_and_split "*xor_one_cmpl<mode>3"
3778 [(set (match_operand:GPI 0 "register_operand" "=r,w")
3779 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w")
3780 (match_operand:GPI 2 "register_operand" "r,w"))))]
3783 eon\\t%<w>0, %<w>1, %<w>2
3785 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers.
3786 [(set (match_operand:GPI 0 "register_operand" "=w")
3787 (xor:GPI (match_operand:GPI 1 "register_operand" "w")
3788 (match_operand:GPI 2 "register_operand" "w")))
3789 (set (match_dup 0) (not:GPI (match_dup 0)))]
3791 [(set_attr "type" "logic_reg,multiple")
3792 (set_attr "simd" "*,yes")]
3795 (define_insn "*and_one_cmpl<mode>3_compare0"
3796 [(set (reg:CC_NZ CC_REGNUM)
3799 (match_operand:GPI 1 "register_operand" "r"))
3800 (match_operand:GPI 2 "register_operand" "r"))
3802 (set (match_operand:GPI 0 "register_operand" "=r")
3803 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))]
3805 "bics\\t%<w>0, %<w>2, %<w>1"
3806 [(set_attr "type" "logics_reg")]
3809 ;; zero_extend version of above
3810 (define_insn "*and_one_cmplsi3_compare0_uxtw"
3811 [(set (reg:CC_NZ CC_REGNUM)
3814 (match_operand:SI 1 "register_operand" "r"))
3815 (match_operand:SI 2 "register_operand" "r"))
3817 (set (match_operand:DI 0 "register_operand" "=r")
3818 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))]
3820 "bics\\t%w0, %w2, %w1"
3821 [(set_attr "type" "logics_reg")]
3824 (define_insn "*and_one_cmpl<mode>3_compare0_no_reuse"
3825 [(set (reg:CC_NZ CC_REGNUM)
3828 (match_operand:GPI 0 "register_operand" "r"))
3829 (match_operand:GPI 1 "register_operand" "r"))
3832 "bics\\t<w>zr, %<w>1, %<w>0"
3833 [(set_attr "type" "logics_reg")]
3836 (define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3"
3837 [(set (match_operand:GPI 0 "register_operand" "=r")
3838 (LOGICAL:GPI (not:GPI
3840 (match_operand:GPI 1 "register_operand" "r")
3841 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3842 (match_operand:GPI 3 "register_operand" "r")))]
3844 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3845 [(set_attr "type" "logic_shift_imm")]
3848 (define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt"
3849 [(set (match_operand:GPI 0 "register_operand" "=r")
3852 (match_operand:GPI 1 "register_operand" "r")
3853 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))
3854 (match_operand:GPI 3 "register_operand" "r"))))]
3856 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3857 [(set_attr "type" "logic_shift_imm")]
3860 ;; Zero-extend version of the above.
3861 (define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze"
3862 [(set (match_operand:DI 0 "register_operand" "=r")
3866 (match_operand:SI 1 "register_operand" "r")
3867 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))
3868 (match_operand:SI 3 "register_operand" "r")))))]
3870 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3871 [(set_attr "type" "logic_shift_imm")]
3874 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0"
3875 [(set (reg:CC_NZ CC_REGNUM)
3879 (match_operand:GPI 1 "register_operand" "r")
3880 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")))
3881 (match_operand:GPI 3 "register_operand" "r"))
3883 (set (match_operand:GPI 0 "register_operand" "=r")
3886 (match_dup 1) (match_dup 2))) (match_dup 3)))]
3888 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2"
3889 [(set_attr "type" "logics_shift_imm")]
3892 ;; zero_extend version of above
3893 (define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw"
3894 [(set (reg:CC_NZ CC_REGNUM)
3898 (match_operand:SI 1 "register_operand" "r")
3899 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))
3900 (match_operand:SI 3 "register_operand" "r"))
3902 (set (match_operand:DI 0 "register_operand" "=r")
3903 (zero_extend:DI (and:SI
3905 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))]
3907 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2"
3908 [(set_attr "type" "logics_shift_imm")]
3911 (define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse"
3912 [(set (reg:CC_NZ CC_REGNUM)
3916 (match_operand:GPI 0 "register_operand" "r")
3917 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")))
3918 (match_operand:GPI 2 "register_operand" "r"))
3921 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1"
3922 [(set_attr "type" "logics_shift_imm")]
3925 (define_insn "clz<mode>2"
3926 [(set (match_operand:GPI 0 "register_operand" "=r")
3927 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))]
3929 "clz\\t%<w>0, %<w>1"
3930 [(set_attr "type" "clz")]
3933 (define_expand "ffs<mode>2"
3934 [(match_operand:GPI 0 "register_operand")
3935 (match_operand:GPI 1 "register_operand")]
3938 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
3939 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
3941 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
3942 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
3943 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx));
3948 ;; Pop count be done via the "CNT" instruction in AdvSIMD.
3955 (define_expand "popcount<mode>2"
3956 [(match_operand:GPI 0 "register_operand")
3957 (match_operand:GPI 1 "register_operand")]
3960 rtx v = gen_reg_rtx (V8QImode);
3961 rtx v1 = gen_reg_rtx (V8QImode);
3962 rtx r = gen_reg_rtx (QImode);
3963 rtx in = operands[1];
3964 rtx out = operands[0];
3965 if(<MODE>mode == SImode)
3968 tmp = gen_reg_rtx (DImode);
3969 /* If we have SImode, zero extend to DImode, pop count does
3970 not change if we have extra zeros. */
3971 emit_insn (gen_zero_extendsidi2 (tmp, in));
3974 emit_move_insn (v, gen_lowpart (V8QImode, in));
3975 emit_insn (gen_popcountv8qi2 (v1, v));
3976 emit_insn (gen_reduc_plus_scal_v8qi (r, v1));
3977 emit_insn (gen_zero_extendqi<mode>2 (out, r));
3981 (define_insn "clrsb<mode>2"
3982 [(set (match_operand:GPI 0 "register_operand" "=r")
3983 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))]
3985 "cls\\t%<w>0, %<w>1"
3986 [(set_attr "type" "clz")]
3989 (define_insn "rbit<mode>2"
3990 [(set (match_operand:GPI 0 "register_operand" "=r")
3991 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))]
3993 "rbit\\t%<w>0, %<w>1"
3994 [(set_attr "type" "rbit")]
3997 ;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC
3998 ;; it is unlikely to fold with any other operation, so keep this as a CTZ
3999 ;; expression and split after reload to enable scheduling them apart if
4002 (define_insn_and_split "ctz<mode>2"
4003 [(set (match_operand:GPI 0 "register_operand" "=r")
4004 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))]
4010 emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
4011 emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
4015 (define_insn "*and<mode>_compare0"
4016 [(set (reg:CC_NZ CC_REGNUM)
4018 (match_operand:SHORT 0 "register_operand" "r")
4021 "tst\\t%<w>0, <short_mask>"
4022 [(set_attr "type" "alus_imm")]
4025 (define_insn "*ands<mode>_compare0"
4026 [(set (reg:CC_NZ CC_REGNUM)
4028 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r"))
4030 (set (match_operand:GPI 0 "register_operand" "=r")
4031 (zero_extend:GPI (match_dup 1)))]
4033 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>"
4034 [(set_attr "type" "alus_imm")]
4037 (define_insn "*and<mode>3nr_compare0"
4038 [(set (reg:CC_NZ CC_REGNUM)
4040 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r")
4041 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>"))
4047 [(set_attr "type" "logics_reg,logics_imm")]
4051 [(set (reg:CC_NZ CC_REGNUM)
4053 (and:GPI (match_operand:GPI 0 "register_operand")
4054 (match_operand:GPI 1 "aarch64_mov_imm_operand"))
4056 (clobber (match_operand:SI 2 "register_operand"))]
4058 [(set (match_dup 2) (match_dup 1))
4059 (set (reg:CC_NZ CC_REGNUM)
4061 (and:GPI (match_dup 0)
4066 (define_insn "*and<mode>3nr_compare0_zextract"
4067 [(set (reg:CC_NZ CC_REGNUM)
4069 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r")
4070 (match_operand:GPI 1 "const_int_operand" "n")
4071 (match_operand:GPI 2 "const_int_operand" "n"))
4073 "INTVAL (operands[1]) > 0
4074 && ((INTVAL (operands[1]) + INTVAL (operands[2]))
4075 <= GET_MODE_BITSIZE (<MODE>mode))
4076 && aarch64_bitmask_imm (
4077 UINTVAL (aarch64_mask_from_zextract_ops (operands[1],
4082 = aarch64_mask_from_zextract_ops (operands[1], operands[2]);
4083 return "tst\\t%<w>0, %1";
4085 [(set_attr "type" "logics_shift_imm")]
4088 (define_insn "*and_<SHIFT:optab><mode>3nr_compare0"
4089 [(set (reg:CC_NZ CC_REGNUM)
4092 (match_operand:GPI 0 "register_operand" "r")
4093 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))
4094 (match_operand:GPI 2 "register_operand" "r"))
4097 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1"
4098 [(set_attr "type" "logics_shift_imm")]
4102 [(set (reg:CC_NZ CC_REGNUM)
4105 (match_operand:GPI 0 "register_operand")
4106 (match_operand:QI 1 "aarch64_shift_imm_<mode>"))
4107 (match_operand:GPI 2 "aarch64_mov_imm_operand"))
4109 (clobber (match_operand:SI 3 "register_operand"))]
4111 [(set (match_dup 3) (match_dup 2))
4112 (set (reg:CC_NZ CC_REGNUM)
4121 ;; -------------------------------------------------------------------
4123 ;; -------------------------------------------------------------------
4125 (define_expand "<optab><mode>3"
4126 [(set (match_operand:GPI 0 "register_operand")
4127 (ASHIFT:GPI (match_operand:GPI 1 "register_operand")
4128 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4131 if (CONST_INT_P (operands[2]))
4133 operands[2] = GEN_INT (INTVAL (operands[2])
4134 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4136 if (operands[2] == const0_rtx)
4138 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4145 (define_expand "ashl<mode>3"
4146 [(set (match_operand:SHORT 0 "register_operand")
4147 (ashift:SHORT (match_operand:SHORT 1 "register_operand")
4148 (match_operand:QI 2 "const_int_operand")))]
4151 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode));
4153 if (operands[2] == const0_rtx)
4155 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4161 (define_expand "rotr<mode>3"
4162 [(set (match_operand:GPI 0 "register_operand")
4163 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4164 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4167 if (CONST_INT_P (operands[2]))
4169 operands[2] = GEN_INT (INTVAL (operands[2])
4170 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4172 if (operands[2] == const0_rtx)
4174 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4181 (define_expand "rotl<mode>3"
4182 [(set (match_operand:GPI 0 "register_operand")
4183 (rotatert:GPI (match_operand:GPI 1 "register_operand")
4184 (match_operand:QI 2 "aarch64_reg_or_imm")))]
4187 /* (SZ - cnt) % SZ == -cnt % SZ */
4188 if (CONST_INT_P (operands[2]))
4190 operands[2] = GEN_INT ((-INTVAL (operands[2]))
4191 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
4192 if (operands[2] == const0_rtx)
4194 emit_insn (gen_mov<mode> (operands[0], operands[1]));
4199 operands[2] = expand_simple_unop (QImode, NEG, operands[2],
4204 ;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments
4205 ;; they truncate the shift/rotate amount by the size of the registers they
4206 ;; operate on: 32 for W-regs, 64 for X-regs. This allows us to optimise away
4207 ;; such redundant masking instructions. GCC can do that automatically when
4208 ;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD
4209 ;; because some of the SISD shift alternatives don't perform this truncations.
4210 ;; So this pattern exists to catch such cases.
4212 (define_insn "*aarch64_<optab>_reg_<mode>3_mask1"
4213 [(set (match_operand:GPI 0 "register_operand" "=r")
4215 (match_operand:GPI 1 "register_operand" "r")
4216 (match_operator 4 "subreg_lowpart_operator"
4217 [(and:GPI (match_operand:GPI 2 "register_operand" "r")
4218 (match_operand 3 "const_int_operand" "n"))])))]
4219 "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0"
4220 "<shift>\t%<w>0, %<w>1, %<w>2"
4221 [(set_attr "type" "shift_reg")]
4224 (define_insn_and_split "*aarch64_<optab>_reg_<mode>3_neg_mask2"
4225 [(set (match_operand:GPI 0 "register_operand" "=&r")
4227 (match_operand:GPI 1 "register_operand" "r")
4228 (match_operator 4 "subreg_lowpart_operator"
4229 [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r")
4230 (match_operand 3 "const_int_operand" "n")))])))]
4231 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)"
4236 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4237 : lowpart_subreg (SImode, operands[0], <MODE>mode));
4238 emit_insn (gen_negsi2 (tmp, operands[2]));
4240 rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]);
4241 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op,
4242 SUBREG_BYTE (operands[4]));
4243 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp));
4248 (define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask"
4249 [(set (match_operand:GPI 0 "register_operand" "=&r")
4251 (match_operand:GPI 1 "register_operand" "r")
4252 (minus:QI (match_operand 2 "const_int_operand" "n")
4253 (match_operator 5 "subreg_lowpart_operator"
4254 [(and:SI (match_operand:SI 3 "register_operand" "r")
4255 (match_operand 4 "const_int_operand" "n"))]))))]
4256 "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)
4257 && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
4262 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4265 emit_insn (gen_negsi2 (tmp, operands[3]));
4267 rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]);
4268 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op,
4269 SUBREG_BYTE (operands[5]));
4271 emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp));
4276 (define_insn "*aarch64_<optab>_reg_di3_mask2"
4277 [(set (match_operand:DI 0 "register_operand" "=r")
4279 (match_operand:DI 1 "register_operand" "r")
4280 (match_operator 4 "subreg_lowpart_operator"
4281 [(and:SI (match_operand:SI 2 "register_operand" "r")
4282 (match_operand 3 "const_int_operand" "n"))])))]
4283 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)"
4286 xop[0] = operands[0];
4287 xop[1] = operands[1];
4288 xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]);
4289 output_asm_insn ("<shift>\t%x0, %x1, %x2", xop);
4292 [(set_attr "type" "shift_reg")]
4295 (define_insn_and_split "*aarch64_<optab>_reg_minus<mode>3"
4296 [(set (match_operand:GPI 0 "register_operand" "=&r")
4298 (match_operand:GPI 1 "register_operand" "r")
4299 (minus:QI (match_operand 2 "const_int_operand" "n")
4300 (match_operand:QI 3 "register_operand" "r"))))]
4301 "INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)"
4306 rtx subreg_tmp = gen_lowpart (SImode, operands[3]);
4308 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode)
4309 : gen_lowpart (SImode, operands[0]));
4311 emit_insn (gen_negsi2 (tmp, subreg_tmp));
4313 rtx and_op = gen_rtx_AND (SImode, tmp,
4314 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1));
4316 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op);
4318 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp2));
4321 [(set_attr "length" "8")]
4324 ;; Logical left shift using SISD or Integer instruction
4325 (define_insn "*aarch64_ashl_sisd_or_int_<mode>3"
4326 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w")
4328 (match_operand:GPI 1 "register_operand" "r,r,w,w")
4329 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))]
4332 lsl\t%<w>0, %<w>1, %2
4333 lsl\t%<w>0, %<w>1, %<w>2
4334 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4335 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>"
4336 [(set_attr "simd" "no,no,yes,yes")
4337 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")]
4340 ;; Logical right shift using SISD or Integer instruction
4341 (define_insn "*aarch64_lshr_sisd_or_int_<mode>3"
4342 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4344 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4345 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>"
4346 "Us<cmode>,r,Us<cmode_simd>,w,0")))]
4349 lsr\t%<w>0, %<w>1, %2
4350 lsr\t%<w>0, %<w>1, %<w>2
4351 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4354 [(set_attr "simd" "no,no,yes,yes,yes")
4355 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4359 [(set (match_operand:DI 0 "aarch64_simd_register")
4361 (match_operand:DI 1 "aarch64_simd_register")
4362 (match_operand:QI 2 "aarch64_simd_register")))]
4363 "TARGET_SIMD && reload_completed"
4365 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4367 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))]
4369 operands[3] = gen_lowpart (QImode, operands[0]);
4374 [(set (match_operand:SI 0 "aarch64_simd_register")
4376 (match_operand:SI 1 "aarch64_simd_register")
4377 (match_operand:QI 2 "aarch64_simd_register")))]
4378 "TARGET_SIMD && reload_completed"
4380 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4382 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))]
4384 operands[3] = gen_lowpart (QImode, operands[0]);
4388 ;; Arithmetic right shift using SISD or Integer instruction
4389 (define_insn "*aarch64_ashr_sisd_or_int_<mode>3"
4390 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w")
4392 (match_operand:GPI 1 "register_operand" "r,r,w,w,w")
4393 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di"
4394 "Us<cmode>,r,Us<cmode_simd>,w,0")))]
4397 asr\t%<w>0, %<w>1, %2
4398 asr\t%<w>0, %<w>1, %<w>2
4399 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2
4402 [(set_attr "simd" "no,no,yes,yes,yes")
4403 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")]
4407 [(set (match_operand:DI 0 "aarch64_simd_register")
4409 (match_operand:DI 1 "aarch64_simd_register")
4410 (match_operand:QI 2 "aarch64_simd_register")))]
4411 "TARGET_SIMD && reload_completed"
4413 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4415 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))]
4417 operands[3] = gen_lowpart (QImode, operands[0]);
4422 [(set (match_operand:SI 0 "aarch64_simd_register")
4424 (match_operand:SI 1 "aarch64_simd_register")
4425 (match_operand:QI 2 "aarch64_simd_register")))]
4426 "TARGET_SIMD && reload_completed"
4428 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG))
4430 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))]
4432 operands[3] = gen_lowpart (QImode, operands[0]);
4436 (define_insn "*aarch64_sisd_ushl"
4437 [(set (match_operand:DI 0 "register_operand" "=w")
4438 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4439 (match_operand:QI 2 "register_operand" "w")]
4442 "ushl\t%d0, %d1, %d2"
4443 [(set_attr "simd" "yes")
4444 (set_attr "type" "neon_shift_reg")]
4447 (define_insn "*aarch64_ushl_2s"
4448 [(set (match_operand:SI 0 "register_operand" "=w")
4449 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4450 (match_operand:QI 2 "register_operand" "w")]
4453 "ushl\t%0.2s, %1.2s, %2.2s"
4454 [(set_attr "simd" "yes")
4455 (set_attr "type" "neon_shift_reg")]
4458 (define_insn "*aarch64_sisd_sshl"
4459 [(set (match_operand:DI 0 "register_operand" "=w")
4460 (unspec:DI [(match_operand:DI 1 "register_operand" "w")
4461 (match_operand:QI 2 "register_operand" "w")]
4464 "sshl\t%d0, %d1, %d2"
4465 [(set_attr "simd" "yes")
4466 (set_attr "type" "neon_shift_reg")]
4469 (define_insn "*aarch64_sshl_2s"
4470 [(set (match_operand:SI 0 "register_operand" "=w")
4471 (unspec:SI [(match_operand:SI 1 "register_operand" "w")
4472 (match_operand:QI 2 "register_operand" "w")]
4475 "sshl\t%0.2s, %1.2s, %2.2s"
4476 [(set_attr "simd" "yes")
4477 (set_attr "type" "neon_shift_reg")]
4480 (define_insn "*aarch64_sisd_neg_qi"
4481 [(set (match_operand:QI 0 "register_operand" "=w")
4482 (unspec:QI [(match_operand:QI 1 "register_operand" "w")]
4486 [(set_attr "simd" "yes")
4487 (set_attr "type" "neon_neg")]
4491 (define_insn "*ror<mode>3_insn"
4492 [(set (match_operand:GPI 0 "register_operand" "=r,r")
4494 (match_operand:GPI 1 "register_operand" "r,r")
4495 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))]
4498 ror\\t%<w>0, %<w>1, %2
4499 ror\\t%<w>0, %<w>1, %<w>2"
4500 [(set_attr "type" "rotate_imm,shift_reg")]
4503 ;; zero_extend version of above
4504 (define_insn "*<optab>si3_insn_uxtw"
4505 [(set (match_operand:DI 0 "register_operand" "=r,r")
4506 (zero_extend:DI (SHIFT:SI
4507 (match_operand:SI 1 "register_operand" "r,r")
4508 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))]
4511 <shift>\\t%w0, %w1, %2
4512 <shift>\\t%w0, %w1, %w2"
4513 [(set_attr "type" "bfx,shift_reg")]
4516 (define_insn "*<optab><mode>3_insn"
4517 [(set (match_operand:SHORT 0 "register_operand" "=r")
4518 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r")
4519 (match_operand 2 "const_int_operand" "n")))]
4520 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4522 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4523 return "<bfshift>\t%w0, %w1, %2, %3";
4525 [(set_attr "type" "bfx")]
4528 (define_insn "*extr<mode>5_insn"
4529 [(set (match_operand:GPI 0 "register_operand" "=r")
4530 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4531 (match_operand 3 "const_int_operand" "n"))
4532 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4533 (match_operand 4 "const_int_operand" "n"))))]
4534 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) &&
4535 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))"
4536 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4537 [(set_attr "type" "rotate_imm")]
4540 ;; There are no canonicalisation rules for ashift and lshiftrt inside an ior
4541 ;; so we have to match both orderings.
4542 (define_insn "*extr<mode>5_insn_alt"
4543 [(set (match_operand:GPI 0 "register_operand" "=r")
4544 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r")
4545 (match_operand 4 "const_int_operand" "n"))
4546 (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4547 (match_operand 3 "const_int_operand" "n"))))]
4548 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode)
4549 && (UINTVAL (operands[3]) + UINTVAL (operands[4])
4550 == GET_MODE_BITSIZE (<MODE>mode))"
4551 "extr\\t%<w>0, %<w>1, %<w>2, %4"
4552 [(set_attr "type" "rotate_imm")]
4555 ;; zero_extend version of the above
4556 (define_insn "*extrsi5_insn_uxtw"
4557 [(set (match_operand:DI 0 "register_operand" "=r")
4559 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
4560 (match_operand 3 "const_int_operand" "n"))
4561 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4562 (match_operand 4 "const_int_operand" "n")))))]
4563 "UINTVAL (operands[3]) < 32 &&
4564 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4565 "extr\\t%w0, %w1, %w2, %4"
4566 [(set_attr "type" "rotate_imm")]
4569 (define_insn "*extrsi5_insn_uxtw_alt"
4570 [(set (match_operand:DI 0 "register_operand" "=r")
4572 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r")
4573 (match_operand 4 "const_int_operand" "n"))
4574 (ashift:SI (match_operand:SI 1 "register_operand" "r")
4575 (match_operand 3 "const_int_operand" "n")))))]
4576 "UINTVAL (operands[3]) < 32 &&
4577 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)"
4578 "extr\\t%w0, %w1, %w2, %4"
4579 [(set_attr "type" "rotate_imm")]
4582 (define_insn "*ror<mode>3_insn"
4583 [(set (match_operand:GPI 0 "register_operand" "=r")
4584 (rotate:GPI (match_operand:GPI 1 "register_operand" "r")
4585 (match_operand 2 "const_int_operand" "n")))]
4586 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
4588 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2]));
4589 return "ror\\t%<w>0, %<w>1, %3";
4591 [(set_attr "type" "rotate_imm")]
4594 ;; zero_extend version of the above
4595 (define_insn "*rorsi3_insn_uxtw"
4596 [(set (match_operand:DI 0 "register_operand" "=r")
4598 (rotate:SI (match_operand:SI 1 "register_operand" "r")
4599 (match_operand 2 "const_int_operand" "n"))))]
4600 "UINTVAL (operands[2]) < 32"
4602 operands[3] = GEN_INT (32 - UINTVAL (operands[2]));
4603 return "ror\\t%w0, %w1, %3";
4605 [(set_attr "type" "rotate_imm")]
4608 (define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>"
4609 [(set (match_operand:GPI 0 "register_operand" "=r")
4611 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r")
4612 (match_operand 2 "const_int_operand" "n"))))]
4613 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4615 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4616 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4618 [(set_attr "type" "bfx")]
4621 (define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>"
4622 [(set (match_operand:GPI 0 "register_operand" "=r")
4624 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4625 (match_operand 2 "const_int_operand" "n"))))]
4626 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4628 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4629 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4631 [(set_attr "type" "bfx")]
4634 (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
4635 [(set (match_operand:GPI 0 "register_operand" "=r")
4637 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r")
4638 (match_operand 2 "const_int_operand" "n"))))]
4639 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
4641 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2]));
4642 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4644 [(set_attr "type" "bfx")]
4647 ;; -------------------------------------------------------------------
4649 ;; -------------------------------------------------------------------
4651 (define_expand "<optab>"
4652 [(set (match_operand:DI 0 "register_operand" "=r")
4653 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
4655 "aarch64_simd_shift_imm_offset_di")
4656 (match_operand 3 "aarch64_simd_shift_imm_di")))]
4659 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4660 1, GET_MODE_BITSIZE (DImode) - 1))
4666 (define_insn "*<optab><mode>"
4667 [(set (match_operand:GPI 0 "register_operand" "=r")
4668 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
4670 "aarch64_simd_shift_imm_offset_<mode>" "n")
4672 "aarch64_simd_shift_imm_<mode>" "n")))]
4673 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
4674 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
4675 "<su>bfx\\t%<w>0, %<w>1, %3, %2"
4676 [(set_attr "type" "bfx")]
4679 ;; When the bit position and width add up to 32 we can use a W-reg LSR
4680 ;; instruction taking advantage of the implicit zero-extension of the X-reg.
4682 [(set (match_operand:DI 0 "register_operand")
4683 (zero_extract:DI (match_operand:DI 1 "register_operand")
4685 "aarch64_simd_shift_imm_offset_di")
4687 "aarch64_simd_shift_imm_di")))]
4688 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1,
4689 GET_MODE_BITSIZE (DImode) - 1)
4690 && (INTVAL (operands[2]) + INTVAL (operands[3]))
4691 == GET_MODE_BITSIZE (SImode)"
4693 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))]
4695 operands[4] = gen_lowpart (SImode, operands[1]);
4699 ;; Bitfield Insert (insv)
4700 (define_expand "insv<mode>"
4701 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand")
4702 (match_operand 1 "const_int_operand")
4703 (match_operand 2 "const_int_operand"))
4704 (match_operand:GPI 3 "general_operand"))]
4707 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]);
4708 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]);
4709 rtx value = operands[3];
4711 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode))
4714 if (CONST_INT_P (value))
4716 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1;
4718 /* Prefer AND/OR for inserting all zeros or all ones. */
4719 if ((UINTVAL (value) & mask) == 0
4720 || (UINTVAL (value) & mask) == mask)
4723 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */
4724 if (width == 16 && (pos % 16) == 0)
4727 operands[3] = force_reg (<MODE>mode, value);
4730 (define_insn "*insv_reg<mode>"
4731 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4732 (match_operand 1 "const_int_operand" "n")
4733 (match_operand 2 "const_int_operand" "n"))
4734 (match_operand:GPI 3 "register_operand" "r"))]
4735 "!(UINTVAL (operands[1]) == 0
4736 || (UINTVAL (operands[2]) + UINTVAL (operands[1])
4737 > GET_MODE_BITSIZE (<MODE>mode)))"
4738 "bfi\\t%<w>0, %<w>3, %2, %1"
4739 [(set_attr "type" "bfm")]
4742 (define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4"
4743 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4744 (match_operand 1 "const_int_operand" "n")
4745 (match_operand 2 "const_int_operand" "n"))
4746 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))]
4747 "UINTVAL (operands[1]) <= <ALLX:sizen>"
4748 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1"
4749 [(set_attr "type" "bfm")]
4752 (define_insn "*extr_insv_lower_reg<mode>"
4753 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r")
4754 (match_operand 1 "const_int_operand" "n")
4756 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r")
4758 (match_operand 3 "const_int_operand" "n")))]
4759 "!(UINTVAL (operands[1]) == 0
4760 || (UINTVAL (operands[3]) + UINTVAL (operands[1])
4761 > GET_MODE_BITSIZE (<MODE>mode)))"
4762 "bfxil\\t%<w>0, %<w>2, %3, %1"
4763 [(set_attr "type" "bfm")]
4766 (define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>"
4767 [(set (match_operand:GPI 0 "register_operand" "=r")
4768 (ashift:GPI (ANY_EXTEND:GPI
4769 (match_operand:ALLX 1 "register_operand" "r"))
4770 (match_operand 2 "const_int_operand" "n")))]
4771 "UINTVAL (operands[2]) < <GPI:sizen>"
4773 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2])))
4774 ? GEN_INT (<ALLX:sizen>)
4775 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2]));
4776 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3";
4778 [(set_attr "type" "bfx")]
4781 ;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below
4783 (define_insn "*andim_ashift<mode>_bfiz"
4784 [(set (match_operand:GPI 0 "register_operand" "=r")
4785 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4786 (match_operand 2 "const_int_operand" "n"))
4787 (match_operand 3 "const_int_operand" "n")))]
4788 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])"
4789 "ubfiz\\t%<w>0, %<w>1, %2, %P3"
4790 [(set_attr "type" "bfx")]
4793 ;; When the bit position and width of the equivalent extraction add up to 32
4794 ;; we can use a W-reg LSL instruction taking advantage of the implicit
4795 ;; zero-extension of the X-reg.
4797 [(set (match_operand:DI 0 "register_operand")
4798 (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
4799 (match_operand 2 "const_int_operand"))
4800 (match_operand 3 "const_int_operand")))]
4801 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2])
4802 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3])))
4803 == GET_MODE_BITSIZE (SImode)"
4805 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))]
4807 operands[4] = gen_lowpart (SImode, operands[1]);
4811 (define_insn "bswap<mode>2"
4812 [(set (match_operand:GPI 0 "register_operand" "=r")
4813 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))]
4815 "rev\\t%<w>0, %<w>1"
4816 [(set_attr "type" "rev")]
4819 (define_insn "bswaphi2"
4820 [(set (match_operand:HI 0 "register_operand" "=r")
4821 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
4824 [(set_attr "type" "rev")]
4827 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
4828 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
4829 ;; each valid permutation.
4831 (define_insn "rev16<mode>2"
4832 [(set (match_operand:GPI 0 "register_operand" "=r")
4833 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r")
4835 (match_operand:GPI 3 "const_int_operand" "n"))
4836 (and:GPI (lshiftrt:GPI (match_dup 1)
4838 (match_operand:GPI 2 "const_int_operand" "n"))))]
4839 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4840 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4841 "rev16\\t%<w>0, %<w>1"
4842 [(set_attr "type" "rev")]
4845 (define_insn "rev16<mode>2_alt"
4846 [(set (match_operand:GPI 0 "register_operand" "=r")
4847 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r")
4849 (match_operand:GPI 2 "const_int_operand" "n"))
4850 (and:GPI (ashift:GPI (match_dup 1)
4852 (match_operand:GPI 3 "const_int_operand" "n"))))]
4853 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode)
4854 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)"
4855 "rev16\\t%<w>0, %<w>1"
4856 [(set_attr "type" "rev")]
4859 ;; zero_extend version of above
4860 (define_insn "*bswapsi2_uxtw"
4861 [(set (match_operand:DI 0 "register_operand" "=r")
4862 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))]
4865 [(set_attr "type" "rev")]
4868 ;; -------------------------------------------------------------------
4869 ;; Floating-point intrinsics
4870 ;; -------------------------------------------------------------------
4872 ;; frint floating-point round to integral standard patterns.
4873 ;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn.
4875 (define_insn "<frint_pattern><mode>2"
4876 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4877 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4880 "frint<frint_suffix>\\t%<s>0, %<s>1"
4881 [(set_attr "type" "f_rint<stype>")]
4884 ;; frcvt floating-point round to integer and convert standard patterns.
4885 ;; Expands to lbtrunc, lceil, lfloor, lround.
4886 (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2"
4887 [(set (match_operand:GPI 0 "register_operand" "=r")
4889 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")]
4892 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1"
4893 [(set_attr "type" "f_cvtf2i")]
4896 (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult"
4897 [(set (match_operand:GPI 0 "register_operand" "=r")
4900 (match_operand:GPF 1 "register_operand" "w")
4901 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))]
4903 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1,
4904 GET_MODE_BITSIZE (<GPI:MODE>mode))"
4906 int fbits = aarch64_fpconst_pow_of_2 (operands[2]);
4908 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits);
4909 output_asm_insn (buf, operands);
4912 [(set_attr "type" "f_cvtf2i")]
4915 ;; fma - expand fma into patterns with the accumulator operand first since
4916 ;; reusing the accumulator results in better register allocation.
4917 ;; The register allocator considers copy preferences in operand order,
4918 ;; so this prefers fmadd s0, s1, s2, s0 over fmadd s1, s1, s2, s0.
4920 (define_expand "fma<mode>4"
4921 [(set (match_operand:GPF_F16 0 "register_operand")
4922 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand")
4923 (match_operand:GPF_F16 2 "register_operand")
4924 (match_operand:GPF_F16 3 "register_operand")))]
4928 (define_insn "*aarch64_fma<mode>4"
4929 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4930 (fma:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w")
4931 (match_operand:GPF_F16 3 "register_operand" "w")
4932 (match_operand:GPF_F16 1 "register_operand" "w")))]
4934 "fmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
4935 [(set_attr "type" "fmac<stype>")]
4938 (define_expand "fnma<mode>4"
4939 [(set (match_operand:GPF_F16 0 "register_operand")
4941 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand"))
4942 (match_operand:GPF_F16 2 "register_operand")
4943 (match_operand:GPF_F16 3 "register_operand")))]
4947 (define_insn "*aarch64_fnma<mode>4"
4948 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
4950 (neg:GPF_F16 (match_operand:GPF_F16 2 "register_operand" "w"))
4951 (match_operand:GPF_F16 3 "register_operand" "w")
4952 (match_operand:GPF_F16 1 "register_operand" "w")))]
4954 "fmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
4955 [(set_attr "type" "fmac<stype>")]
4959 (define_expand "fms<mode>4"
4960 [(set (match_operand:GPF 0 "register_operand")
4961 (fma:GPF (match_operand:GPF 1 "register_operand")
4962 (match_operand:GPF 2 "register_operand")
4963 (neg:GPF (match_operand:GPF 3 "register_operand"))))]
4967 (define_insn "*aarch64_fms<mode>4"
4968 [(set (match_operand:GPF 0 "register_operand" "=w")
4969 (fma:GPF (match_operand:GPF 2 "register_operand" "w")
4970 (match_operand:GPF 3 "register_operand" "w")
4971 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
4973 "fnmsub\\t%<s>0, %<s>2, %<s>3, %<s>1"
4974 [(set_attr "type" "fmac<s>")]
4977 (define_expand "fnms<mode>4"
4978 [(set (match_operand:GPF 0 "register_operand")
4979 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand"))
4980 (match_operand:GPF 2 "register_operand")
4981 (neg:GPF (match_operand:GPF 3 "register_operand"))))]
4985 (define_insn "*aarch64_fnms<mode>4"
4986 [(set (match_operand:GPF 0 "register_operand" "=w")
4987 (fma:GPF (neg:GPF (match_operand:GPF 2 "register_operand" "w"))
4988 (match_operand:GPF 3 "register_operand" "w")
4989 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))))]
4991 "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
4992 [(set_attr "type" "fmac<s>")]
4995 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
4996 (define_insn "*aarch64_fnmadd<mode>4"
4997 [(set (match_operand:GPF 0 "register_operand" "=w")
4998 (neg:GPF (fma:GPF (match_operand:GPF 2 "register_operand" "w")
4999 (match_operand:GPF 3 "register_operand" "w")
5000 (match_operand:GPF 1 "register_operand" "w"))))]
5001 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT"
5002 "fnmadd\\t%<s>0, %<s>2, %<s>3, %<s>1"
5003 [(set_attr "type" "fmac<s>")]
5006 ;; -------------------------------------------------------------------
5007 ;; Floating-point conversions
5008 ;; -------------------------------------------------------------------
5010 (define_insn "extendsfdf2"
5011 [(set (match_operand:DF 0 "register_operand" "=w")
5012 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))]
5015 [(set_attr "type" "f_cvt")]
5018 (define_insn "extendhfsf2"
5019 [(set (match_operand:SF 0 "register_operand" "=w")
5020 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))]
5023 [(set_attr "type" "f_cvt")]
5026 (define_insn "extendhfdf2"
5027 [(set (match_operand:DF 0 "register_operand" "=w")
5028 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))]
5031 [(set_attr "type" "f_cvt")]
5034 (define_insn "truncdfsf2"
5035 [(set (match_operand:SF 0 "register_operand" "=w")
5036 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))]
5039 [(set_attr "type" "f_cvt")]
5042 (define_insn "truncsfhf2"
5043 [(set (match_operand:HF 0 "register_operand" "=w")
5044 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))]
5047 [(set_attr "type" "f_cvt")]
5050 (define_insn "truncdfhf2"
5051 [(set (match_operand:HF 0 "register_operand" "=w")
5052 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))]
5055 [(set_attr "type" "f_cvt")]
5058 ;; Convert SF -> SI or DF -> DI while preferring w = w register constraints
5059 ;; and making r = w more expensive
5061 (define_insn "<optab>_trunc<fcvt_target><GPI:mode>2"
5062 [(set (match_operand:GPI 0 "register_operand" "=w,?r")
5063 (FIXUORS:GPI (match_operand:<FCVT_TARGET> 1 "register_operand" "w,w")))]
5066 fcvtz<su>\t%<s>0, %<s>1
5067 fcvtz<su>\t%<w>0, %<s>1"
5068 [(set_attr "type" "neon_fp_to_int_s,f_cvtf2i")]
5071 ;; Convert HF -> SI or DI
5073 (define_insn "<optab>_trunchf<GPI:mode>2"
5074 [(set (match_operand:GPI 0 "register_operand" "=r")
5075 (FIXUORS:GPI (match_operand:HF 1 "register_operand" "w")))]
5077 "fcvtz<su>\t%<w>0, %h1"
5078 [(set_attr "type" "f_cvtf2i")]
5081 ;; Convert DF -> SI or SF -> DI which can only be accomplished with
5082 ;; input in a fp register and output in a integer register
5084 (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>2"
5085 [(set (match_operand:GPI 0 "register_operand" "=r")
5086 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand" "w")))]
5088 "fcvtz<su>\t%<w>0, %<fpw>1"
5089 [(set_attr "type" "f_cvtf2i")]
5092 (define_insn "<optab><fcvt_target><GPF:mode>2"
5093 [(set (match_operand:GPF 0 "register_operand" "=w,w")
5094 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,?r")))]
5097 <su_optab>cvtf\t%<GPF:s>0, %<s>1
5098 <su_optab>cvtf\t%<GPF:s>0, %<w1>1"
5099 [(set_attr "simd" "yes,no")
5100 (set_attr "fp" "no,yes")
5101 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")]
5104 (define_insn "<optab><fcvt_iesize><GPF:mode>2"
5105 [(set (match_operand:GPF 0 "register_operand" "=w")
5106 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))]
5108 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1"
5109 [(set_attr "type" "f_cvti2f")]
5112 ;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
5113 ;; midend will arrange for an SImode conversion to HFmode to first go
5114 ;; through DFmode, then to HFmode. But first it will try converting
5115 ;; to DImode then down, which would match our DImode pattern below and
5116 ;; give very poor code-generation. So, we must provide our own emulation
5117 ;; of the mid-end logic.
5119 (define_insn "aarch64_fp16_<optab><mode>hf2"
5120 [(set (match_operand:HF 0 "register_operand" "=w")
5121 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
5123 "<su_optab>cvtf\t%h0, %<w>1"
5124 [(set_attr "type" "f_cvti2f")]
5127 (define_expand "<optab>sihf2"
5128 [(set (match_operand:HF 0 "register_operand")
5129 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
5132 if (TARGET_FP_F16INST)
5133 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
5136 rtx convert_target = gen_reg_rtx (DFmode);
5137 emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
5138 emit_insn (gen_truncdfhf2 (operands[0], convert_target));
5144 ;; For DImode there is no wide enough floating-point mode that we
5145 ;; can convert through natively (TFmode would work, but requires a library
5146 ;; call). However, we know that any value >= 65504 will be rounded
5147 ;; to infinity on conversion. This is well within the range of SImode, so
5149 ;; Saturate to SImode.
5150 ;; Convert from that to DFmode
5151 ;; Convert from that to HFmode (phew!).
5152 ;; Note that the saturation to SImode requires the SIMD extensions. If
5153 ;; we ever need to provide this pattern where the SIMD extensions are not
5154 ;; available, we would need a different approach.
5156 (define_expand "<optab>dihf2"
5157 [(set (match_operand:HF 0 "register_operand")
5158 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
5159 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
5161 if (TARGET_FP_F16INST)
5162 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
5165 rtx sat_target = gen_reg_rtx (SImode);
5166 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
5167 emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
5174 ;; Convert between fixed-point and floating-point (scalar modes)
5176 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
5177 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w")
5178 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w")
5179 (match_operand:SI 2 "immediate_operand" "i, i")]
5183 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2
5184 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2"
5185 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>")
5186 (set_attr "fp" "yes, *")
5187 (set_attr "simd" "*, yes")]
5190 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3"
5191 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w")
5192 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w")
5193 (match_operand:SI 2 "immediate_operand" "i, i")]
5197 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2
5198 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2"
5199 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>")
5200 (set_attr "fp" "yes, *")
5201 (set_attr "simd" "*, yes")]
5204 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3"
5205 [(set (match_operand:GPI 0 "register_operand" "=r")
5206 (unspec:GPI [(match_operand:HF 1 "register_operand" "w")
5207 (match_operand:SI 2 "immediate_operand" "i")]
5210 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2"
5211 [(set_attr "type" "f_cvtf2i")]
5214 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3"
5215 [(set (match_operand:HF 0 "register_operand" "=w")
5216 (unspec:HF [(match_operand:GPI 1 "register_operand" "r")
5217 (match_operand:SI 2 "immediate_operand" "i")]
5220 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2"
5221 [(set_attr "type" "f_cvti2f")]
5224 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3"
5225 [(set (match_operand:HI 0 "register_operand" "=w")
5226 (unspec:HI [(match_operand:HF 1 "register_operand" "w")
5227 (match_operand:SI 2 "immediate_operand" "i")]
5230 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2"
5231 [(set_attr "type" "neon_fp_to_int_s")]
5234 (define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3"
5235 [(set (match_operand:HF 0 "register_operand" "=w")
5236 (unspec:HF [(match_operand:HI 1 "register_operand" "w")
5237 (match_operand:SI 2 "immediate_operand" "i")]
5240 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2"
5241 [(set_attr "type" "neon_int_to_fp_s")]
5244 ;; -------------------------------------------------------------------
5245 ;; Floating-point arithmetic
5246 ;; -------------------------------------------------------------------
5248 (define_insn "add<mode>3"
5249 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5251 (match_operand:GPF_F16 1 "register_operand" "w")
5252 (match_operand:GPF_F16 2 "register_operand" "w")))]
5254 "fadd\\t%<s>0, %<s>1, %<s>2"
5255 [(set_attr "type" "fadd<stype>")]
5258 (define_insn "sub<mode>3"
5259 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5261 (match_operand:GPF_F16 1 "register_operand" "w")
5262 (match_operand:GPF_F16 2 "register_operand" "w")))]
5264 "fsub\\t%<s>0, %<s>1, %<s>2"
5265 [(set_attr "type" "fadd<stype>")]
5268 (define_insn "mul<mode>3"
5269 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5271 (match_operand:GPF_F16 1 "register_operand" "w")
5272 (match_operand:GPF_F16 2 "register_operand" "w")))]
5274 "fmul\\t%<s>0, %<s>1, %<s>2"
5275 [(set_attr "type" "fmul<stype>")]
5278 (define_insn "*fnmul<mode>3"
5279 [(set (match_operand:GPF 0 "register_operand" "=w")
5281 (neg:GPF (match_operand:GPF 1 "register_operand" "w"))
5282 (match_operand:GPF 2 "register_operand" "w")))]
5283 "TARGET_FLOAT && !flag_rounding_math"
5284 "fnmul\\t%<s>0, %<s>1, %<s>2"
5285 [(set_attr "type" "fmul<s>")]
5288 (define_insn "*fnmul<mode>3"
5289 [(set (match_operand:GPF 0 "register_operand" "=w")
5291 (match_operand:GPF 1 "register_operand" "w")
5292 (match_operand:GPF 2 "register_operand" "w"))))]
5294 "fnmul\\t%<s>0, %<s>1, %<s>2"
5295 [(set_attr "type" "fmul<s>")]
5298 (define_expand "div<mode>3"
5299 [(set (match_operand:GPF_F16 0 "register_operand")
5300 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand")
5301 (match_operand:GPF_F16 2 "register_operand")))]
5304 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
5307 operands[1] = force_reg (<MODE>mode, operands[1]);
5310 (define_insn "*div<mode>3"
5311 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5312 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")
5313 (match_operand:GPF_F16 2 "register_operand" "w")))]
5315 "fdiv\\t%<s>0, %<s>1, %<s>2"
5316 [(set_attr "type" "fdiv<stype>")]
5319 (define_insn "neg<mode>2"
5320 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5321 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5323 "fneg\\t%<s>0, %<s>1"
5324 [(set_attr "type" "ffarith<stype>")]
5327 (define_expand "sqrt<mode>2"
5328 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5329 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5332 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
5336 (define_insn "*sqrt<mode>2"
5337 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5338 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5340 "fsqrt\\t%<s>0, %<s>1"
5341 [(set_attr "type" "fsqrt<stype>")]
5344 (define_insn "abs<mode>2"
5345 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5346 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
5348 "fabs\\t%<s>0, %<s>1"
5349 [(set_attr "type" "ffarith<stype>")]
5352 ;; Given that smax/smin do not specify the result when either input is NaN,
5353 ;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN
5356 (define_insn "smax<mode>3"
5357 [(set (match_operand:GPF 0 "register_operand" "=w")
5358 (smax:GPF (match_operand:GPF 1 "register_operand" "w")
5359 (match_operand:GPF 2 "register_operand" "w")))]
5361 "fmaxnm\\t%<s>0, %<s>1, %<s>2"
5362 [(set_attr "type" "f_minmax<s>")]
5365 (define_insn "smin<mode>3"
5366 [(set (match_operand:GPF 0 "register_operand" "=w")
5367 (smin:GPF (match_operand:GPF 1 "register_operand" "w")
5368 (match_operand:GPF 2 "register_operand" "w")))]
5370 "fminnm\\t%<s>0, %<s>1, %<s>2"
5371 [(set_attr "type" "f_minmax<s>")]
5374 ;; Scalar forms for fmax, fmin, fmaxnm, fminnm.
5375 ;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names,
5376 ;; which implement the IEEE fmax ()/fmin () functions.
5377 (define_insn "<maxmin_uns><mode>3"
5378 [(set (match_operand:GPF_F16 0 "register_operand" "=w")
5379 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")
5380 (match_operand:GPF_F16 2 "register_operand" "w")]
5383 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2"
5384 [(set_attr "type" "f_minmax<stype>")]
5387 (define_expand "lrint<GPF:mode><GPI:mode>2"
5388 [(match_operand:GPI 0 "register_operand")
5389 (match_operand:GPF 1 "register_operand")]
5391 && ((GET_MODE_SIZE (<GPF:MODE>mode) <= GET_MODE_SIZE (<GPI:MODE>mode))
5392 || !flag_trapping_math || flag_fp_int_builtin_inexact)"
5394 rtx cvt = gen_reg_rtx (<GPF:MODE>mode);
5395 emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1]));
5396 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt));
5401 ;; For copysign (x, y), we want to generate:
5403 ;; LDR d2, #(1 << 63)
5404 ;; BSL v2.8b, [y], [x]
5406 ;; or another, equivalent, sequence using one of BSL/BIT/BIF.
5407 ;; aarch64_simd_bsldf will select the best suited of these instructions
5408 ;; to generate based on register allocation, and knows how to partially
5409 ;; constant fold based on the values of X and Y, so expand through that.
5411 (define_expand "copysigndf3"
5412 [(match_operand:DF 0 "register_operand")
5413 (match_operand:DF 1 "register_operand")
5414 (match_operand:DF 2 "register_operand")]
5415 "TARGET_FLOAT && TARGET_SIMD"
5417 rtx mask = gen_reg_rtx (DImode);
5418 emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
5419 emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
5420 operands[2], operands[1]));
5425 ;; As above, but we must first get to a 64-bit value if we wish to use
5426 ;; aarch64_simd_bslv2sf.
5428 (define_expand "copysignsf3"
5429 [(match_operand:SF 0 "register_operand")
5430 (match_operand:SF 1 "register_operand")
5431 (match_operand:SF 2 "register_operand")]
5432 "TARGET_FLOAT && TARGET_SIMD"
5434 rtx v_bitmask = gen_reg_rtx (V2SImode);
5436 /* Juggle modes to get us in to a vector mode for BSL. */
5437 rtx op1 = lowpart_subreg (DImode, operands[1], SFmode);
5438 rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
5439 rtx tmp = gen_reg_rtx (V2SFmode);
5440 emit_move_insn (v_bitmask,
5441 aarch64_simd_gen_const_vector_dup (V2SImode,
5442 HOST_WIDE_INT_M1U << 31));
5443 emit_insn (gen_aarch64_simd_bslv2sf (tmp, v_bitmask, op2, op1));
5444 emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
5449 ;; For xorsign (x, y), we want to generate:
5452 ;; AND v3.8B, v1.8B, v2.8B
5453 ;; EOR v0.8B, v0.8B, v3.8B
5456 (define_expand "xorsign<mode>3"
5457 [(match_operand:GPF 0 "register_operand")
5458 (match_operand:GPF 1 "register_operand")
5459 (match_operand:GPF 2 "register_operand")]
5460 "TARGET_FLOAT && TARGET_SIMD"
5463 machine_mode imode = <V_INT_EQUIV>mode;
5464 rtx mask = gen_reg_rtx (imode);
5465 rtx op1x = gen_reg_rtx (imode);
5466 rtx op2x = gen_reg_rtx (imode);
5468 int bits = GET_MODE_BITSIZE (<MODE>mode) - 1;
5469 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits,
5472 emit_insn (gen_and<v_int_equiv>3 (op2x, mask,
5473 lowpart_subreg (imode, operands[2],
5475 emit_insn (gen_xor<v_int_equiv>3 (op1x,
5476 lowpart_subreg (imode, operands[1],
5479 emit_move_insn (operands[0],
5480 lowpart_subreg (<MODE>mode, op1x, imode));
5485 ;; -------------------------------------------------------------------
5487 ;; -------------------------------------------------------------------
5488 ;; Reload Scalar Floating point modes from constant pool.
5489 ;; The AArch64 port doesn't have __int128 constant move support.
5490 (define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
5491 [(set (match_operand:GPF_TF 0 "register_operand" "=w")
5492 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
5493 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5496 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5497 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2]));
5502 ;; Reload Vector modes from constant pool.
5503 (define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
5504 [(set (match_operand:VALL 0 "register_operand" "=w")
5505 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
5506 (clobber (match_operand:P 2 "register_operand" "=&r"))]
5509 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0));
5510 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2]));
5515 (define_expand "aarch64_reload_mov<mode>"
5516 [(set (match_operand:TX 0 "register_operand" "=w")
5517 (match_operand:TX 1 "register_operand" "w"))
5518 (clobber (match_operand:DI 2 "register_operand" "=&r"))
5522 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0);
5523 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0);
5524 gen_aarch64_movtilow_tilow (op0, op1);
5525 gen_aarch64_movdi_tihigh (operands[2], op1);
5526 gen_aarch64_movtihigh_di (op0, operands[2]);
5531 ;; The following secondary reload helpers patterns are invoked
5532 ;; after or during reload as we don't want these patterns to start
5533 ;; kicking in during the combiner.
5535 (define_insn "aarch64_movdi_<mode>low"
5536 [(set (match_operand:DI 0 "register_operand" "=r")
5537 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5538 (const_int 64) (const_int 0)))]
5539 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5541 [(set_attr "type" "f_mrc")
5542 (set_attr "length" "4")
5545 (define_insn "aarch64_movdi_<mode>high"
5546 [(set (match_operand:DI 0 "register_operand" "=r")
5547 (zero_extract:DI (match_operand:TX 1 "register_operand" "w")
5548 (const_int 64) (const_int 64)))]
5549 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5550 "fmov\\t%x0, %1.d[1]"
5551 [(set_attr "type" "f_mrc")
5552 (set_attr "length" "4")
5555 (define_insn "aarch64_mov<mode>high_di"
5556 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
5557 (const_int 64) (const_int 64))
5558 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5559 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5560 "fmov\\t%0.d[1], %x1"
5561 [(set_attr "type" "f_mcr")
5562 (set_attr "length" "4")
5565 (define_insn "aarch64_mov<mode>low_di"
5566 [(set (match_operand:TX 0 "register_operand" "=w")
5567 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
5568 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5570 [(set_attr "type" "f_mcr")
5571 (set_attr "length" "4")
5574 (define_insn "aarch64_movtilow_tilow"
5575 [(set (match_operand:TI 0 "register_operand" "=w")
5577 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))]
5578 "TARGET_FLOAT && (reload_completed || reload_in_progress)"
5580 [(set_attr "type" "fmov")
5581 (set_attr "length" "4")
5584 ;; There is a deliberate reason why the parameters of high and lo_sum's
5585 ;; don't have modes for ADRP and ADD instructions. This is to allow high
5586 ;; and lo_sum's to be used with the labels defining the jump tables in
5589 (define_expand "add_losym"
5590 [(set (match_operand 0 "register_operand" "=r")
5591 (lo_sum (match_operand 1 "register_operand" "r")
5592 (match_operand 2 "aarch64_valid_symref" "S")))]
5595 machine_mode mode = GET_MODE (operands[0]);
5597 emit_insn ((mode == DImode
5599 : gen_add_losym_si) (operands[0],
5605 (define_insn "add_losym_<mode>"
5606 [(set (match_operand:P 0 "register_operand" "=r")
5607 (lo_sum:P (match_operand:P 1 "register_operand" "r")
5608 (match_operand 2 "aarch64_valid_symref" "S")))]
5610 "add\\t%<w>0, %<w>1, :lo12:%c2"
5611 [(set_attr "type" "alu_imm")]
5614 (define_insn "ldr_got_small_<mode>"
5615 [(set (match_operand:PTR 0 "register_operand" "=r")
5616 (unspec:PTR [(mem:PTR (lo_sum:PTR
5617 (match_operand:PTR 1 "register_operand" "r")
5618 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5619 UNSPEC_GOTSMALLPIC))]
5621 "ldr\\t%<w>0, [%1, #:got_lo12:%c2]"
5622 [(set_attr "type" "load_<ldst_sz>")]
5625 (define_insn "ldr_got_small_sidi"
5626 [(set (match_operand:DI 0 "register_operand" "=r")
5628 (unspec:SI [(mem:SI (lo_sum:DI
5629 (match_operand:DI 1 "register_operand" "r")
5630 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5631 UNSPEC_GOTSMALLPIC)))]
5633 "ldr\\t%w0, [%1, #:got_lo12:%c2]"
5634 [(set_attr "type" "load_4")]
5637 (define_insn "ldr_got_small_28k_<mode>"
5638 [(set (match_operand:PTR 0 "register_operand" "=r")
5639 (unspec:PTR [(mem:PTR (lo_sum:PTR
5640 (match_operand:PTR 1 "register_operand" "r")
5641 (match_operand:PTR 2 "aarch64_valid_symref" "S")))]
5642 UNSPEC_GOTSMALLPIC28K))]
5644 "ldr\\t%<w>0, [%1, #:<got_modifier>:%c2]"
5645 [(set_attr "type" "load_<ldst_sz>")]
5648 (define_insn "ldr_got_small_28k_sidi"
5649 [(set (match_operand:DI 0 "register_operand" "=r")
5651 (unspec:SI [(mem:SI (lo_sum:DI
5652 (match_operand:DI 1 "register_operand" "r")
5653 (match_operand:DI 2 "aarch64_valid_symref" "S")))]
5654 UNSPEC_GOTSMALLPIC28K)))]
5656 "ldr\\t%w0, [%1, #:gotpage_lo14:%c2]"
5657 [(set_attr "type" "load_4")]
5660 (define_insn "ldr_got_tiny"
5661 [(set (match_operand:DI 0 "register_operand" "=r")
5662 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")]
5663 UNSPEC_GOTTINYPIC))]
5666 [(set_attr "type" "load_8")]
5669 (define_insn "aarch64_load_tp_hard"
5670 [(set (match_operand:DI 0 "register_operand" "=r")
5671 (unspec:DI [(const_int 0)] UNSPEC_TLS))]
5673 "mrs\\t%0, tpidr_el0"
5674 [(set_attr "type" "mrs")]
5677 ;; The TLS ABI specifically requires that the compiler does not schedule
5678 ;; instructions in the TLS stubs, in order to enable linker relaxation.
5679 ;; Therefore we treat the stubs as an atomic sequence.
5680 (define_expand "tlsgd_small_<mode>"
5681 [(parallel [(set (match_operand 0 "register_operand" "")
5682 (call (mem:DI (match_dup 2)) (const_int 1)))
5683 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
5684 (clobber (reg:DI LR_REGNUM))])]
5687 operands[2] = aarch64_tls_get_addr ();
5690 (define_insn "*tlsgd_small_<mode>"
5691 [(set (match_operand 0 "register_operand" "")
5692 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1)))
5693 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS)
5694 (clobber (reg:DI LR_REGNUM))
5697 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop"
5698 [(set_attr "type" "call")
5699 (set_attr "length" "16")])
5701 (define_insn "tlsie_small_<mode>"
5702 [(set (match_operand:PTR 0 "register_operand" "=r")
5703 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5704 UNSPEC_GOTSMALLTLS))]
5706 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]"
5707 [(set_attr "type" "load_4")
5708 (set_attr "length" "8")]
5711 (define_insn "tlsie_small_sidi"
5712 [(set (match_operand:DI 0 "register_operand" "=r")
5714 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")]
5715 UNSPEC_GOTSMALLTLS)))]
5717 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]"
5718 [(set_attr "type" "load_4")
5719 (set_attr "length" "8")]
5722 (define_insn "tlsie_tiny_<mode>"
5723 [(set (match_operand:PTR 0 "register_operand" "=&r")
5724 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")
5725 (match_operand:PTR 2 "register_operand" "r")]
5726 UNSPEC_GOTTINYTLS))]
5728 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2"
5729 [(set_attr "type" "multiple")
5730 (set_attr "length" "8")]
5733 (define_insn "tlsie_tiny_sidi"
5734 [(set (match_operand:DI 0 "register_operand" "=&r")
5736 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")
5737 (match_operand:DI 2 "register_operand" "r")
5739 UNSPEC_GOTTINYTLS)))]
5741 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2"
5742 [(set_attr "type" "multiple")
5743 (set_attr "length" "8")]
5746 (define_insn "tlsle12_<mode>"
5747 [(set (match_operand:P 0 "register_operand" "=r")
5748 (unspec:P [(match_operand:P 1 "register_operand" "r")
5749 (match_operand 2 "aarch64_tls_le_symref" "S")]
5752 "add\\t%<w>0, %<w>1, #%L2";
5753 [(set_attr "type" "alu_sreg")
5754 (set_attr "length" "4")]
5757 (define_insn "tlsle24_<mode>"
5758 [(set (match_operand:P 0 "register_operand" "=r")
5759 (unspec:P [(match_operand:P 1 "register_operand" "r")
5760 (match_operand 2 "aarch64_tls_le_symref" "S")]
5763 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2"
5764 [(set_attr "type" "multiple")
5765 (set_attr "length" "8")]
5768 (define_insn "tlsle32_<mode>"
5769 [(set (match_operand:P 0 "register_operand" "=r")
5770 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5773 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5774 [(set_attr "type" "multiple")
5775 (set_attr "length" "8")]
5778 (define_insn "tlsle48_<mode>"
5779 [(set (match_operand:P 0 "register_operand" "=r")
5780 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")]
5783 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1"
5784 [(set_attr "type" "multiple")
5785 (set_attr "length" "12")]
5788 (define_expand "tlsdesc_small_<mode>"
5789 [(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)]
5793 emit_insn (gen_tlsdesc_small_sve_<mode> (operands[0]));
5795 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0]));
5800 ;; tlsdesc calls preserve all core and Advanced SIMD registers except
5802 (define_insn "tlsdesc_small_advsimd_<mode>"
5803 [(set (reg:PTR R0_REGNUM)
5804 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5806 (clobber (reg:DI LR_REGNUM))
5807 (clobber (reg:CC CC_REGNUM))
5808 (clobber (match_scratch:DI 1 "=r"))]
5809 "TARGET_TLS_DESC && !TARGET_SVE"
5810 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5811 [(set_attr "type" "call")
5812 (set_attr "length" "16")])
5814 ;; For SVE, model tlsdesc calls as clobbering all vector and predicate
5815 ;; registers, on top of the usual R0 and LR. In reality the calls
5816 ;; preserve the low 128 bits of the vector registers, but we don't
5817 ;; yet have a way of representing that in the instruction pattern.
5818 (define_insn "tlsdesc_small_sve_<mode>"
5819 [(set (reg:PTR R0_REGNUM)
5820 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")]
5822 (clobber (reg:DI LR_REGNUM))
5823 (clobber (reg:CC CC_REGNUM))
5824 (clobber (reg:XI V0_REGNUM))
5825 (clobber (reg:XI V4_REGNUM))
5826 (clobber (reg:XI V8_REGNUM))
5827 (clobber (reg:XI V12_REGNUM))
5828 (clobber (reg:XI V16_REGNUM))
5829 (clobber (reg:XI V20_REGNUM))
5830 (clobber (reg:XI V24_REGNUM))
5831 (clobber (reg:XI V28_REGNUM))
5832 (clobber (reg:VNx2BI P0_REGNUM))
5833 (clobber (reg:VNx2BI P1_REGNUM))
5834 (clobber (reg:VNx2BI P2_REGNUM))
5835 (clobber (reg:VNx2BI P3_REGNUM))
5836 (clobber (reg:VNx2BI P4_REGNUM))
5837 (clobber (reg:VNx2BI P5_REGNUM))
5838 (clobber (reg:VNx2BI P6_REGNUM))
5839 (clobber (reg:VNx2BI P7_REGNUM))
5840 (clobber (reg:VNx2BI P8_REGNUM))
5841 (clobber (reg:VNx2BI P9_REGNUM))
5842 (clobber (reg:VNx2BI P10_REGNUM))
5843 (clobber (reg:VNx2BI P11_REGNUM))
5844 (clobber (reg:VNx2BI P12_REGNUM))
5845 (clobber (reg:VNx2BI P13_REGNUM))
5846 (clobber (reg:VNx2BI P14_REGNUM))
5847 (clobber (reg:VNx2BI P15_REGNUM))
5848 (clobber (match_scratch:DI 1 "=r"))]
5849 "TARGET_TLS_DESC && TARGET_SVE"
5850 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
5851 [(set_attr "type" "call")
5852 (set_attr "length" "16")])
5854 (define_insn "stack_tie"
5855 [(set (mem:BLK (scratch))
5856 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk")
5857 (match_operand:DI 1 "register_operand" "rk")]
5861 [(set_attr "length" "0")]
5864 ;; Pointer authentication patterns are always provided. In architecture
5865 ;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs.
5866 ;; This lets the user write portable software which authenticates pointers
5867 ;; when run on something which implements ARMv8.3-A, and which runs
5868 ;; correctly, but does not authenticate pointers, where ARMv8.3-A is not
5871 ;; Signing/Authenticating R30 using SP as the salt.
5873 (define_insn "<pauth_mnem_prefix>sp"
5874 [(set (reg:DI R30_REGNUM)
5875 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
5877 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
5880 ;; Signing/Authenticating X17 using X16 as the salt.
5882 (define_insn "<pauth_mnem_prefix>1716"
5883 [(set (reg:DI R17_REGNUM)
5884 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
5886 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
5889 ;; Stripping the signature in R30.
5891 (define_insn "xpaclri"
5892 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))]
5894 "hint\t7 // xpaclri"
5897 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5898 ;; all of memory. This blocks insns from being moved across this point.
5900 (define_insn "blockage"
5901 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
5904 [(set_attr "length" "0")
5905 (set_attr "type" "block")]
5908 (define_insn "probe_stack_range"
5909 [(set (match_operand:DI 0 "register_operand" "=r")
5910 (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")
5911 (match_operand:DI 2 "register_operand" "r")]
5912 UNSPECV_PROBE_STACK_RANGE))]
5915 return aarch64_output_probe_stack_range (operands[0], operands[2]);
5917 [(set_attr "length" "32")]
5920 ;; Named pattern for expanding thread pointer reference.
5921 (define_expand "get_thread_pointerdi"
5922 [(match_operand:DI 0 "register_operand" "=r")]
5925 rtx tmp = aarch64_load_tp (operands[0]);
5926 if (tmp != operands[0])
5927 emit_move_insn (operands[0], tmp);
5931 ;; Named patterns for stack smashing protection.
5932 (define_expand "stack_protect_set"
5933 [(match_operand 0 "memory_operand")
5934 (match_operand 1 "memory_operand")]
5937 machine_mode mode = GET_MODE (operands[0]);
5939 emit_insn ((mode == DImode
5940 ? gen_stack_protect_set_di
5941 : gen_stack_protect_set_si) (operands[0], operands[1]));
5945 (define_insn "stack_protect_set_<mode>"
5946 [(set (match_operand:PTR 0 "memory_operand" "=m")
5947 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
5949 (set (match_scratch:PTR 2 "=&r") (const_int 0))]
5951 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0"
5952 [(set_attr "length" "12")
5953 (set_attr "type" "multiple")])
5955 (define_expand "stack_protect_test"
5956 [(match_operand 0 "memory_operand")
5957 (match_operand 1 "memory_operand")
5962 machine_mode mode = GET_MODE (operands[0]);
5964 result = gen_reg_rtx(mode);
5966 emit_insn ((mode == DImode
5967 ? gen_stack_protect_test_di
5968 : gen_stack_protect_test_si) (result,
5973 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5974 result, const0_rtx, operands[2]));
5976 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx),
5977 result, const0_rtx, operands[2]));
5981 (define_insn "stack_protect_test_<mode>"
5982 [(set (match_operand:PTR 0 "register_operand" "=r")
5983 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")
5984 (match_operand:PTR 2 "memory_operand" "m")]
5986 (clobber (match_scratch:PTR 3 "=&r"))]
5988 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0"
5989 [(set_attr "length" "12")
5990 (set_attr "type" "multiple")])
5992 ;; Write Floating-point Control Register.
5993 (define_insn "set_fpcr"
5994 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)]
5997 [(set_attr "type" "mrs")])
5999 ;; Read Floating-point Control Register.
6000 (define_insn "get_fpcr"
6001 [(set (match_operand:SI 0 "register_operand" "=r")
6002 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))]
6005 [(set_attr "type" "mrs")])
6007 ;; Write Floating-point Status Register.
6008 (define_insn "set_fpsr"
6009 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)]
6012 [(set_attr "type" "mrs")])
6014 ;; Read Floating-point Status Register.
6015 (define_insn "get_fpsr"
6016 [(set (match_operand:SI 0 "register_operand" "=r")
6017 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))]
6020 [(set_attr "type" "mrs")])
6023 ;; Define the subtract-one-and-jump insns so loop.c
6024 ;; knows what to generate.
6025 (define_expand "doloop_end"
6026 [(use (match_operand 0 "" "")) ; loop pseudo
6027 (use (match_operand 1 "" ""))] ; label
6028 "optimize > 0 && flag_modulo_sched"
6037 /* Currently SMS relies on the do-loop pattern to recognize loops
6038 where (1) the control part consists of all insns defining and/or
6039 using a certain 'count' register and (2) the loop count can be
6040 adjusted by modifying this register prior to the loop.
6041 ??? The possible introduction of a new block to initialize the
6042 new IV can potentially affect branch optimizations. */
6044 if (GET_MODE (operands[0]) != DImode)
6048 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1)));
6050 cmp = XVECEXP (PATTERN (insn), 0, 0);
6051 cc_reg = SET_DEST (cmp);
6052 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
6053 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
6054 emit_jump_insn (gen_rtx_SET (pc_rtx,
6055 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
6060 ;; Helper for aarch64.c code.
6061 (define_expand "set_clobber_cc"
6062 [(parallel [(set (match_operand 0)
6064 (clobber (reg:CC CC_REGNUM))])])
6067 (include "aarch64-simd.md")
6069 ;; Atomic Operations
6070 (include "atomics.md")
6072 ;; ldp/stp peephole patterns
6073 (include "aarch64-ldpstp.md")
6076 (include "aarch64-sve.md")