1 ;; AArch64 ldp/stp peephole optimizations.
2 ;; Copyright (C) 2014-2025 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/>.
22 [(set (match_operand:GPI 0 "register_operand" "")
23 (match_operand:GPI 1 "memory_operand" ""))
24 (set (match_operand:GPI 2 "register_operand" "")
25 (match_operand:GPI 3 "memory_operand" ""))]
26 "aarch64_operands_ok_for_ldpstp (operands, true)"
29 aarch64_finish_ldpstp_peephole (operands, true);
34 [(set (match_operand:GPI 0 "memory_operand" "")
35 (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
36 (set (match_operand:GPI 2 "memory_operand" "")
37 (match_operand:GPI 3 "aarch64_reg_or_zero" ""))]
38 "aarch64_operands_ok_for_ldpstp (operands, false)"
41 aarch64_finish_ldpstp_peephole (operands, false);
46 [(set (match_operand:GPF 0 "register_operand" "")
47 (match_operand:GPF 1 "memory_operand" ""))
48 (set (match_operand:GPF 2 "register_operand" "")
49 (match_operand:GPF 3 "memory_operand" ""))]
50 "aarch64_operands_ok_for_ldpstp (operands, true)"
53 aarch64_finish_ldpstp_peephole (operands, true);
58 [(set (match_operand:GPF 0 "memory_operand" "")
59 (match_operand:GPF 1 "aarch64_reg_or_fp_zero" ""))
60 (set (match_operand:GPF 2 "memory_operand" "")
61 (match_operand:GPF 3 "aarch64_reg_or_fp_zero" ""))]
62 "aarch64_operands_ok_for_ldpstp (operands, false)"
65 aarch64_finish_ldpstp_peephole (operands, false);
70 [(set (match_operand:DREG 0 "register_operand" "")
71 (match_operand:DREG 1 "memory_operand" ""))
72 (set (match_operand:DREG2 2 "register_operand" "")
73 (match_operand:DREG2 3 "memory_operand" ""))]
74 "aarch64_operands_ok_for_ldpstp (operands, true)"
77 aarch64_finish_ldpstp_peephole (operands, true);
82 [(set (match_operand:DREG 0 "memory_operand" "")
83 (match_operand:DREG 1 "register_operand" ""))
84 (set (match_operand:DREG2 2 "memory_operand" "")
85 (match_operand:DREG2 3 "register_operand" ""))]
86 "aarch64_operands_ok_for_ldpstp (operands, false)"
89 aarch64_finish_ldpstp_peephole (operands, false);
94 [(set (match_operand:VQ 0 "register_operand" "")
95 (match_operand:VQ 1 "memory_operand" ""))
96 (set (match_operand:VQ2 2 "register_operand" "")
97 (match_operand:VQ2 3 "memory_operand" ""))]
99 && aarch64_operands_ok_for_ldpstp (operands, true)"
102 aarch64_finish_ldpstp_peephole (operands, true);
107 [(set (match_operand:VQ 0 "memory_operand" "")
108 (match_operand:VQ 1 "register_operand" ""))
109 (set (match_operand:VQ2 2 "memory_operand" "")
110 (match_operand:VQ2 3 "register_operand" ""))]
112 && aarch64_operands_ok_for_ldpstp (operands, false)"
115 aarch64_finish_ldpstp_peephole (operands, false);
120 ;; Handle sign/zero extended consecutive load/store.
123 [(set (match_operand:DI 0 "register_operand" "")
124 (sign_extend:DI (match_operand:SI 1 "memory_operand" "")))
125 (set (match_operand:DI 2 "register_operand" "")
126 (sign_extend:DI (match_operand:SI 3 "memory_operand" "")))]
127 "aarch64_operands_ok_for_ldpstp (operands, true)"
130 aarch64_finish_ldpstp_peephole (operands, true, SIGN_EXTEND);
135 [(set (match_operand:DI 0 "register_operand" "")
136 (zero_extend:DI (match_operand:SI 1 "memory_operand" "")))
137 (set (match_operand:DI 2 "register_operand" "")
138 (zero_extend:DI (match_operand:SI 3 "memory_operand" "")))]
139 "aarch64_operands_ok_for_ldpstp (operands, true)"
142 aarch64_finish_ldpstp_peephole (operands, true, ZERO_EXTEND);
146 ;; Handle storing of a floating point zero with integer data.
147 ;; This handles cases like:
148 ;; struct pair { int a; float b; }
153 ;; We can match modes that won't work for a stp instruction
154 ;; as aarch64_operands_ok_for_ldpstp checks that the modes are
157 [(set (match_operand:DSX 0 "memory_operand" "")
158 (match_operand:DSX 1 "aarch64_reg_zero_or_fp_zero" ""))
159 (set (match_operand:<FCVT_TARGET> 2 "memory_operand" "")
160 (match_operand:<FCVT_TARGET> 3 "aarch64_reg_zero_or_fp_zero" ""))]
161 "aarch64_operands_ok_for_ldpstp (operands, false)"
164 aarch64_finish_ldpstp_peephole (operands, false);
168 ;; Handle consecutive load/store whose offset is out of the range
169 ;; supported by ldp/ldpsw/stp. We firstly adjust offset in a scratch
170 ;; register, then merge them into ldp/ldpsw/stp by using the adjusted
174 [(match_scratch:DI 8 "r")
175 (set (match_operand:GPI 0 "register_operand" "")
176 (match_operand:GPI 1 "memory_operand" ""))
177 (set (match_operand:GPI 2 "register_operand" "")
178 (match_operand:GPI 3 "memory_operand" ""))
179 (set (match_operand:GPI 4 "register_operand" "")
180 (match_operand:GPI 5 "memory_operand" ""))
181 (set (match_operand:GPI 6 "register_operand" "")
182 (match_operand:GPI 7 "memory_operand" ""))
184 "aarch64_operands_adjust_ok_for_ldpstp (operands, true, <MODE>mode)"
187 if (aarch64_gen_adjusted_ldpstp (operands, true, <MODE>mode, UNKNOWN))
194 [(match_scratch:DI 8 "r")
195 (set (match_operand:GPF 0 "register_operand" "")
196 (match_operand:GPF 1 "memory_operand" ""))
197 (set (match_operand:GPF 2 "register_operand" "")
198 (match_operand:GPF 3 "memory_operand" ""))
199 (set (match_operand:GPF 4 "register_operand" "")
200 (match_operand:GPF 5 "memory_operand" ""))
201 (set (match_operand:GPF 6 "register_operand" "")
202 (match_operand:GPF 7 "memory_operand" ""))
204 "aarch64_operands_adjust_ok_for_ldpstp (operands, true, <MODE>mode)"
207 if (aarch64_gen_adjusted_ldpstp (operands, true, <MODE>mode, UNKNOWN))
214 [(match_scratch:DI 8 "r")
215 (set (match_operand:DI 0 "register_operand" "")
216 (sign_extend:DI (match_operand:SI 1 "memory_operand" "")))
217 (set (match_operand:DI 2 "register_operand" "")
218 (sign_extend:DI (match_operand:SI 3 "memory_operand" "")))
219 (set (match_operand:DI 4 "register_operand" "")
220 (sign_extend:DI (match_operand:SI 5 "memory_operand" "")))
221 (set (match_operand:DI 6 "register_operand" "")
222 (sign_extend:DI (match_operand:SI 7 "memory_operand" "")))
224 "aarch64_operands_adjust_ok_for_ldpstp (operands, true, SImode)"
227 if (aarch64_gen_adjusted_ldpstp (operands, true, SImode, SIGN_EXTEND))
234 [(match_scratch:DI 8 "r")
235 (set (match_operand:DI 0 "register_operand" "")
236 (zero_extend:DI (match_operand:SI 1 "memory_operand" "")))
237 (set (match_operand:DI 2 "register_operand" "")
238 (zero_extend:DI (match_operand:SI 3 "memory_operand" "")))
239 (set (match_operand:DI 4 "register_operand" "")
240 (zero_extend:DI (match_operand:SI 5 "memory_operand" "")))
241 (set (match_operand:DI 6 "register_operand" "")
242 (zero_extend:DI (match_operand:SI 7 "memory_operand" "")))
244 "aarch64_operands_adjust_ok_for_ldpstp (operands, true, SImode)"
247 if (aarch64_gen_adjusted_ldpstp (operands, true, SImode, ZERO_EXTEND))
254 [(match_scratch:DI 8 "r")
255 (set (match_operand:GPI 0 "memory_operand" "")
256 (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
257 (set (match_operand:GPI 2 "memory_operand" "")
258 (match_operand:GPI 3 "aarch64_reg_or_zero" ""))
259 (set (match_operand:GPI 4 "memory_operand" "")
260 (match_operand:GPI 5 "aarch64_reg_or_zero" ""))
261 (set (match_operand:GPI 6 "memory_operand" "")
262 (match_operand:GPI 7 "aarch64_reg_or_zero" ""))
264 "aarch64_operands_adjust_ok_for_ldpstp (operands, false, <MODE>mode)"
267 if (aarch64_gen_adjusted_ldpstp (operands, false, <MODE>mode, UNKNOWN))
274 [(match_scratch:DI 8 "r")
275 (set (match_operand:GPF 0 "memory_operand" "")
276 (match_operand:GPF 1 "aarch64_reg_or_fp_zero" ""))
277 (set (match_operand:GPF 2 "memory_operand" "")
278 (match_operand:GPF 3 "aarch64_reg_or_fp_zero" ""))
279 (set (match_operand:GPF 4 "memory_operand" "")
280 (match_operand:GPF 5 "aarch64_reg_or_fp_zero" ""))
281 (set (match_operand:GPF 6 "memory_operand" "")
282 (match_operand:GPF 7 "aarch64_reg_or_fp_zero" ""))
284 "aarch64_operands_adjust_ok_for_ldpstp (operands, false, <MODE>mode)"
287 if (aarch64_gen_adjusted_ldpstp (operands, false, <MODE>mode, UNKNOWN))
294 [(match_scratch:DI 8 "r")
295 (set (match_operand:VP_2E 0 "memory_operand" "")
296 (match_operand:VP_2E 1 "aarch64_reg_or_zero" ""))
297 (set (match_operand:VP_2E 2 "memory_operand" "")
298 (match_operand:VP_2E 3 "aarch64_reg_or_zero" ""))
299 (set (match_operand:VP_2E 4 "memory_operand" "")
300 (match_operand:VP_2E 5 "aarch64_reg_or_zero" ""))
301 (set (match_operand:VP_2E 6 "memory_operand" "")
302 (match_operand:VP_2E 7 "aarch64_reg_or_zero" ""))
305 && aarch64_operands_adjust_ok_for_ldpstp (operands, false, <MODE>mode)"
308 if (aarch64_gen_adjusted_ldpstp (operands, false, <MODE>mode, UNKNOWN))
315 [(match_scratch:DI 8 "r")
316 (set (match_operand:VP_2E 0 "register_operand" "")
317 (match_operand:VP_2E 1 "memory_operand" ""))
318 (set (match_operand:VP_2E 2 "register_operand" "")
319 (match_operand:VP_2E 3 "memory_operand" ""))
320 (set (match_operand:VP_2E 4 "register_operand" "")
321 (match_operand:VP_2E 5 "memory_operand" ""))
322 (set (match_operand:VP_2E 6 "register_operand" "")
323 (match_operand:VP_2E 7 "memory_operand" ""))
326 && aarch64_operands_adjust_ok_for_ldpstp (operands, true, <MODE>mode)"
329 if (aarch64_gen_adjusted_ldpstp (operands, true, <MODE>mode, UNKNOWN))