middle-end/111821 - compile-time/memory-hog with large copy
[official-gcc.git] / gcc / config / arm / ldrdstrd.md
blob9d3c9a0eb5cfd180b43cabce2dfd51f7af07d0e1
1 ;; ARM ldrd/strd peephole optimizations.
2 ;;
3 ;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
4 ;;
5 ;; Written by Greta Yorsh <greta.yorsh@arm.com>
7 ;; This file is part of GCC.
8 ;;
9 ;; GCC is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; any later version.
14 ;; GCC is distributed in the hope that it will be useful, but
15 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ;; General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3.  If not see
21 ;; <http://www.gnu.org/licenses/>.
23 ;; The following peephole optimizations identify consecutive memory
24 ;; accesses, and try to rearrange the operands to enable generation of
25 ;; ldrd/strd.
27 ;; In many cases they behave in the same way that patterns in ldmstm.md behave,
28 ;; but there is extra logic in gen_operands_ldrd_strd to try and ensure the
29 ;; registers used are an (r<N>, r<N + 1>) pair where N is even.
31 (define_peephole2 ; ldrd
32   [(set (match_operand:SI 0 "arm_general_register_operand" "")
33         (match_operand:SI 2 "memory_operand" ""))
34    (set (match_operand:SI 1 "arm_general_register_operand" "")
35         (match_operand:SI 3 "memory_operand" ""))]
36   "TARGET_LDRD"
37   [(parallel [(set (match_dup 0) (match_dup 2))
38               (set (match_dup 1) (match_dup 3))])]
40   if (!gen_operands_ldrd_strd (operands, true, false, false))
41     FAIL;
44 (define_peephole2 ; strd
45   [(set (match_operand:SI 2 "memory_operand" "")
46         (match_operand:SI 0 "arm_general_register_operand" ""))
47    (set (match_operand:SI 3 "memory_operand" "")
48         (match_operand:SI 1 "arm_general_register_operand" ""))]
49   "TARGET_LDRD"
50   [(parallel [(set (match_dup 2) (match_dup 0))
51               (set (match_dup 3) (match_dup 1))])]
53   if (!gen_operands_ldrd_strd (operands, false, false, false))
54     FAIL;
57 ;; The following peepholes reorder registers to enable LDRD/STRD.
58 (define_peephole2 ; strd of constants
59   [(set (match_operand:SI 0 "arm_general_register_operand" "")
60         (match_operand:SI 4 "const_int_operand" ""))
61    (set (match_operand:SI 2 "memory_operand" "")
62         (match_dup 0))
63    (set (match_operand:SI 1 "arm_general_register_operand" "")
64         (match_operand:SI 5 "const_int_operand" ""))
65    (set (match_operand:SI 3 "memory_operand" "")
66         (match_dup 1))]
67   "TARGET_LDRD"
68   [(set (match_dup 0) (match_dup 4))
69    (set (match_dup 1) (match_dup 5))
70    (parallel [(set (match_dup 2) (match_dup 0))
71               (set (match_dup 3) (match_dup 1))])]
73   if (!gen_operands_ldrd_strd (operands, false, true, false))
74     FAIL;
77 (define_peephole2 ; strd of constants
78   [(set (match_operand:SI 0 "arm_general_register_operand" "")
79         (match_operand:SI 4 "const_int_operand" ""))
80    (set (match_operand:SI 1 "arm_general_register_operand" "")
81         (match_operand:SI 5 "const_int_operand" ""))
82    (set (match_operand:SI 2 "memory_operand" "")
83         (match_dup 0))
84    (set (match_operand:SI 3 "memory_operand" "")
85         (match_dup 1))]
86   "TARGET_LDRD"
87   [(set (match_dup 0) (match_dup 4))
88    (set (match_dup 1) (match_dup 5))
89    (parallel [(set (match_dup 2) (match_dup 0))
90               (set (match_dup 3) (match_dup 1))])]
92   if (!gen_operands_ldrd_strd (operands, false, true, false))
93      FAIL;
96 ;; The following two peephole optimizations are only relevant for ARM
97 ;; mode where LDRD/STRD require consecutive registers.
99 (define_peephole2 ; swap the destination registers of two loads
100                   ; before a commutative operation.
101   [(set (match_operand:SI 0 "arm_general_register_operand" "")
102         (match_operand:SI 2 "memory_operand" ""))
103    (set (match_operand:SI 1 "arm_general_register_operand" "")
104         (match_operand:SI 3 "memory_operand" ""))
105    (set (match_operand:SI 4 "arm_general_register_operand" "")
106         (match_operator:SI 5 "commutative_binary_operator"
107                            [(match_operand 6 "arm_general_register_operand" "")
108                             (match_operand 7 "arm_general_register_operand" "") ]))]
109   "TARGET_LDRD && TARGET_ARM
110    && (  ((rtx_equal_p(operands[0], operands[6])) && (rtx_equal_p(operands[1], operands[7])))
111         ||((rtx_equal_p(operands[0], operands[7])) && (rtx_equal_p(operands[1], operands[6]))))
112    && (peep2_reg_dead_p (3, operands[0]) || rtx_equal_p (operands[0], operands[4]))
113    && (peep2_reg_dead_p (3, operands[1]) || rtx_equal_p (operands[1], operands[4]))"
114   [(parallel [(set (match_dup 0) (match_dup 2))
115               (set (match_dup 1) (match_dup 3))])
116    (set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))]
118   if (!gen_operands_ldrd_strd (operands, true, false, true))
119     FAIL;
122 (define_peephole2 ; swap the destination registers of two loads
123                   ; before a commutative operation that sets the flags.
124   [(set (match_operand:SI 0 "arm_general_register_operand" "")
125         (match_operand:SI 2 "memory_operand" ""))
126    (set (match_operand:SI 1 "arm_general_register_operand" "")
127         (match_operand:SI 3 "memory_operand" ""))
128    (parallel
129       [(set (match_operand:SI 4 "arm_general_register_operand" "")
130             (match_operator:SI 5 "commutative_binary_operator"
131                                [(match_operand 6 "arm_general_register_operand" "")
132                                 (match_operand 7 "arm_general_register_operand" "") ]))
133        (clobber (reg:CC CC_REGNUM))])]
134   "TARGET_LDRD && TARGET_ARM
135    && (  ((rtx_equal_p(operands[0], operands[6])) && (rtx_equal_p(operands[1], operands[7])))
136        ||((rtx_equal_p(operands[0], operands[7])) && (rtx_equal_p(operands[1], operands[6]))))
137    && (peep2_reg_dead_p (3, operands[0]) || rtx_equal_p (operands[0], operands[4]))
138    && (peep2_reg_dead_p (3, operands[1]) || rtx_equal_p (operands[1], operands[4]))"
139   [(parallel [(set (match_dup 0) (match_dup 2))
140               (set (match_dup 1) (match_dup 3))])
141    (parallel
142       [(set (match_dup 4)
143             (match_op_dup 5 [(match_dup 6) (match_dup 7)]))
144        (clobber (reg:CC CC_REGNUM))])]
146   if (!gen_operands_ldrd_strd (operands, true, false, true))
147     FAIL;
150 ;; TODO: Handle LDRD/STRD with writeback:
151 ;; (a) memory operands can be POST_INC, POST_DEC, PRE_MODIFY, POST_MODIFY
152 ;; (b) Patterns may be followed by an update of the base address.
155 ;; insns matching the LDRD/STRD patterns that will get created by the above
156 ;; peepholes.
157 ;; We use gen_operands_ldrd_strd() with a modify argument as false so that the
158 ;; operands are not changed.
159 (define_insn "*arm_ldrd"
160   [(parallel [(set (match_operand:SI 0 "s_register_operand" "=r")
161                    (match_operand:SI 2 "memory_operand" "m"))
162               (set (match_operand:SI 1 "s_register_operand" "=rk")
163                    (match_operand:SI 3 "memory_operand" "m"))])]
164   "TARGET_LDRD && TARGET_ARM && reload_completed
165   && valid_operands_ldrd_strd (operands, true)"
166   {
167     rtx op[2];
168     op[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
169     op[1] = adjust_address (operands[2], DImode, 0);
170     return output_move_double (op, true, NULL);
171   }
172   [(set (attr "length")
173         (symbol_ref "arm_count_ldrdstrd_insns (operands, true) * 4"))
174    (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4"))
175    (set_attr "type" "load_8")
176    (set_attr "predicable" "yes")]
179 (define_insn "*arm_strd"
180   [(parallel [(set (match_operand:SI 2 "memory_operand" "=m")
181                    (match_operand:SI 0 "s_register_operand" "r"))
182               (set (match_operand:SI 3 "memory_operand" "=m")
183                    (match_operand:SI 1 "s_register_operand" "rk"))])]
184   "TARGET_LDRD && TARGET_ARM && reload_completed
185   && valid_operands_ldrd_strd (operands, false)"
186   {
187     rtx op[2];
188     op[0] = adjust_address (operands[2], DImode, 0);
189     op[1] = gen_rtx_REG (DImode, REGNO (operands[0]));
190     return output_move_double (op, true, NULL);
191   }
192   [(set (attr "length")
193         (symbol_ref "arm_count_ldrdstrd_insns (operands, false) * 4"))
194    (set (attr "ce_count") (symbol_ref "get_attr_length (insn) / 4"))
195    (set_attr "type" "store_8")
196    (set_attr "predicable" "yes")]