[RISC-V] Avoid unnecessary extensions when value is already extended
[official-gcc.git] / gcc / testsuite / gcc.dg / rtl / arm / ldrd-peepholes.c
blobcbb64a770f5d796250601cafe481d7c2ea13f2eb
1 /* { dg-do compile { target arm*-*-* } } */
2 /* { dg-require-effective-target arm_arm_ok } */
3 /* { dg-require-effective-target arm_ldrd_strd_ok } */
4 /* { dg-skip-if "Ensure only targetting arm with TARGET_LDRD" { *-*-* } { "-mthumb" } { "" } } */
5 /* { dg-options "-O3 -marm -fdump-rtl-peephole2" } */
7 /*
8 Test file contains testcases that are there to check.
9 1) Each peephole generates the expected patterns.
10 2) These patterns match the expected define_insns and generate ldrd/strd.
11 2) Memory alias information is not lost in the peephole transformation.
13 I don't check the peephole pass on most of the functions here but just check
14 the correct assembly is output. The ldrd/strd peepholes only generate a
15 different pattern to the ldm/stm peepholes in some specific cases, and those
16 are checked.
18 The exceptions are tested by the crafted testcases at the end of this file
19 that are named in the pattern foo_x[[:digit:]].
21 The first testcase (foo_mem_11) demonstrates bug 88714 is fixed by checking
22 that both alias sets in the RTL are preserved.
24 All other testcases are only checked to see that they generate a LDRD or
25 STRD instruction accordingly.
29 /* Example of bugzilla 88714 -- memory aliasing info needs to be retained. */
30 int __RTL (startwith ("peephole2")) foo_mem_11 (int *a, int *b)
32 (function "foo_mem_11"
33 (insn-chain
34 (cnote 1 NOTE_INSN_DELETED)
35 (block 2
36 (edge-from entry (flags "FALLTHRU"))
37 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
38 (cinsn 101 (set (reg:SI r2)
39 (mem/c:SI (reg:SI r0) [1 S4 A64])) "/home/matmal01/test.c":18)
40 (cinsn 102 (set (reg:SI r3)
41 (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [2 S4 A32])) "/home/matmal01/test.c":18)
42 (cinsn 103 (set (reg:SI r0)
43 (plus:SI (reg:SI r2) (reg:SI r3))) "/home/matmal01/test.c":18)
44 (edge-to exit (flags "FALLTHRU"))
45 ) ;; block 2
46 ) ;; insn-chain
47 (crtl
48 (return_rtx
49 (reg/i:SI r0)
50 ) ;; return_rtx
51 ) ;; crtl
52 ) ;; function "main"
54 /* { dg-final { scan-rtl-dump {Function foo_mem_11.*\(mem/c:SI[^\n]*\[1.*\(mem/c:SI[^\n]*\n[^\n]*\[2.*Function foo11} "peephole2" } } */
56 /* ldrd plain peephole2. */
57 int __RTL (startwith ("peephole2")) foo11 (int *a)
59 (function "foo11"
60 (insn-chain
61 (cnote 1 NOTE_INSN_DELETED)
62 (block 2
63 (edge-from entry (flags "FALLTHRU"))
64 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
65 (cinsn 101 (set (reg:SI r2)
66 (mem/c:SI (reg:SI r0) [0 S4 A64])) "/home/matmal01/test.c":18)
67 (cinsn 102 (set (reg:SI r3)
68 (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])) "/home/matmal01/test.c":18)
69 (cinsn 103 (set (reg:SI r0)
70 (plus:SI (reg:SI r2) (reg:SI r3))) "/home/matmal01/test.c":18)
71 (edge-to exit (flags "FALLTHRU"))
72 ) ;; block 2
73 ) ;; insn-chain
74 (crtl
75 (return_rtx
76 (reg/i:SI r0)
77 ) ;; return_rtx
78 ) ;; crtl
79 ) ;; function "main"
82 /* ldrd plain peephole2, which accepts insns initially out of order. */
83 int __RTL (startwith ("peephole2")) foo11_alt (int *a)
85 (function "foo11_alt"
86 (insn-chain
87 (cnote 1 NOTE_INSN_DELETED)
88 (block 2
89 (edge-from entry (flags "FALLTHRU"))
90 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
91 (cinsn 102 (set (reg:SI r3)
92 (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])) "/home/matmal01/test.c":18)
93 (cinsn 101 (set (reg:SI r2)
94 (mem/c:SI (reg:SI r0) [0 S4 A64])) "/home/matmal01/test.c":18)
95 (cinsn 103 (set (reg:SI r0)
96 (plus:SI (reg:SI r2) (reg:SI r3))) "/home/matmal01/test.c":18)
97 (edge-to exit (flags "FALLTHRU"))
98 ) ;; block 2
99 ) ;; insn-chain
100 (crtl
101 (return_rtx
102 (reg/i:SI r0)
103 ) ;; return_rtx
104 ) ;; crtl
105 ) ;; function "main"
108 /* strd plain peephole2. */
109 int __RTL (startwith ("peephole2")) foo12 (int *a)
111 (function "foo12"
112 (insn-chain
113 (cnote 1 NOTE_INSN_DELETED)
114 (block 2
115 (edge-from entry (flags "FALLTHRU"))
116 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
117 (cinsn 101 (set (mem/c:SI (reg:SI r0) [0 S4 A64])
118 (reg:SI r2)) "/home/matmal01/test.c":18)
119 (cinsn 102 (set (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])
120 (reg:SI r3)) "/home/matmal01/test.c":18)
121 (edge-to exit (flags "FALLTHRU"))
122 ) ;; block 2
123 ) ;; insn-chain
124 (crtl
125 (return_rtx
126 (reg/i:SI r0)
127 ) ;; return_rtx
128 ) ;; crtl
129 ) ;; function "main"
132 /* strd of constants -- store interleaved with constant move into register.
133 Use same register twice to ensure we use the relevant pattern. */
134 int __RTL (startwith ("peephole2")) foo13 (int *a)
136 (function "foo13"
137 (insn-chain
138 (cnote 1 NOTE_INSN_DELETED)
139 (block 2
140 (edge-from entry (flags "FALLTHRU"))
141 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
142 (cinsn 99 (set (reg:SI r2)
143 (const_int 1)) "/home/matmal01/test.c":18)
144 (cinsn 101 (set (mem/c:SI (reg:SI r0) [0 S4 A64])
145 (reg:SI r2)) "/home/matmal01/test.c":18)
146 (cinsn 100 (set (reg:SI r2)
147 (const_int 0)) "/home/matmal01/test.c":18)
148 (cinsn 102 (set (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])
149 (reg:SI r2)) "/home/matmal01/test.c":18)
150 (edge-to exit (flags "FALLTHRU"))
151 ) ;; block 2
152 ) ;; insn-chain
153 (crtl
154 (return_rtx
155 (reg/i:SI r0)
156 ) ;; return_rtx
157 ) ;; crtl
158 ) ;; function "main"
161 /* strd of constants -- stores after constant moves into registers.
162 Use registers out of order, is only way to avoid plain strd while hitting
163 this pattern. */
164 int __RTL (startwith ("peephole2")) foo14 (int *a)
166 (function "foo14"
167 (insn-chain
168 (cnote 1 NOTE_INSN_DELETED)
169 (block 2
170 (edge-from entry (flags "FALLTHRU"))
171 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
172 (cinsn 99 (set (reg:SI r3)
173 (const_int 1)) "/home/matmal01/test.c":18)
174 (cinsn 100 (set (reg:SI r2)
175 (const_int 0)) "/home/matmal01/test.c":18)
176 (cinsn 101 (set (mem/c:SI (reg:SI r0) [0 S4 A64])
177 (reg:SI r3)) "/home/matmal01/test.c":18)
178 (cinsn 102 (set (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])
179 (reg:SI r2)) "/home/matmal01/test.c":18)
180 (edge-to exit (flags "FALLTHRU"))
181 ) ;; block 2
182 ) ;; insn-chain
183 (crtl
184 (return_rtx
185 (reg/i:SI r0)
186 ) ;; return_rtx
187 ) ;; crtl
188 ) ;; function "main"
191 /* swap the destination registers of two loads before a commutative operation.
192 Here the commutative operation is what the peephole uses to know it can
193 swap the register loads around. */
194 int __RTL (startwith ("peephole2")) foo15 (int *a)
196 (function "foo15"
197 (insn-chain
198 (cnote 1 NOTE_INSN_DELETED)
199 (block 2
200 (edge-from entry (flags "FALLTHRU"))
201 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
202 (cinsn 100 (set (reg:SI r3)
203 (mem/c:SI (reg:SI r0) [0 S4 A64])) "/home/matmal01/test.c":18)
204 (cinsn 101 (set (reg:SI r2)
205 (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])) "/home/matmal01/test.c":18)
206 (cinsn 102 (set (reg:SI r0)
207 (plus:SI (reg:SI r2) (reg:SI r3))) "/home/matmal01/test.c":18
208 (expr_list:REG_DEAD (reg:SI r2)
209 (expr_list:REG_DEAD (reg:SI r3)
210 (nil))))
211 (edge-to exit (flags "FALLTHRU"))
212 ) ;; block 2
213 ) ;; insn-chain
214 (crtl
215 (return_rtx
216 (reg/i:SI r0)
217 ) ;; return_rtx
218 ) ;; crtl
219 ) ;; function "main"
223 /* swap the destination registers of two loads before a commutative operation
224 that sets the flags. */
226 NOTE Can't make a testcase for this pattern since there are no insn patterns
227 matching the parallel insn in the peephole.
229 i.e. until some define_insn is defined matching that insn that peephole can
230 never match in real code, and in artificial RTL code any pattern that can
231 match it will cause an ICE.
233 int __RTL (startwith ("peephole2")) foo16 (int *a)
235 (function "foo16"
236 (insn-chain
237 (cnote 1 NOTE_INSN_DELETED)
238 (block 2
239 (edge-from entry (flags "FALLTHRU"))
240 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
241 (cinsn 100 (set (reg:SI r3)
242 (mem/c:SI (reg:SI r0) [0 S4 A64])) "/home/matmal01/test.c":18)
243 (cinsn 101 (set (reg:SI r2)
244 (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])) "/home/matmal01/test.c":18)
245 (cinsn 103 (parallel
246 [(set (reg:SI r0)
247 (and:SI (reg:SI r3) (reg:SI r2)))
248 (clobber (reg:CC cc))]) "/home/matmal01/test.c":18
249 (expr_list:REG_DEAD (reg:SI r2)
250 (expr_list:REG_DEAD (reg:SI r3)
251 (nil))))
252 (edge-to exit (flags "FALLTHRU"))
253 ) ;; block 2
254 ) ;; insn-chain
255 (crtl
256 (return_rtx
257 (reg/i:SI r0)
258 ) ;; return_rtx
259 ) ;; crtl
260 ) ;; function "main"
265 /* Making patterns that will behave differently between the LDM/STM peepholes
266 and LDRD/STRD peepholes.
267 gen_operands_ldrd_strd() uses peep2_find_free_register() to find spare
268 registers to use.
269 peep2_find_free_register() only ever returns registers marked in
270 call_used_regs, hence we make sure to leave register 2 and 3 available (as
271 they are always on in the defaults marked by CALL_USED_REGISTERS). */
273 /* gen_operands_ldrd_strd() purposefully finds an even register to look at
274 which would treat the following pattern differently to the stm peepholes.
276 int __RTL (startwith ("peephole2")) foo_x1 (int *a)
278 (function "foo_x1"
279 (insn-chain
280 (cnote 1 NOTE_INSN_DELETED)
281 (block 2
282 (edge-from entry (flags "FALLTHRU"))
283 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
284 (cinsn 99 (set (reg:SI r5)
285 (const_int 1)) "/home/matmal01/test.c":18)
286 (cinsn 101 (set (mem/c:SI (reg:SI r0) [0 S4 A64])
287 (reg:SI r5)) "/home/matmal01/test.c":18)
288 (cinsn 100 (set (reg:SI r5)
289 (const_int 0)) "/home/matmal01/test.c":18)
290 (cinsn 102 (set (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])
291 (reg:SI r5)) "/home/matmal01/test.c":18
292 (expr_list:REG_DEAD (reg:SI r5)
293 (nil)))
294 (edge-to exit (flags "FALLTHRU"))
295 ) ;; block 2
296 ) ;; insn-chain
297 (crtl
298 (return_rtx
299 (reg/i:SI r0)
300 ) ;; return_rtx
301 ) ;; crtl
302 ) ;; function "main"
304 /* Ensure we generated a parallel that started with a set from an even register.
305 i.e.
306 (parallel [
307 (set (mem
308 (reg:SI <even>
310 /* { dg-final { scan-rtl-dump {Function foo_x1.*\(parallel \[\n[^\n]*\(set \(mem[^\n]*\n[^\n]*\(reg:SI (?:[12])?[2468] r(?:[12])?[2468]\).*Function foo_x2} "peephole2" } } */
312 /* Like above gen_operands_ldrd_strd() would look to start with an even
313 register while gen_const_stm_seq() doesn't care. */
314 int __RTL (startwith ("peephole2")) foo_x2 (int *a)
316 (function "foo_x2"
317 (insn-chain
318 (cnote 1 NOTE_INSN_DELETED)
319 (block 2
320 (edge-from entry (flags "FALLTHRU"))
321 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
322 (cinsn 99 (set (reg:SI r5)
323 (const_int 1)) "/home/matmal01/test.c":18)
324 (cinsn 100 (set (reg:SI r6)
325 (const_int 0)) "/home/matmal01/test.c":18)
326 (cinsn 101 (set (mem/c:SI (reg:SI r0) [0 S4 A64])
327 (reg:SI r5)) "/home/matmal01/test.c":18)
328 (cinsn 102 (set (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])
329 (reg:SI r6)) "/home/matmal01/test.c":18)
330 (edge-to exit (flags "FALLTHRU"))
331 ) ;; block 2
332 ) ;; insn-chain
333 (crtl
334 (return_rtx
335 (reg/i:SI r0)
336 ) ;; return_rtx
337 ) ;; crtl
338 ) ;; function "main"
340 /* Ensure generated parallel starts with a set from an even register (as foo_x1). */
341 /* { dg-final { scan-rtl-dump {Function foo_x2.*\(parallel \[\n[^\n]*\(set \(mem[^\n]*\n[^\n]*\(reg:SI (?:[12])?[2468] r(?:[12])?[2468]\).*Function foo_x3} "peephole2" } } */
343 /* When storing multiple values into a register that will be used later, ldrd
344 searches for another register to use instead of just giving up. */
345 int __RTL (startwith ("peephole2")) foo_x3 (int *a)
347 (function "foo_x3"
348 (insn-chain
349 (cnote 1 NOTE_INSN_DELETED)
350 (block 2
351 (edge-from entry (flags "FALLTHRU"))
352 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
353 (cinsn 99 (set (reg:SI r3)
354 (const_int 1)) "/home/matmal01/test.c":18)
355 (cinsn 101 (set (mem/c:SI (reg:SI r0) [0 S4 A64])
356 (reg:SI r3)) "/home/matmal01/test.c":18)
357 (cinsn 100 (set (reg:SI r3)
358 (const_int 0)) "/home/matmal01/test.c":18)
359 (cinsn 102 (set (mem/c:SI (plus:SI (reg:SI r0) (const_int 4)) [0 S4 A32])
360 (reg:SI r3)) "/home/matmal01/test.c":18)
361 (cinsn 103 (set (reg:SI r0)
362 (plus:SI (reg:SI r0) (reg:SI r3))) "/home/matmal01/test.c":18)
363 (edge-to exit (flags "FALLTHRU"))
364 ) ;; block 2
365 ) ;; insn-chain
366 (crtl
367 (return_rtx
368 (reg/i:SI r0)
369 ) ;; return_rtx
370 ) ;; crtl
371 ) ;; function "main"
373 /* Ensure generated parallel starts with a set from an even register (as foo_x1). */
374 /* { dg-final { scan-rtl-dump {Function foo_x3.*\(parallel \[\n[^\n]*\(set \(mem[^\n]*\n[^\n]*\(reg:SI (?:[12])?[2468] r(?:[12])?[2468]\).*Function foo_x4} "peephole2" } } */
376 /* ldrd gen_peephole2_11 but using plus 8 and plus 12 in the offsets. */
377 int __RTL (startwith ("peephole2")) foo_x4 (int *a)
379 (function "foo_x4"
380 (insn-chain
381 (cnote 1 NOTE_INSN_DELETED)
382 (block 2
383 (edge-from entry (flags "FALLTHRU"))
384 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
385 (cinsn 101 (set (reg:SI r2)
386 (mem/c:SI (plus:SI (reg:SI r0) (const_int 8)) [0 S4 A64])) "/home/matmal01/test.c":18)
387 (cinsn 102 (set (reg:SI r3)
388 (mem/c:SI (plus:SI (reg:SI r0) (const_int 12)) [0 S4 A32])) "/home/matmal01/test.c":18)
389 (cinsn 103 (set (reg:SI r0)
390 (plus:SI (reg:SI r2) (reg:SI r3))) "/home/matmal01/test.c":18)
391 (edge-to exit (flags "FALLTHRU"))
392 ) ;; block 2
393 ) ;; insn-chain
394 (crtl
395 (return_rtx
396 (reg/i:SI r0)
397 ) ;; return_rtx
398 ) ;; crtl
399 ) ;; function "main"
401 /* Ensure generated parallel starts with a set from the appropriate offset from
402 register 0.
403 (parallel [
404 (set (reg:SI ...
405 (mem/c:SI (plus:SI (reg:SI 0 r0)
406 (const_int 8 .*
408 /* { dg-final { scan-rtl-dump {Function foo_x4.*\(parallel \[\n[^\n]*\(set \(reg:SI[^\n]*\n *\(mem/c:SI \(plus:SI \(reg:SI 0 r0\)\n *\(const_int 8.*Function foo_x5} "peephole2" } } */
410 /* strd gen_peephole2_12 but using plus 8 and plus 12 in the offsets. */
411 int __RTL (startwith ("peephole2")) foo_x5 (int *a)
413 (function "foo12"
414 (insn-chain
415 (cnote 1 NOTE_INSN_DELETED)
416 (block 2
417 (edge-from entry (flags "FALLTHRU"))
418 (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK)
419 (cinsn 101 (set (mem/c:SI (plus:SI (reg:SI r0) (const_int 8)) [0 S4 A64])
420 (reg:SI r2)) "/home/matmal01/test.c":18)
421 (cinsn 102 (set (mem/c:SI (plus:SI (reg:SI r0) (const_int 12)) [0 S4 A32])
422 (reg:SI r3)) "/home/matmal01/test.c":18)
423 (edge-to exit (flags "FALLTHRU"))
424 ) ;; block 2
425 ) ;; insn-chain
426 (crtl
427 (return_rtx
428 (reg/i:SI r0)
429 ) ;; return_rtx
430 ) ;; crtl
431 ) ;; function "main"
433 /* Ensure generated parallel starts with a set to the appropriate offset from
434 register 0. */
435 /* { dg-final { scan-rtl-dump {Function foo_x5.*\(parallel \[\n[^\n]*\(set \(mem/c:SI \(plus:SI \(reg:SI 0 r0\)\n *\(const_int 8.*$} "peephole2" } } */
438 /* { dg-final { scan-assembler-not "ldm" } } */
439 /* { dg-final { scan-assembler-not "stm" } } */
440 /* { dg-final { scan-assembler-times {ldrd\tr[2468], \[r0\]} 4 } } */
441 /* { dg-final { scan-assembler-times {ldrd\tr[2468], \[r0, #8\]} 1 } } */
442 /* { dg-final { scan-assembler-times {strd\tr[2468], \[r0\]} 6 } } */
443 /* { dg-final { scan-assembler-times {strd\tr[2468], \[r0, #8\]} 1 } } */