1 ;; AArch64 ldp/stp peephole optimizations.
2 ;; Copyright (C) 2014-2017 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 "aarch64_mem_pair_operand" ""))
24 (set (match_operand:GPI 2 "register_operand" "")
25 (match_operand:GPI 3 "memory_operand" ""))]
26 "aarch64_operands_ok_for_ldpstp (operands, true, <MODE>mode)"
27 [(parallel [(set (match_dup 0) (match_dup 1))
28 (set (match_dup 2) (match_dup 3))])]
30 rtx base, offset_1, offset_2;
32 extract_base_offset_in_addr (operands[1], &base, &offset_1);
33 extract_base_offset_in_addr (operands[3], &base, &offset_2);
34 if (INTVAL (offset_1) > INTVAL (offset_2))
36 std::swap (operands[0], operands[2]);
37 std::swap (operands[1], operands[3]);
42 [(set (match_operand:GPI 0 "aarch64_mem_pair_operand" "")
43 (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
44 (set (match_operand:GPI 2 "memory_operand" "")
45 (match_operand:GPI 3 "aarch64_reg_or_zero" ""))]
46 "aarch64_operands_ok_for_ldpstp (operands, false, <MODE>mode)"
47 [(parallel [(set (match_dup 0) (match_dup 1))
48 (set (match_dup 2) (match_dup 3))])]
50 rtx base, offset_1, offset_2;
52 extract_base_offset_in_addr (operands[0], &base, &offset_1);
53 extract_base_offset_in_addr (operands[2], &base, &offset_2);
54 if (INTVAL (offset_1) > INTVAL (offset_2))
56 std::swap (operands[0], operands[2]);
57 std::swap (operands[1], operands[3]);
62 [(set (match_operand:GPF 0 "register_operand" "")
63 (match_operand:GPF 1 "aarch64_mem_pair_operand" ""))
64 (set (match_operand:GPF 2 "register_operand" "")
65 (match_operand:GPF 3 "memory_operand" ""))]
66 "aarch64_operands_ok_for_ldpstp (operands, true, <MODE>mode)"
67 [(parallel [(set (match_dup 0) (match_dup 1))
68 (set (match_dup 2) (match_dup 3))])]
70 rtx base, offset_1, offset_2;
72 extract_base_offset_in_addr (operands[1], &base, &offset_1);
73 extract_base_offset_in_addr (operands[3], &base, &offset_2);
74 if (INTVAL (offset_1) > INTVAL (offset_2))
76 std::swap (operands[0], operands[2]);
77 std::swap (operands[1], operands[3]);
82 [(set (match_operand:GPF 0 "aarch64_mem_pair_operand" "")
83 (match_operand:GPF 1 "aarch64_reg_or_fp_zero" ""))
84 (set (match_operand:GPF 2 "memory_operand" "")
85 (match_operand:GPF 3 "aarch64_reg_or_fp_zero" ""))]
86 "aarch64_operands_ok_for_ldpstp (operands, false, <MODE>mode)"
87 [(parallel [(set (match_dup 0) (match_dup 1))
88 (set (match_dup 2) (match_dup 3))])]
90 rtx base, offset_1, offset_2;
92 extract_base_offset_in_addr (operands[0], &base, &offset_1);
93 extract_base_offset_in_addr (operands[2], &base, &offset_2);
94 if (INTVAL (offset_1) > INTVAL (offset_2))
96 std::swap (operands[0], operands[2]);
97 std::swap (operands[1], operands[3]);
102 [(set (match_operand:VD 0 "register_operand" "")
103 (match_operand:VD 1 "aarch64_mem_pair_operand" ""))
104 (set (match_operand:VD 2 "register_operand" "")
105 (match_operand:VD 3 "memory_operand" ""))]
106 "aarch64_operands_ok_for_ldpstp (operands, true, <MODE>mode)"
107 [(parallel [(set (match_dup 0) (match_dup 1))
108 (set (match_dup 2) (match_dup 3))])]
110 rtx base, offset_1, offset_2;
112 extract_base_offset_in_addr (operands[1], &base, &offset_1);
113 extract_base_offset_in_addr (operands[3], &base, &offset_2);
114 if (INTVAL (offset_1) > INTVAL (offset_2))
116 std::swap (operands[0], operands[2]);
117 std::swap (operands[1], operands[3]);
122 [(set (match_operand:VD 0 "aarch64_mem_pair_operand" "")
123 (match_operand:VD 1 "register_operand" ""))
124 (set (match_operand:VD 2 "memory_operand" "")
125 (match_operand:VD 3 "register_operand" ""))]
126 "TARGET_SIMD && aarch64_operands_ok_for_ldpstp (operands, false, <MODE>mode)"
127 [(parallel [(set (match_dup 0) (match_dup 1))
128 (set (match_dup 2) (match_dup 3))])]
130 rtx base, offset_1, offset_2;
132 extract_base_offset_in_addr (operands[0], &base, &offset_1);
133 extract_base_offset_in_addr (operands[2], &base, &offset_2);
134 if (INTVAL (offset_1) > INTVAL (offset_2))
136 std::swap (operands[0], operands[2]);
137 std::swap (operands[1], operands[3]);
142 ;; Handle sign/zero extended consecutive load/store.
145 [(set (match_operand:DI 0 "register_operand" "")
146 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "")))
147 (set (match_operand:DI 2 "register_operand" "")
148 (sign_extend:DI (match_operand:SI 3 "memory_operand" "")))]
149 "aarch64_operands_ok_for_ldpstp (operands, true, SImode)"
150 [(parallel [(set (match_dup 0) (sign_extend:DI (match_dup 1)))
151 (set (match_dup 2) (sign_extend:DI (match_dup 3)))])]
153 rtx base, offset_1, offset_2;
155 extract_base_offset_in_addr (operands[1], &base, &offset_1);
156 extract_base_offset_in_addr (operands[3], &base, &offset_2);
157 if (INTVAL (offset_1) > INTVAL (offset_2))
159 std::swap (operands[0], operands[2]);
160 std::swap (operands[1], operands[3]);
165 [(set (match_operand:DI 0 "register_operand" "")
166 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "")))
167 (set (match_operand:DI 2 "register_operand" "")
168 (zero_extend:DI (match_operand:SI 3 "memory_operand" "")))]
169 "aarch64_operands_ok_for_ldpstp (operands, true, SImode)"
170 [(parallel [(set (match_dup 0) (zero_extend:DI (match_dup 1)))
171 (set (match_dup 2) (zero_extend:DI (match_dup 3)))])]
173 rtx base, offset_1, offset_2;
175 extract_base_offset_in_addr (operands[1], &base, &offset_1);
176 extract_base_offset_in_addr (operands[3], &base, &offset_2);
177 if (INTVAL (offset_1) > INTVAL (offset_2))
179 std::swap (operands[0], operands[2]);
180 std::swap (operands[1], operands[3]);
184 ;; Handle consecutive load/store whose offset is out of the range
185 ;; supported by ldp/ldpsw/stp. We firstly adjust offset in a scratch
186 ;; register, then merge them into ldp/ldpsw/stp by using the adjusted
190 [(match_scratch:DI 8 "r")
191 (set (match_operand:GPI 0 "register_operand" "")
192 (match_operand:GPI 1 "memory_operand" ""))
193 (set (match_operand:GPI 2 "register_operand" "")
194 (match_operand:GPI 3 "memory_operand" ""))
195 (set (match_operand:GPI 4 "register_operand" "")
196 (match_operand:GPI 5 "memory_operand" ""))
197 (set (match_operand:GPI 6 "register_operand" "")
198 (match_operand:GPI 7 "memory_operand" ""))
200 "aarch64_operands_adjust_ok_for_ldpstp (operands, true, <MODE>mode)"
203 rtx base, offset_1, offset_2;
205 extract_base_offset_in_addr (operands[1], &base, &offset_1);
206 extract_base_offset_in_addr (operands[3], &base, &offset_2);
207 if (INTVAL (offset_1) > INTVAL (offset_2))
209 std::swap (operands[0], operands[6]);
210 std::swap (operands[1], operands[7]);
211 std::swap (operands[2], operands[4]);
212 std::swap (operands[3], operands[5]);
215 if (aarch64_gen_adjusted_ldpstp (operands, true, <MODE>mode, UNKNOWN))
222 [(match_scratch:DI 8 "r")
223 (set (match_operand:GPF 0 "register_operand" "")
224 (match_operand:GPF 1 "memory_operand" ""))
225 (set (match_operand:GPF 2 "register_operand" "")
226 (match_operand:GPF 3 "memory_operand" ""))
227 (set (match_operand:GPF 4 "register_operand" "")
228 (match_operand:GPF 5 "memory_operand" ""))
229 (set (match_operand:GPF 6 "register_operand" "")
230 (match_operand:GPF 7 "memory_operand" ""))
232 "aarch64_operands_adjust_ok_for_ldpstp (operands, true, <MODE>mode)"
235 rtx base, offset_1, offset_2;
237 extract_base_offset_in_addr (operands[1], &base, &offset_1);
238 extract_base_offset_in_addr (operands[3], &base, &offset_2);
239 if (INTVAL (offset_1) > INTVAL (offset_2))
241 std::swap (operands[0], operands[6]);
242 std::swap (operands[1], operands[7]);
243 std::swap (operands[2], operands[4]);
244 std::swap (operands[3], operands[5]);
247 if (aarch64_gen_adjusted_ldpstp (operands, true, <MODE>mode, UNKNOWN))
254 [(match_scratch:DI 8 "r")
255 (set (match_operand:DI 0 "register_operand" "")
256 (sign_extend:DI (match_operand:SI 1 "memory_operand" "")))
257 (set (match_operand:DI 2 "register_operand" "")
258 (sign_extend:DI (match_operand:SI 3 "memory_operand" "")))
259 (set (match_operand:DI 4 "register_operand" "")
260 (sign_extend:DI (match_operand:SI 5 "memory_operand" "")))
261 (set (match_operand:DI 6 "register_operand" "")
262 (sign_extend:DI (match_operand:SI 7 "memory_operand" "")))
264 "aarch64_operands_adjust_ok_for_ldpstp (operands, true, SImode)"
267 rtx base, offset_1, offset_2;
269 extract_base_offset_in_addr (operands[1], &base, &offset_1);
270 extract_base_offset_in_addr (operands[3], &base, &offset_2);
271 if (INTVAL (offset_1) > INTVAL (offset_2))
273 std::swap (operands[0], operands[6]);
274 std::swap (operands[1], operands[7]);
275 std::swap (operands[2], operands[4]);
276 std::swap (operands[3], operands[5]);
279 if (aarch64_gen_adjusted_ldpstp (operands, true, SImode, SIGN_EXTEND))
286 [(match_scratch:DI 8 "r")
287 (set (match_operand:DI 0 "register_operand" "")
288 (zero_extend:DI (match_operand:SI 1 "memory_operand" "")))
289 (set (match_operand:DI 2 "register_operand" "")
290 (zero_extend:DI (match_operand:SI 3 "memory_operand" "")))
291 (set (match_operand:DI 4 "register_operand" "")
292 (zero_extend:DI (match_operand:SI 5 "memory_operand" "")))
293 (set (match_operand:DI 6 "register_operand" "")
294 (zero_extend:DI (match_operand:SI 7 "memory_operand" "")))
296 "aarch64_operands_adjust_ok_for_ldpstp (operands, true, SImode)"
299 rtx base, offset_1, offset_2;
301 extract_base_offset_in_addr (operands[1], &base, &offset_1);
302 extract_base_offset_in_addr (operands[3], &base, &offset_2);
303 if (INTVAL (offset_1) > INTVAL (offset_2))
305 std::swap (operands[0], operands[6]);
306 std::swap (operands[1], operands[7]);
307 std::swap (operands[2], operands[4]);
308 std::swap (operands[3], operands[5]);
311 if (aarch64_gen_adjusted_ldpstp (operands, true, SImode, ZERO_EXTEND))
318 [(match_scratch:DI 8 "r")
319 (set (match_operand:GPI 0 "memory_operand" "")
320 (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
321 (set (match_operand:GPI 2 "memory_operand" "")
322 (match_operand:GPI 3 "aarch64_reg_or_zero" ""))
323 (set (match_operand:GPI 4 "memory_operand" "")
324 (match_operand:GPI 5 "aarch64_reg_or_zero" ""))
325 (set (match_operand:GPI 6 "memory_operand" "")
326 (match_operand:GPI 7 "aarch64_reg_or_zero" ""))
328 "aarch64_operands_adjust_ok_for_ldpstp (operands, false, <MODE>mode)"
331 rtx base, offset_1, offset_2;
333 extract_base_offset_in_addr (operands[0], &base, &offset_1);
334 extract_base_offset_in_addr (operands[2], &base, &offset_2);
335 if (INTVAL (offset_1) > INTVAL (offset_2))
337 std::swap (operands[0], operands[6]);
338 std::swap (operands[1], operands[7]);
339 std::swap (operands[2], operands[4]);
340 std::swap (operands[3], operands[5]);
343 if (aarch64_gen_adjusted_ldpstp (operands, false, <MODE>mode, UNKNOWN))
350 [(match_scratch:DI 8 "r")
351 (set (match_operand:GPF 0 "memory_operand" "")
352 (match_operand:GPF 1 "aarch64_reg_or_fp_zero" ""))
353 (set (match_operand:GPF 2 "memory_operand" "")
354 (match_operand:GPF 3 "aarch64_reg_or_fp_zero" ""))
355 (set (match_operand:GPF 4 "memory_operand" "")
356 (match_operand:GPF 5 "aarch64_reg_or_fp_zero" ""))
357 (set (match_operand:GPF 6 "memory_operand" "")
358 (match_operand:GPF 7 "aarch64_reg_or_fp_zero" ""))
360 "aarch64_operands_adjust_ok_for_ldpstp (operands, false, <MODE>mode)"
363 rtx base, offset_1, offset_2;
365 extract_base_offset_in_addr (operands[0], &base, &offset_1);
366 extract_base_offset_in_addr (operands[2], &base, &offset_2);
367 if (INTVAL (offset_1) > INTVAL (offset_2))
369 std::swap (operands[0], operands[6]);
370 std::swap (operands[1], operands[7]);
371 std::swap (operands[2], operands[4]);
372 std::swap (operands[3], operands[5]);
375 if (aarch64_gen_adjusted_ldpstp (operands, false, <MODE>mode, UNKNOWN))