diff options
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch')
-rw-r--r-- | toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch | 2011 |
1 files changed, 2011 insertions, 0 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch new file mode 100644 index 0000000000..e1e89bf8af --- /dev/null +++ b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch | |||
@@ -0,0 +1,2011 @@ | |||
1 | 2010-08-29 Chung-Lin Tang <cltang@codesourcery.com> | ||
2 | |||
3 | Backport from mainline: | ||
4 | |||
5 | 2010-04-16 Bernd Schmidt <bernds@codesourcery.com> | ||
6 | |||
7 | PR target/41514 | ||
8 | gcc/ | ||
9 | * config/arm/arm.md (cbranchsi4_insn): Renamed from "*cbranchsi4_insn". | ||
10 | If the previous insn is a cbranchsi4_insn with the same arguments, | ||
11 | omit the compare instruction. | ||
12 | |||
13 | gcc/testsuite/ | ||
14 | * gcc.target/arm/thumb-comparisons.c: New test. | ||
15 | |||
16 | gcc/ | ||
17 | * config/arm/arm.md (addsi3_cbranch): If destination is a high | ||
18 | register, inputs must be low registers and we need a low register | ||
19 | scratch. Handle alternative 2 like alternative 3. | ||
20 | |||
21 | PR target/40603 | ||
22 | gcc/ | ||
23 | * config/arm/arm.md (cbranchqi4): New pattern. | ||
24 | * config/arm/predicates.md (const0_operand, | ||
25 | cbranchqi4_comparison_operator): New predicates. | ||
26 | |||
27 | gcc/testsuite/ | ||
28 | * gcc.target/arm/thumb-cbranchqi.c: New test. | ||
29 | |||
30 | 2010-04-27 Bernd Schmidt <bernds@codesourcery.com> | ||
31 | |||
32 | PR target/40657 | ||
33 | gcc/ | ||
34 | * config/arm/arm.c (thumb1_extra_regs_pushed): New function. | ||
35 | (thumb1_expand_prologue, thumb1_output_function_prologue): Call it | ||
36 | here to determine which regs to push and how much stack to reserve. | ||
37 | |||
38 | gcc/testsuite/ | ||
39 | * gcc.target/arm/thumb-stackframe.c: New test. | ||
40 | |||
41 | 2010-07-02 Bernd Schmidt <bernds@codesourcery.com> | ||
42 | |||
43 | PR target/42835 | ||
44 | gcc/ | ||
45 | * config/arm/arm-modes.def (CC_NOTB): New mode. | ||
46 | * config/arm/arm.c (get_arm_condition_code): Handle it. | ||
47 | * config/arm/thumb2.md (thumb2_compare_scc): Delete pattern. | ||
48 | * config/arm/arm.md (subsi3_compare0_c): New pattern. | ||
49 | (compare_scc): Now a define_and_split. Add a number of extra | ||
50 | splitters before it. | ||
51 | |||
52 | gcc/testsuite/ | ||
53 | * gcc.target/arm/pr42835.c: New test. | ||
54 | |||
55 | PR target/42172 | ||
56 | gcc/ | ||
57 | * config/arm/arm.c (thumb1_rtx_costs): Improve support for SIGN_EXTEND | ||
58 | and ZERO_EXTEND. | ||
59 | (arm_rtx_costs_1): Likewise. | ||
60 | (arm_size_rtx_costs): Use arm_rtx_costs_1 for these codes. | ||
61 | * config/arm/arm.md (is_arch6): New attribute. | ||
62 | (zero_extendhisi2, zero_extendqisi2, extendhisi2, | ||
63 | extendqisi2): Tighten the code somewhat, avoiding invalid | ||
64 | RTL to occur in the expander patterns. | ||
65 | (thumb1_zero_extendhisi2): Merge with thumb1_zero_extendhisi2_v6. | ||
66 | (thumb1_zero_extendhisi2_v6): Delete. | ||
67 | (thumb1_extendhisi2): Merge with thumb1_extendhisi2_v6. | ||
68 | (thumb1_extendhisi2_v6): Delete. | ||
69 | (thumb1_extendqisi2): Merge with thumb1_extendhisi2_v6. | ||
70 | (thumb1_extendqisi2_v6): Delete. | ||
71 | (zero_extendhisi2 for register input splitter): New. | ||
72 | (zero_extendqisi2 for register input splitter): New. | ||
73 | (thumb1_extendhisi2 for register input splitter): New. | ||
74 | (extendhisi2 for register input splitter): New. | ||
75 | (extendqisi2 for register input splitter): New. | ||
76 | (TARGET_THUMB1 extendqisi2 for memory input splitter): New. | ||
77 | (arm_zero_extendhisi2): Allow nonimmediate_operand for operand 1, | ||
78 | and add support for a register alternative requiring a split. | ||
79 | (thumb1_zero_extendqisi2): Likewise. | ||
80 | (arm_zero_extendqisi2): Likewise. | ||
81 | (arm_extendhisi2): Likewise. | ||
82 | (arm_extendqisi2): Likewise. | ||
83 | |||
84 | gcc/testsuite/ | ||
85 | * gcc.target/arm/pr42172-1.c: New test. | ||
86 | |||
87 | 2010-07-05 Bernd Schmidt <bernds@codesourcery.com> | ||
88 | |||
89 | * config/arm/arm.c (get_arm_condition_code): Remove CC_NOTBmode case. | ||
90 | * arm-modes.def (CC_NOTB): Don't define. | ||
91 | * config/arm/arm.md (arm_adddi3): Generate canonical RTL. | ||
92 | (adddi_sesidi_di, adddi_zesidi_di): Likewise. | ||
93 | (LTUGEU): New code_iterator. | ||
94 | (cnb, optab): New corresponding code_attrs. | ||
95 | (addsi3_carryin_<optab>): Renamed from addsi3_carryin. Change pattern | ||
96 | to canonical form. Operands 1 and 2 are commutative. Parametrize | ||
97 | using LTUGEU. | ||
98 | (addsi3_carryin_shift_<optab>): Likewise. | ||
99 | (addsi3_carryin_alt2_<optab>): Renamed from addsi3_carryin_alt2. | ||
100 | Operands 1 and 2 are commutative. Parametrize using LTUGEU. | ||
101 | (addsi3_carryin_alt1, addsi3_carryin_alt3): Remove. | ||
102 | (subsi3_compare): Renamed from subsi3_compare0_c. Change CC_NOTB to | ||
103 | CC. | ||
104 | (arm_subsi3_insn): Allow constants for operand 0. | ||
105 | (compare_scc peephole for eq case): New. | ||
106 | (compare_scc splitters): Change CC_NOTB to CC. | ||
107 | |||
108 | 2010-07-09 Bernd Schmidt <bernds@codesourcery.com> | ||
109 | |||
110 | PR target/40657 | ||
111 | gcc/ | ||
112 | * config/arm/arm.c (thumb1_extra_regs_pushed): New arg FOR_PROLOGUE. | ||
113 | All callers changed. | ||
114 | Handle the case when we're called for the epilogue. | ||
115 | (thumb_unexpanded_epilogue): Use it. | ||
116 | (thumb1_expand_epilogue): Likewise. | ||
117 | |||
118 | gcc/testsuite/ | ||
119 | * gcc.target/arm/pr40657-1.c: New test. | ||
120 | * gcc.target/arm/pr40657-2.c: New test. | ||
121 | * gcc.c-torture/execute/pr40657.c: New test. | ||
122 | |||
123 | gcc/ | ||
124 | * config/arm/arm.md (addsi3_cbranch): Switch alternatives 0 and 1. | ||
125 | |||
126 | * config/arm/arm.md (Thumb-1 ldrsb peephole): New. | ||
127 | |||
128 | * config/arm/arm.md (cbranchqi4): Fix array size. | ||
129 | (addsi3_cbranch): Also andle alternative 2 like alternative 3 when | ||
130 | calculating length. | ||
131 | |||
132 | 2010-08-27 Paul Brook <paul@codesourcery.com> | ||
133 | |||
134 | gcc/ | ||
135 | |||
136 | === modified file 'gcc/config/arm/arm-modes.def' | ||
137 | --- old/gcc/config/arm/arm-modes.def 2010-07-29 16:58:56 +0000 | ||
138 | +++ new/gcc/config/arm/arm-modes.def 2010-08-31 10:00:27 +0000 | ||
139 | @@ -34,6 +34,8 @@ | ||
140 | CCFPmode should be used with floating equalities. | ||
141 | CC_NOOVmode should be used with SImode integer equalities. | ||
142 | CC_Zmode should be used if only the Z flag is set correctly | ||
143 | + CC_Cmode should be used if only the C flag is set correctly, after an | ||
144 | + addition. | ||
145 | CC_Nmode should be used if only the N (sign) flag is set correctly | ||
146 | CC_CZmode should be used if only the C and Z flags are correct | ||
147 | (used for DImode unsigned comparisons). | ||
148 | |||
149 | === modified file 'gcc/config/arm/arm.c' | ||
150 | --- old/gcc/config/arm/arm.c 2010-08-25 16:22:17 +0000 | ||
151 | +++ new/gcc/config/arm/arm.c 2010-08-31 10:00:27 +0000 | ||
152 | @@ -6443,6 +6443,7 @@ | ||
153 | thumb1_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer) | ||
154 | { | ||
155 | enum machine_mode mode = GET_MODE (x); | ||
156 | + int total; | ||
157 | |||
158 | switch (code) | ||
159 | { | ||
160 | @@ -6545,24 +6546,20 @@ | ||
161 | return 14; | ||
162 | return 2; | ||
163 | |||
164 | + case SIGN_EXTEND: | ||
165 | case ZERO_EXTEND: | ||
166 | - /* XXX still guessing. */ | ||
167 | - switch (GET_MODE (XEXP (x, 0))) | ||
168 | - { | ||
169 | - case QImode: | ||
170 | - return (1 + (mode == DImode ? 4 : 0) | ||
171 | - + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); | ||
172 | - | ||
173 | - case HImode: | ||
174 | - return (4 + (mode == DImode ? 4 : 0) | ||
175 | - + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); | ||
176 | - | ||
177 | - case SImode: | ||
178 | - return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0)); | ||
179 | - | ||
180 | - default: | ||
181 | - return 99; | ||
182 | - } | ||
183 | + total = mode == DImode ? COSTS_N_INSNS (1) : 0; | ||
184 | + total += thumb1_rtx_costs (XEXP (x, 0), GET_CODE (XEXP (x, 0)), code); | ||
185 | + | ||
186 | + if (mode == SImode) | ||
187 | + return total; | ||
188 | + | ||
189 | + if (arm_arch6) | ||
190 | + return total + COSTS_N_INSNS (1); | ||
191 | + | ||
192 | + /* Assume a two-shift sequence. Increase the cost slightly so | ||
193 | + we prefer actual shifts over an extend operation. */ | ||
194 | + return total + 1 + COSTS_N_INSNS (2); | ||
195 | |||
196 | default: | ||
197 | return 99; | ||
198 | @@ -7046,44 +7043,39 @@ | ||
199 | return false; | ||
200 | |||
201 | case SIGN_EXTEND: | ||
202 | - if (GET_MODE_CLASS (mode) == MODE_INT) | ||
203 | - { | ||
204 | - *total = 0; | ||
205 | - if (mode == DImode) | ||
206 | - *total += COSTS_N_INSNS (1); | ||
207 | - | ||
208 | - if (GET_MODE (XEXP (x, 0)) != SImode) | ||
209 | - { | ||
210 | - if (arm_arch6) | ||
211 | - { | ||
212 | - if (GET_CODE (XEXP (x, 0)) != MEM) | ||
213 | - *total += COSTS_N_INSNS (1); | ||
214 | - } | ||
215 | - else if (!arm_arch4 || GET_CODE (XEXP (x, 0)) != MEM) | ||
216 | - *total += COSTS_N_INSNS (2); | ||
217 | - } | ||
218 | - | ||
219 | - return false; | ||
220 | - } | ||
221 | - | ||
222 | - /* Fall through */ | ||
223 | case ZERO_EXTEND: | ||
224 | *total = 0; | ||
225 | if (GET_MODE_CLASS (mode) == MODE_INT) | ||
226 | { | ||
227 | + rtx op = XEXP (x, 0); | ||
228 | + enum machine_mode opmode = GET_MODE (op); | ||
229 | + | ||
230 | if (mode == DImode) | ||
231 | *total += COSTS_N_INSNS (1); | ||
232 | |||
233 | - if (GET_MODE (XEXP (x, 0)) != SImode) | ||
234 | + if (opmode != SImode) | ||
235 | { | ||
236 | - if (arm_arch6) | ||
237 | + if (MEM_P (op)) | ||
238 | { | ||
239 | - if (GET_CODE (XEXP (x, 0)) != MEM) | ||
240 | - *total += COSTS_N_INSNS (1); | ||
241 | + /* If !arm_arch4, we use one of the extendhisi2_mem | ||
242 | + or movhi_bytes patterns for HImode. For a QImode | ||
243 | + sign extension, we first zero-extend from memory | ||
244 | + and then perform a shift sequence. */ | ||
245 | + if (!arm_arch4 && (opmode != QImode || code == SIGN_EXTEND)) | ||
246 | + *total += COSTS_N_INSNS (2); | ||
247 | } | ||
248 | - else if (!arm_arch4 || GET_CODE (XEXP (x, 0)) != MEM) | ||
249 | - *total += COSTS_N_INSNS (GET_MODE (XEXP (x, 0)) == QImode ? | ||
250 | - 1 : 2); | ||
251 | + else if (arm_arch6) | ||
252 | + *total += COSTS_N_INSNS (1); | ||
253 | + | ||
254 | + /* We don't have the necessary insn, so we need to perform some | ||
255 | + other operation. */ | ||
256 | + else if (TARGET_ARM && code == ZERO_EXTEND && mode == QImode) | ||
257 | + /* An and with constant 255. */ | ||
258 | + *total += COSTS_N_INSNS (1); | ||
259 | + else | ||
260 | + /* A shift sequence. Increase costs slightly to avoid | ||
261 | + combining two shifts into an extend operation. */ | ||
262 | + *total += COSTS_N_INSNS (2) + 1; | ||
263 | } | ||
264 | |||
265 | return false; | ||
266 | @@ -7333,41 +7325,8 @@ | ||
267 | return false; | ||
268 | |||
269 | case SIGN_EXTEND: | ||
270 | - *total = 0; | ||
271 | - if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) < 4) | ||
272 | - { | ||
273 | - if (!(arm_arch4 && MEM_P (XEXP (x, 0)))) | ||
274 | - *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); | ||
275 | - } | ||
276 | - if (mode == DImode) | ||
277 | - *total += COSTS_N_INSNS (1); | ||
278 | - return false; | ||
279 | - | ||
280 | case ZERO_EXTEND: | ||
281 | - *total = 0; | ||
282 | - if (!(arm_arch4 && MEM_P (XEXP (x, 0)))) | ||
283 | - { | ||
284 | - switch (GET_MODE (XEXP (x, 0))) | ||
285 | - { | ||
286 | - case QImode: | ||
287 | - *total += COSTS_N_INSNS (1); | ||
288 | - break; | ||
289 | - | ||
290 | - case HImode: | ||
291 | - *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2); | ||
292 | - | ||
293 | - case SImode: | ||
294 | - break; | ||
295 | - | ||
296 | - default: | ||
297 | - *total += COSTS_N_INSNS (2); | ||
298 | - } | ||
299 | - } | ||
300 | - | ||
301 | - if (mode == DImode) | ||
302 | - *total += COSTS_N_INSNS (1); | ||
303 | - | ||
304 | - return false; | ||
305 | + return arm_rtx_costs_1 (x, outer_code, total, 0); | ||
306 | |||
307 | case CONST_INT: | ||
308 | if (const_ok_for_arm (INTVAL (x))) | ||
309 | @@ -16898,11 +16857,11 @@ | ||
310 | |||
311 | case CC_Cmode: | ||
312 | switch (comp_code) | ||
313 | - { | ||
314 | - case LTU: return ARM_CS; | ||
315 | - case GEU: return ARM_CC; | ||
316 | - default: gcc_unreachable (); | ||
317 | - } | ||
318 | + { | ||
319 | + case LTU: return ARM_CS; | ||
320 | + case GEU: return ARM_CC; | ||
321 | + default: gcc_unreachable (); | ||
322 | + } | ||
323 | |||
324 | case CC_CZmode: | ||
325 | switch (comp_code) | ||
326 | @@ -20127,6 +20086,81 @@ | ||
327 | #endif | ||
328 | } | ||
329 | |||
330 | +/* Given the stack offsets and register mask in OFFSETS, decide how | ||
331 | + many additional registers to push instead of subtracting a constant | ||
332 | + from SP. For epilogues the principle is the same except we use pop. | ||
333 | + FOR_PROLOGUE indicates which we're generating. */ | ||
334 | +static int | ||
335 | +thumb1_extra_regs_pushed (arm_stack_offsets *offsets, bool for_prologue) | ||
336 | +{ | ||
337 | + HOST_WIDE_INT amount; | ||
338 | + unsigned long live_regs_mask = offsets->saved_regs_mask; | ||
339 | + /* Extract a mask of the ones we can give to the Thumb's push/pop | ||
340 | + instruction. */ | ||
341 | + unsigned long l_mask = live_regs_mask & (for_prologue ? 0x40ff : 0xff); | ||
342 | + /* Then count how many other high registers will need to be pushed. */ | ||
343 | + unsigned long high_regs_pushed = bit_count (live_regs_mask & 0x0f00); | ||
344 | + int n_free, reg_base; | ||
345 | + | ||
346 | + if (!for_prologue && frame_pointer_needed) | ||
347 | + amount = offsets->locals_base - offsets->saved_regs; | ||
348 | + else | ||
349 | + amount = offsets->outgoing_args - offsets->saved_regs; | ||
350 | + | ||
351 | + /* If the stack frame size is 512 exactly, we can save one load | ||
352 | + instruction, which should make this a win even when optimizing | ||
353 | + for speed. */ | ||
354 | + if (!optimize_size && amount != 512) | ||
355 | + return 0; | ||
356 | + | ||
357 | + /* Can't do this if there are high registers to push. */ | ||
358 | + if (high_regs_pushed != 0) | ||
359 | + return 0; | ||
360 | + | ||
361 | + /* Shouldn't do it in the prologue if no registers would normally | ||
362 | + be pushed at all. In the epilogue, also allow it if we'll have | ||
363 | + a pop insn for the PC. */ | ||
364 | + if (l_mask == 0 | ||
365 | + && (for_prologue | ||
366 | + || TARGET_BACKTRACE | ||
367 | + || (live_regs_mask & 1 << LR_REGNUM) == 0 | ||
368 | + || TARGET_INTERWORK | ||
369 | + || crtl->args.pretend_args_size != 0)) | ||
370 | + return 0; | ||
371 | + | ||
372 | + /* Don't do this if thumb_expand_prologue wants to emit instructions | ||
373 | + between the push and the stack frame allocation. */ | ||
374 | + if (for_prologue | ||
375 | + && ((flag_pic && arm_pic_register != INVALID_REGNUM) | ||
376 | + || (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0))) | ||
377 | + return 0; | ||
378 | + | ||
379 | + reg_base = 0; | ||
380 | + n_free = 0; | ||
381 | + if (!for_prologue) | ||
382 | + { | ||
383 | + reg_base = arm_size_return_regs () / UNITS_PER_WORD; | ||
384 | + live_regs_mask >>= reg_base; | ||
385 | + } | ||
386 | + | ||
387 | + while (reg_base + n_free < 8 && !(live_regs_mask & 1) | ||
388 | + && (for_prologue || call_used_regs[reg_base + n_free])) | ||
389 | + { | ||
390 | + live_regs_mask >>= 1; | ||
391 | + n_free++; | ||
392 | + } | ||
393 | + | ||
394 | + if (n_free == 0) | ||
395 | + return 0; | ||
396 | + gcc_assert (amount / 4 * 4 == amount); | ||
397 | + | ||
398 | + if (amount >= 512 && (amount - n_free * 4) < 512) | ||
399 | + return (amount - 508) / 4; | ||
400 | + if (amount <= n_free * 4) | ||
401 | + return amount / 4; | ||
402 | + return 0; | ||
403 | +} | ||
404 | + | ||
405 | /* The bits which aren't usefully expanded as rtl. */ | ||
406 | const char * | ||
407 | thumb_unexpanded_epilogue (void) | ||
408 | @@ -20135,6 +20169,7 @@ | ||
409 | int regno; | ||
410 | unsigned long live_regs_mask = 0; | ||
411 | int high_regs_pushed = 0; | ||
412 | + int extra_pop; | ||
413 | int had_to_push_lr; | ||
414 | int size; | ||
415 | |||
416 | @@ -20154,6 +20189,13 @@ | ||
417 | the register is used to hold a return value. */ | ||
418 | size = arm_size_return_regs (); | ||
419 | |||
420 | + extra_pop = thumb1_extra_regs_pushed (offsets, false); | ||
421 | + if (extra_pop > 0) | ||
422 | + { | ||
423 | + unsigned long extra_mask = (1 << extra_pop) - 1; | ||
424 | + live_regs_mask |= extra_mask << (size / UNITS_PER_WORD); | ||
425 | + } | ||
426 | + | ||
427 | /* The prolog may have pushed some high registers to use as | ||
428 | work registers. e.g. the testsuite file: | ||
429 | gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c | ||
430 | @@ -20237,7 +20279,9 @@ | ||
431 | live_regs_mask); | ||
432 | |||
433 | /* We have either just popped the return address into the | ||
434 | - PC or it is was kept in LR for the entire function. */ | ||
435 | + PC or it is was kept in LR for the entire function. | ||
436 | + Note that thumb_pushpop has already called thumb_exit if the | ||
437 | + PC was in the list. */ | ||
438 | if (!had_to_push_lr) | ||
439 | thumb_exit (asm_out_file, LR_REGNUM); | ||
440 | } | ||
441 | @@ -20419,6 +20463,7 @@ | ||
442 | stack_pointer_rtx); | ||
443 | |||
444 | amount = offsets->outgoing_args - offsets->saved_regs; | ||
445 | + amount -= 4 * thumb1_extra_regs_pushed (offsets, true); | ||
446 | if (amount) | ||
447 | { | ||
448 | if (amount < 512) | ||
449 | @@ -20503,6 +20548,7 @@ | ||
450 | emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx)); | ||
451 | amount = offsets->locals_base - offsets->saved_regs; | ||
452 | } | ||
453 | + amount -= 4 * thumb1_extra_regs_pushed (offsets, false); | ||
454 | |||
455 | gcc_assert (amount >= 0); | ||
456 | if (amount) | ||
457 | @@ -20723,7 +20769,11 @@ | ||
458 | register. */ | ||
459 | else if ((l_mask & 0xff) != 0 | ||
460 | || (high_regs_pushed == 0 && l_mask)) | ||
461 | - thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask); | ||
462 | + { | ||
463 | + unsigned long mask = l_mask; | ||
464 | + mask |= (1 << thumb1_extra_regs_pushed (offsets, true)) - 1; | ||
465 | + thumb_pushpop (f, mask, 1, &cfa_offset, mask); | ||
466 | + } | ||
467 | |||
468 | if (high_regs_pushed) | ||
469 | { | ||
470 | |||
471 | === modified file 'gcc/config/arm/arm.md' | ||
472 | --- old/gcc/config/arm/arm.md 2010-08-25 16:22:17 +0000 | ||
473 | +++ new/gcc/config/arm/arm.md 2010-08-31 10:00:27 +0000 | ||
474 | @@ -150,6 +150,9 @@ | ||
475 | ; patterns that share the same RTL in both ARM and Thumb code. | ||
476 | (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code"))) | ||
477 | |||
478 | +; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6. | ||
479 | +(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6"))) | ||
480 | + | ||
481 | ;; Operand number of an input operand that is shifted. Zero if the | ||
482 | ;; given instruction does not shift one of its input operands. | ||
483 | (define_attr "shift" "" (const_int 0)) | ||
484 | @@ -515,8 +518,8 @@ | ||
485 | (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) | ||
486 | (match_dup 1))) | ||
487 | (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) | ||
488 | - (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
489 | - (plus:SI (match_dup 4) (match_dup 5))))] | ||
490 | + (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5)) | ||
491 | + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] | ||
492 | " | ||
493 | { | ||
494 | operands[3] = gen_highpart (SImode, operands[0]); | ||
495 | @@ -543,10 +546,10 @@ | ||
496 | (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) | ||
497 | (match_dup 1))) | ||
498 | (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) | ||
499 | - (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
500 | - (plus:SI (ashiftrt:SI (match_dup 2) | ||
501 | + (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2) | ||
502 | (const_int 31)) | ||
503 | - (match_dup 4))))] | ||
504 | + (match_dup 4)) | ||
505 | + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] | ||
506 | " | ||
507 | { | ||
508 | operands[3] = gen_highpart (SImode, operands[0]); | ||
509 | @@ -572,8 +575,8 @@ | ||
510 | (compare:CC_C (plus:SI (match_dup 1) (match_dup 2)) | ||
511 | (match_dup 1))) | ||
512 | (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) | ||
513 | - (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
514 | - (plus:SI (match_dup 4) (const_int 0))))] | ||
515 | + (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0)) | ||
516 | + (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] | ||
517 | " | ||
518 | { | ||
519 | operands[3] = gen_highpart (SImode, operands[0]); | ||
520 | @@ -861,24 +864,38 @@ | ||
521 | [(set_attr "conds" "set")] | ||
522 | ) | ||
523 | |||
524 | -(define_insn "*addsi3_carryin" | ||
525 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
526 | - (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
527 | - (plus:SI (match_operand:SI 1 "s_register_operand" "r") | ||
528 | - (match_operand:SI 2 "arm_rhs_operand" "rI"))))] | ||
529 | - "TARGET_32BIT" | ||
530 | - "adc%?\\t%0, %1, %2" | ||
531 | - [(set_attr "conds" "use")] | ||
532 | -) | ||
533 | - | ||
534 | -(define_insn "*addsi3_carryin_shift" | ||
535 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
536 | - (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
537 | - (plus:SI | ||
538 | - (match_operator:SI 2 "shift_operator" | ||
539 | - [(match_operand:SI 3 "s_register_operand" "r") | ||
540 | - (match_operand:SI 4 "reg_or_int_operand" "rM")]) | ||
541 | - (match_operand:SI 1 "s_register_operand" "r"))))] | ||
542 | +(define_code_iterator LTUGEU [ltu geu]) | ||
543 | +(define_code_attr cnb [(ltu "CC_C") (geu "CC")]) | ||
544 | +(define_code_attr optab [(ltu "ltu") (geu "geu")]) | ||
545 | + | ||
546 | +(define_insn "*addsi3_carryin_<optab>" | ||
547 | + [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
548 | + (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r") | ||
549 | + (match_operand:SI 2 "arm_rhs_operand" "rI")) | ||
550 | + (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))] | ||
551 | + "TARGET_32BIT" | ||
552 | + "adc%?\\t%0, %1, %2" | ||
553 | + [(set_attr "conds" "use")] | ||
554 | +) | ||
555 | + | ||
556 | +(define_insn "*addsi3_carryin_alt2_<optab>" | ||
557 | + [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
558 | + (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0)) | ||
559 | + (match_operand:SI 1 "s_register_operand" "%r")) | ||
560 | + (match_operand:SI 2 "arm_rhs_operand" "rI")))] | ||
561 | + "TARGET_32BIT" | ||
562 | + "adc%?\\t%0, %1, %2" | ||
563 | + [(set_attr "conds" "use")] | ||
564 | +) | ||
565 | + | ||
566 | +(define_insn "*addsi3_carryin_shift_<optab>" | ||
567 | + [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
568 | + (plus:SI (plus:SI | ||
569 | + (match_operator:SI 2 "shift_operator" | ||
570 | + [(match_operand:SI 3 "s_register_operand" "r") | ||
571 | + (match_operand:SI 4 "reg_or_int_operand" "rM")]) | ||
572 | + (match_operand:SI 1 "s_register_operand" "r")) | ||
573 | + (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))] | ||
574 | "TARGET_32BIT" | ||
575 | "adc%?\\t%0, %1, %3%S2" | ||
576 | [(set_attr "conds" "use") | ||
577 | @@ -887,36 +904,6 @@ | ||
578 | (const_string "alu_shift_reg")))] | ||
579 | ) | ||
580 | |||
581 | -(define_insn "*addsi3_carryin_alt1" | ||
582 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
583 | - (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r") | ||
584 | - (match_operand:SI 2 "arm_rhs_operand" "rI")) | ||
585 | - (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))] | ||
586 | - "TARGET_32BIT" | ||
587 | - "adc%?\\t%0, %1, %2" | ||
588 | - [(set_attr "conds" "use")] | ||
589 | -) | ||
590 | - | ||
591 | -(define_insn "*addsi3_carryin_alt2" | ||
592 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
593 | - (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
594 | - (match_operand:SI 1 "s_register_operand" "r")) | ||
595 | - (match_operand:SI 2 "arm_rhs_operand" "rI")))] | ||
596 | - "TARGET_32BIT" | ||
597 | - "adc%?\\t%0, %1, %2" | ||
598 | - [(set_attr "conds" "use")] | ||
599 | -) | ||
600 | - | ||
601 | -(define_insn "*addsi3_carryin_alt3" | ||
602 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
603 | - (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0)) | ||
604 | - (match_operand:SI 2 "arm_rhs_operand" "rI")) | ||
605 | - (match_operand:SI 1 "s_register_operand" "r")))] | ||
606 | - "TARGET_32BIT" | ||
607 | - "adc%?\\t%0, %1, %2" | ||
608 | - [(set_attr "conds" "use")] | ||
609 | -) | ||
610 | - | ||
611 | (define_expand "incscc" | ||
612 | [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
613 | (plus:SI (match_operator:SI 2 "arm_comparison_operator" | ||
614 | @@ -1116,24 +1103,27 @@ | ||
615 | |||
616 | ; ??? Check Thumb-2 split length | ||
617 | (define_insn_and_split "*arm_subsi3_insn" | ||
618 | - [(set (match_operand:SI 0 "s_register_operand" "=r,rk,r") | ||
619 | - (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,!k,?n") | ||
620 | - (match_operand:SI 2 "s_register_operand" "r, r, r")))] | ||
621 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r") | ||
622 | + (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,!k,?n,r") | ||
623 | + (match_operand:SI 2 "reg_or_int_operand" "r,rI, r, r,?n")))] | ||
624 | "TARGET_32BIT" | ||
625 | "@ | ||
626 | rsb%?\\t%0, %2, %1 | ||
627 | sub%?\\t%0, %1, %2 | ||
628 | + sub%?\\t%0, %1, %2 | ||
629 | + # | ||
630 | #" | ||
631 | - "TARGET_32BIT | ||
632 | - && GET_CODE (operands[1]) == CONST_INT | ||
633 | - && !const_ok_for_arm (INTVAL (operands[1]))" | ||
634 | + "&& ((GET_CODE (operands[1]) == CONST_INT | ||
635 | + && !const_ok_for_arm (INTVAL (operands[1]))) | ||
636 | + || (GET_CODE (operands[2]) == CONST_INT | ||
637 | + && !const_ok_for_arm (INTVAL (operands[2]))))" | ||
638 | [(clobber (const_int 0))] | ||
639 | " | ||
640 | arm_split_constant (MINUS, SImode, curr_insn, | ||
641 | INTVAL (operands[1]), operands[0], operands[2], 0); | ||
642 | DONE; | ||
643 | " | ||
644 | - [(set_attr "length" "4,4,16") | ||
645 | + [(set_attr "length" "4,4,4,16,16") | ||
646 | (set_attr "predicable" "yes")] | ||
647 | ) | ||
648 | |||
649 | @@ -1165,6 +1155,19 @@ | ||
650 | [(set_attr "conds" "set")] | ||
651 | ) | ||
652 | |||
653 | +(define_insn "*subsi3_compare" | ||
654 | + [(set (reg:CC CC_REGNUM) | ||
655 | + (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I") | ||
656 | + (match_operand:SI 2 "arm_rhs_operand" "rI,r"))) | ||
657 | + (set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
658 | + (minus:SI (match_dup 1) (match_dup 2)))] | ||
659 | + "TARGET_32BIT" | ||
660 | + "@ | ||
661 | + sub%.\\t%0, %1, %2 | ||
662 | + rsb%.\\t%0, %2, %1" | ||
663 | + [(set_attr "conds" "set")] | ||
664 | +) | ||
665 | + | ||
666 | (define_expand "decscc" | ||
667 | [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
668 | (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") | ||
669 | @@ -4050,93 +4053,46 @@ | ||
670 | ) | ||
671 | |||
672 | (define_expand "zero_extendhisi2" | ||
673 | - [(set (match_dup 2) | ||
674 | - (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") | ||
675 | - (const_int 16))) | ||
676 | - (set (match_operand:SI 0 "s_register_operand" "") | ||
677 | - (lshiftrt:SI (match_dup 2) (const_int 16)))] | ||
678 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
679 | + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] | ||
680 | "TARGET_EITHER" | ||
681 | - " | ||
682 | - { | ||
683 | - if ((TARGET_THUMB1 || arm_arch4) && GET_CODE (operands[1]) == MEM) | ||
684 | - { | ||
685 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
686 | - gen_rtx_ZERO_EXTEND (SImode, operands[1]))); | ||
687 | - DONE; | ||
688 | - } | ||
689 | - | ||
690 | - if (TARGET_ARM && GET_CODE (operands[1]) == MEM) | ||
691 | - { | ||
692 | - emit_insn (gen_movhi_bytes (operands[0], operands[1])); | ||
693 | - DONE; | ||
694 | - } | ||
695 | - | ||
696 | - if (!s_register_operand (operands[1], HImode)) | ||
697 | - operands[1] = copy_to_mode_reg (HImode, operands[1]); | ||
698 | - | ||
699 | - if (arm_arch6) | ||
700 | - { | ||
701 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
702 | - gen_rtx_ZERO_EXTEND (SImode, operands[1]))); | ||
703 | - DONE; | ||
704 | - } | ||
705 | - | ||
706 | - operands[1] = gen_lowpart (SImode, operands[1]); | ||
707 | - operands[2] = gen_reg_rtx (SImode); | ||
708 | - }" | ||
709 | -) | ||
710 | +{ | ||
711 | + if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1])) | ||
712 | + { | ||
713 | + emit_insn (gen_movhi_bytes (operands[0], operands[1])); | ||
714 | + DONE; | ||
715 | + } | ||
716 | + if (!arm_arch6 && !MEM_P (operands[1])) | ||
717 | + { | ||
718 | + rtx t = gen_lowpart (SImode, operands[1]); | ||
719 | + rtx tmp = gen_reg_rtx (SImode); | ||
720 | + emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16))); | ||
721 | + emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16))); | ||
722 | + DONE; | ||
723 | + } | ||
724 | +}) | ||
725 | + | ||
726 | +(define_split | ||
727 | + [(set (match_operand:SI 0 "register_operand" "") | ||
728 | + (zero_extend:SI (match_operand:HI 1 "register_operand" "l,m")))] | ||
729 | + "!TARGET_THUMB2 && !arm_arch6" | ||
730 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) | ||
731 | + (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] | ||
732 | +{ | ||
733 | + operands[2] = gen_lowpart (SImode, operands[1]); | ||
734 | +}) | ||
735 | |||
736 | (define_insn "*thumb1_zero_extendhisi2" | ||
737 | - [(set (match_operand:SI 0 "register_operand" "=l") | ||
738 | - (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | ||
739 | - "TARGET_THUMB1 && !arm_arch6" | ||
740 | - "* | ||
741 | - rtx mem = XEXP (operands[1], 0); | ||
742 | - | ||
743 | - if (GET_CODE (mem) == CONST) | ||
744 | - mem = XEXP (mem, 0); | ||
745 | - | ||
746 | - if (GET_CODE (mem) == LABEL_REF) | ||
747 | - return \"ldr\\t%0, %1\"; | ||
748 | - | ||
749 | - if (GET_CODE (mem) == PLUS) | ||
750 | - { | ||
751 | - rtx a = XEXP (mem, 0); | ||
752 | - rtx b = XEXP (mem, 1); | ||
753 | - | ||
754 | - /* This can happen due to bugs in reload. */ | ||
755 | - if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM) | ||
756 | - { | ||
757 | - rtx ops[2]; | ||
758 | - ops[0] = operands[0]; | ||
759 | - ops[1] = a; | ||
760 | - | ||
761 | - output_asm_insn (\"mov %0, %1\", ops); | ||
762 | - | ||
763 | - XEXP (mem, 0) = operands[0]; | ||
764 | - } | ||
765 | - | ||
766 | - else if ( GET_CODE (a) == LABEL_REF | ||
767 | - && GET_CODE (b) == CONST_INT) | ||
768 | - return \"ldr\\t%0, %1\"; | ||
769 | - } | ||
770 | - | ||
771 | - return \"ldrh\\t%0, %1\"; | ||
772 | - " | ||
773 | - [(set_attr "length" "4") | ||
774 | - (set_attr "type" "load_byte") | ||
775 | - (set_attr "pool_range" "60")] | ||
776 | -) | ||
777 | - | ||
778 | -(define_insn "*thumb1_zero_extendhisi2_v6" | ||
779 | [(set (match_operand:SI 0 "register_operand" "=l,l") | ||
780 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))] | ||
781 | - "TARGET_THUMB1 && arm_arch6" | ||
782 | + "TARGET_THUMB1" | ||
783 | "* | ||
784 | rtx mem; | ||
785 | |||
786 | - if (which_alternative == 0) | ||
787 | + if (which_alternative == 0 && arm_arch6) | ||
788 | return \"uxth\\t%0, %1\"; | ||
789 | + if (which_alternative == 0) | ||
790 | + return \"#\"; | ||
791 | |||
792 | mem = XEXP (operands[1], 0); | ||
793 | |||
794 | @@ -4170,20 +4126,25 @@ | ||
795 | |||
796 | return \"ldrh\\t%0, %1\"; | ||
797 | " | ||
798 | - [(set_attr "length" "2,4") | ||
799 | + [(set_attr_alternative "length" | ||
800 | + [(if_then_else (eq_attr "is_arch6" "yes") | ||
801 | + (const_int 2) (const_int 4)) | ||
802 | + (const_int 4)]) | ||
803 | (set_attr "type" "alu_shift,load_byte") | ||
804 | (set_attr "pool_range" "*,60")] | ||
805 | ) | ||
806 | |||
807 | (define_insn "*arm_zero_extendhisi2" | ||
808 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
809 | - (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | ||
810 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
811 | + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | ||
812 | "TARGET_ARM && arm_arch4 && !arm_arch6" | ||
813 | - "ldr%(h%)\\t%0, %1" | ||
814 | - [(set_attr "type" "load_byte") | ||
815 | + "@ | ||
816 | + # | ||
817 | + ldr%(h%)\\t%0, %1" | ||
818 | + [(set_attr "type" "alu_shift,load_byte") | ||
819 | (set_attr "predicable" "yes") | ||
820 | - (set_attr "pool_range" "256") | ||
821 | - (set_attr "neg_pool_range" "244")] | ||
822 | + (set_attr "pool_range" "*,256") | ||
823 | + (set_attr "neg_pool_range" "*,244")] | ||
824 | ) | ||
825 | |||
826 | (define_insn "*arm_zero_extendhisi2_v6" | ||
827 | @@ -4213,50 +4174,49 @@ | ||
828 | [(set (match_operand:SI 0 "s_register_operand" "") | ||
829 | (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] | ||
830 | "TARGET_EITHER" | ||
831 | - " | ||
832 | - if (!arm_arch6 && GET_CODE (operands[1]) != MEM) | ||
833 | - { | ||
834 | - if (TARGET_ARM) | ||
835 | - { | ||
836 | - emit_insn (gen_andsi3 (operands[0], | ||
837 | - gen_lowpart (SImode, operands[1]), | ||
838 | - GEN_INT (255))); | ||
839 | - } | ||
840 | - else /* TARGET_THUMB */ | ||
841 | - { | ||
842 | - rtx temp = gen_reg_rtx (SImode); | ||
843 | - rtx ops[3]; | ||
844 | - | ||
845 | - operands[1] = copy_to_mode_reg (QImode, operands[1]); | ||
846 | - operands[1] = gen_lowpart (SImode, operands[1]); | ||
847 | - | ||
848 | - ops[0] = temp; | ||
849 | - ops[1] = operands[1]; | ||
850 | - ops[2] = GEN_INT (24); | ||
851 | - | ||
852 | - emit_insn (gen_rtx_SET (VOIDmode, ops[0], | ||
853 | - gen_rtx_ASHIFT (SImode, ops[1], ops[2]))); | ||
854 | - | ||
855 | - ops[0] = operands[0]; | ||
856 | - ops[1] = temp; | ||
857 | - ops[2] = GEN_INT (24); | ||
858 | - | ||
859 | - emit_insn (gen_rtx_SET (VOIDmode, ops[0], | ||
860 | - gen_rtx_LSHIFTRT (SImode, ops[1], ops[2]))); | ||
861 | - } | ||
862 | - DONE; | ||
863 | - } | ||
864 | - " | ||
865 | -) | ||
866 | +{ | ||
867 | + if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM) | ||
868 | + { | ||
869 | + emit_insn (gen_andsi3 (operands[0], | ||
870 | + gen_lowpart (SImode, operands[1]), | ||
871 | + GEN_INT (255))); | ||
872 | + DONE; | ||
873 | + } | ||
874 | + if (!arm_arch6 && !MEM_P (operands[1])) | ||
875 | + { | ||
876 | + rtx t = gen_lowpart (SImode, operands[1]); | ||
877 | + rtx tmp = gen_reg_rtx (SImode); | ||
878 | + emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24))); | ||
879 | + emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24))); | ||
880 | + DONE; | ||
881 | + } | ||
882 | +}) | ||
883 | + | ||
884 | +(define_split | ||
885 | + [(set (match_operand:SI 0 "register_operand" "") | ||
886 | + (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] | ||
887 | + "!arm_arch6" | ||
888 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) | ||
889 | + (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))] | ||
890 | +{ | ||
891 | + operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0); | ||
892 | + if (TARGET_ARM) | ||
893 | + { | ||
894 | + emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255))); | ||
895 | + DONE; | ||
896 | + } | ||
897 | +}) | ||
898 | |||
899 | (define_insn "*thumb1_zero_extendqisi2" | ||
900 | - [(set (match_operand:SI 0 "register_operand" "=l") | ||
901 | - (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] | ||
902 | + [(set (match_operand:SI 0 "register_operand" "=l,l") | ||
903 | + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))] | ||
904 | "TARGET_THUMB1 && !arm_arch6" | ||
905 | - "ldrb\\t%0, %1" | ||
906 | - [(set_attr "length" "2") | ||
907 | - (set_attr "type" "load_byte") | ||
908 | - (set_attr "pool_range" "32")] | ||
909 | + "@ | ||
910 | + # | ||
911 | + ldrb\\t%0, %1" | ||
912 | + [(set_attr "length" "4,2") | ||
913 | + (set_attr "type" "alu_shift,load_byte") | ||
914 | + (set_attr "pool_range" "*,32")] | ||
915 | ) | ||
916 | |||
917 | (define_insn "*thumb1_zero_extendqisi2_v6" | ||
918 | @@ -4272,14 +4232,17 @@ | ||
919 | ) | ||
920 | |||
921 | (define_insn "*arm_zero_extendqisi2" | ||
922 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
923 | - (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] | ||
924 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
925 | + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | ||
926 | "TARGET_ARM && !arm_arch6" | ||
927 | - "ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" | ||
928 | - [(set_attr "type" "load_byte") | ||
929 | + "@ | ||
930 | + # | ||
931 | + ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" | ||
932 | + [(set_attr "length" "8,4") | ||
933 | + (set_attr "type" "alu_shift,load_byte") | ||
934 | (set_attr "predicable" "yes") | ||
935 | - (set_attr "pool_range" "4096") | ||
936 | - (set_attr "neg_pool_range" "4084")] | ||
937 | + (set_attr "pool_range" "*,4096") | ||
938 | + (set_attr "neg_pool_range" "*,4084")] | ||
939 | ) | ||
940 | |||
941 | (define_insn "*arm_zero_extendqisi2_v6" | ||
942 | @@ -4358,108 +4321,42 @@ | ||
943 | ) | ||
944 | |||
945 | (define_expand "extendhisi2" | ||
946 | - [(set (match_dup 2) | ||
947 | - (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") | ||
948 | - (const_int 16))) | ||
949 | - (set (match_operand:SI 0 "s_register_operand" "") | ||
950 | - (ashiftrt:SI (match_dup 2) | ||
951 | - (const_int 16)))] | ||
952 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
953 | + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] | ||
954 | "TARGET_EITHER" | ||
955 | - " | ||
956 | - { | ||
957 | - if (GET_CODE (operands[1]) == MEM) | ||
958 | - { | ||
959 | - if (TARGET_THUMB1) | ||
960 | - { | ||
961 | - emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); | ||
962 | - DONE; | ||
963 | - } | ||
964 | - else if (arm_arch4) | ||
965 | - { | ||
966 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
967 | - gen_rtx_SIGN_EXTEND (SImode, operands[1]))); | ||
968 | - DONE; | ||
969 | - } | ||
970 | - } | ||
971 | - | ||
972 | - if (TARGET_ARM && GET_CODE (operands[1]) == MEM) | ||
973 | - { | ||
974 | - emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); | ||
975 | - DONE; | ||
976 | - } | ||
977 | - | ||
978 | - if (!s_register_operand (operands[1], HImode)) | ||
979 | - operands[1] = copy_to_mode_reg (HImode, operands[1]); | ||
980 | - | ||
981 | - if (arm_arch6) | ||
982 | - { | ||
983 | - if (TARGET_THUMB1) | ||
984 | - emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); | ||
985 | - else | ||
986 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
987 | - gen_rtx_SIGN_EXTEND (SImode, operands[1]))); | ||
988 | - | ||
989 | - DONE; | ||
990 | - } | ||
991 | - | ||
992 | - operands[1] = gen_lowpart (SImode, operands[1]); | ||
993 | - operands[2] = gen_reg_rtx (SImode); | ||
994 | - }" | ||
995 | -) | ||
996 | - | ||
997 | -(define_insn "thumb1_extendhisi2" | ||
998 | - [(set (match_operand:SI 0 "register_operand" "=l") | ||
999 | - (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))) | ||
1000 | - (clobber (match_scratch:SI 2 "=&l"))] | ||
1001 | - "TARGET_THUMB1 && !arm_arch6" | ||
1002 | - "* | ||
1003 | - { | ||
1004 | - rtx ops[4]; | ||
1005 | - rtx mem = XEXP (operands[1], 0); | ||
1006 | - | ||
1007 | - /* This code used to try to use 'V', and fix the address only if it was | ||
1008 | - offsettable, but this fails for e.g. REG+48 because 48 is outside the | ||
1009 | - range of QImode offsets, and offsettable_address_p does a QImode | ||
1010 | - address check. */ | ||
1011 | - | ||
1012 | - if (GET_CODE (mem) == CONST) | ||
1013 | - mem = XEXP (mem, 0); | ||
1014 | - | ||
1015 | - if (GET_CODE (mem) == LABEL_REF) | ||
1016 | - return \"ldr\\t%0, %1\"; | ||
1017 | - | ||
1018 | - if (GET_CODE (mem) == PLUS) | ||
1019 | - { | ||
1020 | - rtx a = XEXP (mem, 0); | ||
1021 | - rtx b = XEXP (mem, 1); | ||
1022 | - | ||
1023 | - if (GET_CODE (a) == LABEL_REF | ||
1024 | - && GET_CODE (b) == CONST_INT) | ||
1025 | - return \"ldr\\t%0, %1\"; | ||
1026 | - | ||
1027 | - if (GET_CODE (b) == REG) | ||
1028 | - return \"ldrsh\\t%0, %1\"; | ||
1029 | - | ||
1030 | - ops[1] = a; | ||
1031 | - ops[2] = b; | ||
1032 | - } | ||
1033 | - else | ||
1034 | - { | ||
1035 | - ops[1] = mem; | ||
1036 | - ops[2] = const0_rtx; | ||
1037 | - } | ||
1038 | - | ||
1039 | - gcc_assert (GET_CODE (ops[1]) == REG); | ||
1040 | - | ||
1041 | - ops[0] = operands[0]; | ||
1042 | - ops[3] = operands[2]; | ||
1043 | - output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); | ||
1044 | - return \"\"; | ||
1045 | - }" | ||
1046 | - [(set_attr "length" "4") | ||
1047 | - (set_attr "type" "load_byte") | ||
1048 | - (set_attr "pool_range" "1020")] | ||
1049 | -) | ||
1050 | +{ | ||
1051 | + if (TARGET_THUMB1) | ||
1052 | + { | ||
1053 | + emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1])); | ||
1054 | + DONE; | ||
1055 | + } | ||
1056 | + if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4) | ||
1057 | + { | ||
1058 | + emit_insn (gen_extendhisi2_mem (operands[0], operands[1])); | ||
1059 | + DONE; | ||
1060 | + } | ||
1061 | + | ||
1062 | + if (!arm_arch6 && !MEM_P (operands[1])) | ||
1063 | + { | ||
1064 | + rtx t = gen_lowpart (SImode, operands[1]); | ||
1065 | + rtx tmp = gen_reg_rtx (SImode); | ||
1066 | + emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16))); | ||
1067 | + emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16))); | ||
1068 | + DONE; | ||
1069 | + } | ||
1070 | +}) | ||
1071 | + | ||
1072 | +(define_split | ||
1073 | + [(parallel | ||
1074 | + [(set (match_operand:SI 0 "register_operand" "") | ||
1075 | + (sign_extend:SI (match_operand:HI 1 "register_operand" ""))) | ||
1076 | + (clobber (match_scratch:SI 2 ""))])] | ||
1077 | + "!arm_arch6" | ||
1078 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) | ||
1079 | + (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] | ||
1080 | +{ | ||
1081 | + operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0); | ||
1082 | +}) | ||
1083 | |||
1084 | ;; We used to have an early-clobber on the scratch register here. | ||
1085 | ;; However, there's a bug somewhere in reload which means that this | ||
1086 | @@ -4468,16 +4365,18 @@ | ||
1087 | ;; we try to verify the operands. Fortunately, we don't really need | ||
1088 | ;; the early-clobber: we can always use operand 0 if operand 2 | ||
1089 | ;; overlaps the address. | ||
1090 | -(define_insn "*thumb1_extendhisi2_insn_v6" | ||
1091 | +(define_insn "thumb1_extendhisi2" | ||
1092 | [(set (match_operand:SI 0 "register_operand" "=l,l") | ||
1093 | (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m"))) | ||
1094 | (clobber (match_scratch:SI 2 "=X,l"))] | ||
1095 | - "TARGET_THUMB1 && arm_arch6" | ||
1096 | + "TARGET_THUMB1" | ||
1097 | "* | ||
1098 | { | ||
1099 | rtx ops[4]; | ||
1100 | rtx mem; | ||
1101 | |||
1102 | + if (which_alternative == 0 && !arm_arch6) | ||
1103 | + return \"#\"; | ||
1104 | if (which_alternative == 0) | ||
1105 | return \"sxth\\t%0, %1\"; | ||
1106 | |||
1107 | @@ -4525,7 +4424,10 @@ | ||
1108 | output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); | ||
1109 | return \"\"; | ||
1110 | }" | ||
1111 | - [(set_attr "length" "2,4") | ||
1112 | + [(set_attr_alternative "length" | ||
1113 | + [(if_then_else (eq_attr "is_arch6" "yes") | ||
1114 | + (const_int 2) (const_int 4)) | ||
1115 | + (const_int 4)]) | ||
1116 | (set_attr "type" "alu_shift,load_byte") | ||
1117 | (set_attr "pool_range" "*,1020")] | ||
1118 | ) | ||
1119 | @@ -4566,15 +4468,28 @@ | ||
1120 | }" | ||
1121 | ) | ||
1122 | |||
1123 | +(define_split | ||
1124 | + [(set (match_operand:SI 0 "register_operand" "") | ||
1125 | + (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] | ||
1126 | + "!arm_arch6" | ||
1127 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) | ||
1128 | + (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] | ||
1129 | +{ | ||
1130 | + operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0); | ||
1131 | +}) | ||
1132 | + | ||
1133 | (define_insn "*arm_extendhisi2" | ||
1134 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
1135 | - (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | ||
1136 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
1137 | + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | ||
1138 | "TARGET_ARM && arm_arch4 && !arm_arch6" | ||
1139 | - "ldr%(sh%)\\t%0, %1" | ||
1140 | - [(set_attr "type" "load_byte") | ||
1141 | + "@ | ||
1142 | + # | ||
1143 | + ldr%(sh%)\\t%0, %1" | ||
1144 | + [(set_attr "length" "8,4") | ||
1145 | + (set_attr "type" "alu_shift,load_byte") | ||
1146 | (set_attr "predicable" "yes") | ||
1147 | - (set_attr "pool_range" "256") | ||
1148 | - (set_attr "neg_pool_range" "244")] | ||
1149 | + (set_attr "pool_range" "*,256") | ||
1150 | + (set_attr "neg_pool_range" "*,244")] | ||
1151 | ) | ||
1152 | |||
1153 | ;; ??? Check Thumb-2 pool range | ||
1154 | @@ -4636,46 +4551,45 @@ | ||
1155 | ) | ||
1156 | |||
1157 | (define_expand "extendqisi2" | ||
1158 | - [(set (match_dup 2) | ||
1159 | - (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "") | ||
1160 | - (const_int 24))) | ||
1161 | - (set (match_operand:SI 0 "s_register_operand" "") | ||
1162 | - (ashiftrt:SI (match_dup 2) | ||
1163 | - (const_int 24)))] | ||
1164 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
1165 | + (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))] | ||
1166 | "TARGET_EITHER" | ||
1167 | - " | ||
1168 | - { | ||
1169 | - if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM) | ||
1170 | - { | ||
1171 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
1172 | - gen_rtx_SIGN_EXTEND (SImode, operands[1]))); | ||
1173 | - DONE; | ||
1174 | - } | ||
1175 | - | ||
1176 | - if (!s_register_operand (operands[1], QImode)) | ||
1177 | - operands[1] = copy_to_mode_reg (QImode, operands[1]); | ||
1178 | - | ||
1179 | - if (arm_arch6) | ||
1180 | - { | ||
1181 | - emit_insn (gen_rtx_SET (VOIDmode, operands[0], | ||
1182 | - gen_rtx_SIGN_EXTEND (SImode, operands[1]))); | ||
1183 | - DONE; | ||
1184 | - } | ||
1185 | - | ||
1186 | - operands[1] = gen_lowpart (SImode, operands[1]); | ||
1187 | - operands[2] = gen_reg_rtx (SImode); | ||
1188 | - }" | ||
1189 | -) | ||
1190 | +{ | ||
1191 | + if (!arm_arch4 && MEM_P (operands[1])) | ||
1192 | + operands[1] = copy_to_mode_reg (QImode, operands[1]); | ||
1193 | + | ||
1194 | + if (!arm_arch6 && !MEM_P (operands[1])) | ||
1195 | + { | ||
1196 | + rtx t = gen_lowpart (SImode, operands[1]); | ||
1197 | + rtx tmp = gen_reg_rtx (SImode); | ||
1198 | + emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24))); | ||
1199 | + emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24))); | ||
1200 | + DONE; | ||
1201 | + } | ||
1202 | +}) | ||
1203 | + | ||
1204 | +(define_split | ||
1205 | + [(set (match_operand:SI 0 "register_operand" "") | ||
1206 | + (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] | ||
1207 | + "!arm_arch6" | ||
1208 | + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) | ||
1209 | + (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))] | ||
1210 | +{ | ||
1211 | + operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0); | ||
1212 | +}) | ||
1213 | |||
1214 | (define_insn "*arm_extendqisi" | ||
1215 | - [(set (match_operand:SI 0 "s_register_operand" "=r") | ||
1216 | - (sign_extend:SI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))] | ||
1217 | + [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
1218 | + (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))] | ||
1219 | "TARGET_ARM && arm_arch4 && !arm_arch6" | ||
1220 | - "ldr%(sb%)\\t%0, %1" | ||
1221 | - [(set_attr "type" "load_byte") | ||
1222 | + "@ | ||
1223 | + # | ||
1224 | + ldr%(sb%)\\t%0, %1" | ||
1225 | + [(set_attr "length" "8,4") | ||
1226 | + (set_attr "type" "alu_shift,load_byte") | ||
1227 | (set_attr "predicable" "yes") | ||
1228 | - (set_attr "pool_range" "256") | ||
1229 | - (set_attr "neg_pool_range" "244")] | ||
1230 | + (set_attr "pool_range" "*,256") | ||
1231 | + (set_attr "neg_pool_range" "*,244")] | ||
1232 | ) | ||
1233 | |||
1234 | (define_insn "*arm_extendqisi_v6" | ||
1235 | @@ -4703,162 +4617,103 @@ | ||
1236 | (set_attr "predicable" "yes")] | ||
1237 | ) | ||
1238 | |||
1239 | -(define_insn "*thumb1_extendqisi2" | ||
1240 | - [(set (match_operand:SI 0 "register_operand" "=l,l") | ||
1241 | - (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))] | ||
1242 | - "TARGET_THUMB1 && !arm_arch6" | ||
1243 | - "* | ||
1244 | - { | ||
1245 | - rtx ops[3]; | ||
1246 | - rtx mem = XEXP (operands[1], 0); | ||
1247 | - | ||
1248 | - if (GET_CODE (mem) == CONST) | ||
1249 | - mem = XEXP (mem, 0); | ||
1250 | - | ||
1251 | - if (GET_CODE (mem) == LABEL_REF) | ||
1252 | - return \"ldr\\t%0, %1\"; | ||
1253 | - | ||
1254 | - if (GET_CODE (mem) == PLUS | ||
1255 | - && GET_CODE (XEXP (mem, 0)) == LABEL_REF) | ||
1256 | - return \"ldr\\t%0, %1\"; | ||
1257 | - | ||
1258 | - if (which_alternative == 0) | ||
1259 | - return \"ldrsb\\t%0, %1\"; | ||
1260 | - | ||
1261 | - ops[0] = operands[0]; | ||
1262 | - | ||
1263 | - if (GET_CODE (mem) == PLUS) | ||
1264 | - { | ||
1265 | - rtx a = XEXP (mem, 0); | ||
1266 | - rtx b = XEXP (mem, 1); | ||
1267 | - | ||
1268 | - ops[1] = a; | ||
1269 | - ops[2] = b; | ||
1270 | - | ||
1271 | - if (GET_CODE (a) == REG) | ||
1272 | - { | ||
1273 | - if (GET_CODE (b) == REG) | ||
1274 | - output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); | ||
1275 | - else if (REGNO (a) == REGNO (ops[0])) | ||
1276 | - { | ||
1277 | - output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); | ||
1278 | - output_asm_insn (\"lsl\\t%0, %0, #24\", ops); | ||
1279 | - output_asm_insn (\"asr\\t%0, %0, #24\", ops); | ||
1280 | - } | ||
1281 | - else | ||
1282 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
1283 | - } | ||
1284 | - else | ||
1285 | - { | ||
1286 | - gcc_assert (GET_CODE (b) == REG); | ||
1287 | - if (REGNO (b) == REGNO (ops[0])) | ||
1288 | - { | ||
1289 | - output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); | ||
1290 | - output_asm_insn (\"lsl\\t%0, %0, #24\", ops); | ||
1291 | - output_asm_insn (\"asr\\t%0, %0, #24\", ops); | ||
1292 | - } | ||
1293 | - else | ||
1294 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
1295 | - } | ||
1296 | - } | ||
1297 | - else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) | ||
1298 | - { | ||
1299 | - output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); | ||
1300 | - output_asm_insn (\"lsl\\t%0, %0, #24\", ops); | ||
1301 | - output_asm_insn (\"asr\\t%0, %0, #24\", ops); | ||
1302 | - } | ||
1303 | - else | ||
1304 | - { | ||
1305 | - ops[1] = mem; | ||
1306 | - ops[2] = const0_rtx; | ||
1307 | - | ||
1308 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
1309 | - } | ||
1310 | - return \"\"; | ||
1311 | - }" | ||
1312 | - [(set_attr "length" "2,6") | ||
1313 | - (set_attr "type" "load_byte,load_byte") | ||
1314 | - (set_attr "pool_range" "32,32")] | ||
1315 | -) | ||
1316 | - | ||
1317 | -(define_insn "*thumb1_extendqisi2_v6" | ||
1318 | +(define_split | ||
1319 | + [(set (match_operand:SI 0 "register_operand" "") | ||
1320 | + (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))] | ||
1321 | + "TARGET_THUMB1 && reload_completed" | ||
1322 | + [(set (match_dup 0) (match_dup 2)) | ||
1323 | + (set (match_dup 0) (sign_extend:SI (match_dup 3)))] | ||
1324 | +{ | ||
1325 | + rtx addr = XEXP (operands[1], 0); | ||
1326 | + | ||
1327 | + if (GET_CODE (addr) == CONST) | ||
1328 | + addr = XEXP (addr, 0); | ||
1329 | + | ||
1330 | + if (GET_CODE (addr) == PLUS | ||
1331 | + && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1))) | ||
1332 | + /* No split necessary. */ | ||
1333 | + FAIL; | ||
1334 | + | ||
1335 | + if (GET_CODE (addr) == PLUS | ||
1336 | + && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1))) | ||
1337 | + FAIL; | ||
1338 | + | ||
1339 | + if (reg_overlap_mentioned_p (operands[0], addr)) | ||
1340 | + { | ||
1341 | + rtx t = gen_lowpart (QImode, operands[0]); | ||
1342 | + emit_move_insn (t, operands[1]); | ||
1343 | + emit_insn (gen_thumb1_extendqisi2 (operands[0], t)); | ||
1344 | + DONE; | ||
1345 | + } | ||
1346 | + | ||
1347 | + if (REG_P (addr)) | ||
1348 | + { | ||
1349 | + addr = gen_rtx_PLUS (Pmode, addr, operands[0]); | ||
1350 | + operands[2] = const0_rtx; | ||
1351 | + } | ||
1352 | + else if (GET_CODE (addr) != PLUS) | ||
1353 | + FAIL; | ||
1354 | + else if (REG_P (XEXP (addr, 0))) | ||
1355 | + { | ||
1356 | + operands[2] = XEXP (addr, 1); | ||
1357 | + addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]); | ||
1358 | + } | ||
1359 | + else | ||
1360 | + { | ||
1361 | + operands[2] = XEXP (addr, 0); | ||
1362 | + addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]); | ||
1363 | + } | ||
1364 | + | ||
1365 | + operands[3] = change_address (operands[1], QImode, addr); | ||
1366 | +}) | ||
1367 | + | ||
1368 | +(define_peephole2 | ||
1369 | + [(set (match_operand:SI 0 "register_operand" "") | ||
1370 | + (plus:SI (match_dup 0) (match_operand 1 "const_int_operand"))) | ||
1371 | + (set (match_operand:SI 2 "register_operand" "") (const_int 0)) | ||
1372 | + (set (match_operand:SI 3 "register_operand" "") | ||
1373 | + (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))] | ||
1374 | + "TARGET_THUMB1 | ||
1375 | + && GET_CODE (XEXP (operands[4], 0)) == PLUS | ||
1376 | + && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0)) | ||
1377 | + && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1)) | ||
1378 | + && (peep2_reg_dead_p (3, operands[0]) | ||
1379 | + || rtx_equal_p (operands[0], operands[3])) | ||
1380 | + && (peep2_reg_dead_p (3, operands[2]) | ||
1381 | + || rtx_equal_p (operands[2], operands[3]))" | ||
1382 | + [(set (match_dup 2) (match_dup 1)) | ||
1383 | + (set (match_dup 3) (sign_extend:SI (match_dup 4)))] | ||
1384 | +{ | ||
1385 | + rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]); | ||
1386 | + operands[4] = change_address (operands[4], QImode, addr); | ||
1387 | +}) | ||
1388 | + | ||
1389 | +(define_insn "thumb1_extendqisi2" | ||
1390 | [(set (match_operand:SI 0 "register_operand" "=l,l,l") | ||
1391 | (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))] | ||
1392 | - "TARGET_THUMB1 && arm_arch6" | ||
1393 | - "* | ||
1394 | - { | ||
1395 | - rtx ops[3]; | ||
1396 | - rtx mem; | ||
1397 | - | ||
1398 | - if (which_alternative == 0) | ||
1399 | - return \"sxtb\\t%0, %1\"; | ||
1400 | - | ||
1401 | - mem = XEXP (operands[1], 0); | ||
1402 | - | ||
1403 | - if (GET_CODE (mem) == CONST) | ||
1404 | - mem = XEXP (mem, 0); | ||
1405 | - | ||
1406 | - if (GET_CODE (mem) == LABEL_REF) | ||
1407 | - return \"ldr\\t%0, %1\"; | ||
1408 | - | ||
1409 | - if (GET_CODE (mem) == PLUS | ||
1410 | - && GET_CODE (XEXP (mem, 0)) == LABEL_REF) | ||
1411 | - return \"ldr\\t%0, %1\"; | ||
1412 | - | ||
1413 | - if (which_alternative == 0) | ||
1414 | - return \"ldrsb\\t%0, %1\"; | ||
1415 | - | ||
1416 | - ops[0] = operands[0]; | ||
1417 | - | ||
1418 | - if (GET_CODE (mem) == PLUS) | ||
1419 | - { | ||
1420 | - rtx a = XEXP (mem, 0); | ||
1421 | - rtx b = XEXP (mem, 1); | ||
1422 | - | ||
1423 | - ops[1] = a; | ||
1424 | - ops[2] = b; | ||
1425 | - | ||
1426 | - if (GET_CODE (a) == REG) | ||
1427 | - { | ||
1428 | - if (GET_CODE (b) == REG) | ||
1429 | - output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops); | ||
1430 | - else if (REGNO (a) == REGNO (ops[0])) | ||
1431 | - { | ||
1432 | - output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops); | ||
1433 | - output_asm_insn (\"sxtb\\t%0, %0\", ops); | ||
1434 | - } | ||
1435 | - else | ||
1436 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
1437 | - } | ||
1438 | - else | ||
1439 | - { | ||
1440 | - gcc_assert (GET_CODE (b) == REG); | ||
1441 | - if (REGNO (b) == REGNO (ops[0])) | ||
1442 | - { | ||
1443 | - output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops); | ||
1444 | - output_asm_insn (\"sxtb\\t%0, %0\", ops); | ||
1445 | - } | ||
1446 | - else | ||
1447 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
1448 | - } | ||
1449 | - } | ||
1450 | - else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem)) | ||
1451 | - { | ||
1452 | - output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops); | ||
1453 | - output_asm_insn (\"sxtb\\t%0, %0\", ops); | ||
1454 | - } | ||
1455 | - else | ||
1456 | - { | ||
1457 | - ops[1] = mem; | ||
1458 | - ops[2] = const0_rtx; | ||
1459 | - | ||
1460 | - output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops); | ||
1461 | - } | ||
1462 | - return \"\"; | ||
1463 | - }" | ||
1464 | - [(set_attr "length" "2,2,4") | ||
1465 | - (set_attr "type" "alu_shift,load_byte,load_byte") | ||
1466 | - (set_attr "pool_range" "*,32,32")] | ||
1467 | + "TARGET_THUMB1" | ||
1468 | +{ | ||
1469 | + rtx addr; | ||
1470 | + | ||
1471 | + if (which_alternative == 0 && arm_arch6) | ||
1472 | + return "sxtb\\t%0, %1"; | ||
1473 | + if (which_alternative == 0) | ||
1474 | + return "#"; | ||
1475 | + | ||
1476 | + addr = XEXP (operands[1], 0); | ||
1477 | + if (GET_CODE (addr) == PLUS | ||
1478 | + && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1))) | ||
1479 | + return "ldrsb\\t%0, %1"; | ||
1480 | + | ||
1481 | + return "#"; | ||
1482 | +} | ||
1483 | + [(set_attr_alternative "length" | ||
1484 | + [(if_then_else (eq_attr "is_arch6" "yes") | ||
1485 | + (const_int 2) (const_int 4)) | ||
1486 | + (const_int 2) | ||
1487 | + (if_then_else (eq_attr "is_arch6" "yes") | ||
1488 | + (const_int 4) (const_int 6))]) | ||
1489 | + (set_attr "type" "alu_shift,load_byte,load_byte")] | ||
1490 | ) | ||
1491 | |||
1492 | (define_expand "extendsfdf2" | ||
1493 | @@ -6784,6 +6639,30 @@ | ||
1494 | operands[2] = force_reg (SImode, operands[2]); | ||
1495 | ") | ||
1496 | |||
1497 | +;; A pattern to recognize a special situation and optimize for it. | ||
1498 | +;; On the thumb, zero-extension from memory is preferrable to sign-extension | ||
1499 | +;; due to the available addressing modes. Hence, convert a signed comparison | ||
1500 | +;; with zero into an unsigned comparison with 127 if possible. | ||
1501 | +(define_expand "cbranchqi4" | ||
1502 | + [(set (pc) (if_then_else | ||
1503 | + (match_operator 0 "lt_ge_comparison_operator" | ||
1504 | + [(match_operand:QI 1 "memory_operand" "") | ||
1505 | + (match_operand:QI 2 "const0_operand" "")]) | ||
1506 | + (label_ref (match_operand 3 "" "")) | ||
1507 | + (pc)))] | ||
1508 | + "TARGET_THUMB1" | ||
1509 | +{ | ||
1510 | + rtx xops[4]; | ||
1511 | + xops[1] = gen_reg_rtx (SImode); | ||
1512 | + emit_insn (gen_zero_extendqisi2 (xops[1], operands[1])); | ||
1513 | + xops[2] = GEN_INT (127); | ||
1514 | + xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU, | ||
1515 | + VOIDmode, xops[1], xops[2]); | ||
1516 | + xops[3] = operands[3]; | ||
1517 | + emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3])); | ||
1518 | + DONE; | ||
1519 | +}) | ||
1520 | + | ||
1521 | (define_expand "cbranchsf4" | ||
1522 | [(set (pc) (if_then_else | ||
1523 | (match_operator 0 "arm_comparison_operator" | ||
1524 | @@ -6849,7 +6728,7 @@ | ||
1525 | }" | ||
1526 | ) | ||
1527 | |||
1528 | -(define_insn "*cbranchsi4_insn" | ||
1529 | +(define_insn "cbranchsi4_insn" | ||
1530 | [(set (pc) (if_then_else | ||
1531 | (match_operator 0 "arm_comparison_operator" | ||
1532 | [(match_operand:SI 1 "s_register_operand" "l,*h") | ||
1533 | @@ -6858,7 +6737,20 @@ | ||
1534 | (pc)))] | ||
1535 | "TARGET_THUMB1" | ||
1536 | "* | ||
1537 | - output_asm_insn (\"cmp\\t%1, %2\", operands); | ||
1538 | + rtx t = prev_nonnote_insn (insn); | ||
1539 | + if (t != NULL_RTX | ||
1540 | + && INSN_P (t) | ||
1541 | + && INSN_CODE (t) == CODE_FOR_cbranchsi4_insn) | ||
1542 | + { | ||
1543 | + t = XEXP (SET_SRC (PATTERN (t)), 0); | ||
1544 | + if (!rtx_equal_p (XEXP (t, 0), operands[1]) | ||
1545 | + || !rtx_equal_p (XEXP (t, 1), operands[2])) | ||
1546 | + t = NULL_RTX; | ||
1547 | + } | ||
1548 | + else | ||
1549 | + t = NULL_RTX; | ||
1550 | + if (t == NULL_RTX) | ||
1551 | + output_asm_insn (\"cmp\\t%1, %2\", operands); | ||
1552 | |||
1553 | switch (get_attr_length (insn)) | ||
1554 | { | ||
1555 | @@ -7674,15 +7566,15 @@ | ||
1556 | (if_then_else | ||
1557 | (match_operator 4 "arm_comparison_operator" | ||
1558 | [(plus:SI | ||
1559 | - (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1") | ||
1560 | - (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ")) | ||
1561 | + (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1") | ||
1562 | + (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ")) | ||
1563 | (const_int 0)]) | ||
1564 | (label_ref (match_operand 5 "" "")) | ||
1565 | (pc))) | ||
1566 | (set | ||
1567 | (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m") | ||
1568 | (plus:SI (match_dup 2) (match_dup 3))) | ||
1569 | - (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))] | ||
1570 | + (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))] | ||
1571 | "TARGET_THUMB1 | ||
1572 | && (GET_CODE (operands[4]) == EQ | ||
1573 | || GET_CODE (operands[4]) == NE | ||
1574 | @@ -7692,8 +7584,7 @@ | ||
1575 | { | ||
1576 | rtx cond[3]; | ||
1577 | |||
1578 | - | ||
1579 | - cond[0] = (which_alternative < 3) ? operands[0] : operands[1]; | ||
1580 | + cond[0] = (which_alternative < 2) ? operands[0] : operands[1]; | ||
1581 | cond[1] = operands[2]; | ||
1582 | cond[2] = operands[3]; | ||
1583 | |||
1584 | @@ -7702,13 +7593,13 @@ | ||
1585 | else | ||
1586 | output_asm_insn (\"add\\t%0, %1, %2\", cond); | ||
1587 | |||
1588 | - if (which_alternative >= 3 | ||
1589 | + if (which_alternative >= 2 | ||
1590 | && which_alternative < 4) | ||
1591 | output_asm_insn (\"mov\\t%0, %1\", operands); | ||
1592 | else if (which_alternative >= 4) | ||
1593 | output_asm_insn (\"str\\t%1, %0\", operands); | ||
1594 | |||
1595 | - switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0)) | ||
1596 | + switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0)) | ||
1597 | { | ||
1598 | case 4: | ||
1599 | return \"b%d4\\t%l5\"; | ||
1600 | @@ -7722,7 +7613,7 @@ | ||
1601 | [(set (attr "far_jump") | ||
1602 | (if_then_else | ||
1603 | (ior (and (lt (symbol_ref ("which_alternative")) | ||
1604 | - (const_int 3)) | ||
1605 | + (const_int 2)) | ||
1606 | (eq_attr "length" "8")) | ||
1607 | (eq_attr "length" "10")) | ||
1608 | (const_string "yes") | ||
1609 | @@ -7730,7 +7621,7 @@ | ||
1610 | (set (attr "length") | ||
1611 | (if_then_else | ||
1612 | (lt (symbol_ref ("which_alternative")) | ||
1613 | - (const_int 3)) | ||
1614 | + (const_int 2)) | ||
1615 | (if_then_else | ||
1616 | (and (ge (minus (match_dup 5) (pc)) (const_int -250)) | ||
1617 | (le (minus (match_dup 5) (pc)) (const_int 256))) | ||
1618 | @@ -9483,41 +9374,117 @@ | ||
1619 | (set_attr "length" "4,8")] | ||
1620 | ) | ||
1621 | |||
1622 | -(define_insn "*compare_scc" | ||
1623 | +; A series of splitters for the compare_scc pattern below. Note that | ||
1624 | +; order is important. | ||
1625 | +(define_split | ||
1626 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
1627 | + (lt:SI (match_operand:SI 1 "s_register_operand" "") | ||
1628 | + (const_int 0))) | ||
1629 | + (clobber (reg:CC CC_REGNUM))] | ||
1630 | + "TARGET_32BIT && reload_completed" | ||
1631 | + [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))]) | ||
1632 | + | ||
1633 | +(define_split | ||
1634 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
1635 | + (ge:SI (match_operand:SI 1 "s_register_operand" "") | ||
1636 | + (const_int 0))) | ||
1637 | + (clobber (reg:CC CC_REGNUM))] | ||
1638 | + "TARGET_32BIT && reload_completed" | ||
1639 | + [(set (match_dup 0) (not:SI (match_dup 1))) | ||
1640 | + (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))]) | ||
1641 | + | ||
1642 | +(define_split | ||
1643 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
1644 | + (eq:SI (match_operand:SI 1 "s_register_operand" "") | ||
1645 | + (const_int 0))) | ||
1646 | + (clobber (reg:CC CC_REGNUM))] | ||
1647 | + "TARGET_32BIT && reload_completed" | ||
1648 | + [(parallel | ||
1649 | + [(set (reg:CC CC_REGNUM) | ||
1650 | + (compare:CC (const_int 1) (match_dup 1))) | ||
1651 | + (set (match_dup 0) | ||
1652 | + (minus:SI (const_int 1) (match_dup 1)))]) | ||
1653 | + (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0)) | ||
1654 | + (set (match_dup 0) (const_int 0)))]) | ||
1655 | + | ||
1656 | +(define_split | ||
1657 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
1658 | + (ne:SI (match_operand:SI 1 "s_register_operand" "") | ||
1659 | + (match_operand:SI 2 "const_int_operand" ""))) | ||
1660 | + (clobber (reg:CC CC_REGNUM))] | ||
1661 | + "TARGET_32BIT && reload_completed" | ||
1662 | + [(parallel | ||
1663 | + [(set (reg:CC CC_REGNUM) | ||
1664 | + (compare:CC (match_dup 1) (match_dup 2))) | ||
1665 | + (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]) | ||
1666 | + (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0)) | ||
1667 | + (set (match_dup 0) (const_int 1)))] | ||
1668 | +{ | ||
1669 | + operands[3] = GEN_INT (-INTVAL (operands[2])); | ||
1670 | +}) | ||
1671 | + | ||
1672 | +(define_split | ||
1673 | + [(set (match_operand:SI 0 "s_register_operand" "") | ||
1674 | + (ne:SI (match_operand:SI 1 "s_register_operand" "") | ||
1675 | + (match_operand:SI 2 "arm_add_operand" ""))) | ||
1676 | + (clobber (reg:CC CC_REGNUM))] | ||
1677 | + "TARGET_32BIT && reload_completed" | ||
1678 | + [(parallel | ||
1679 | + [(set (reg:CC_NOOV CC_REGNUM) | ||
1680 | + (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2)) | ||
1681 | + (const_int 0))) | ||
1682 | + (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))]) | ||
1683 | + (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0)) | ||
1684 | + (set (match_dup 0) (const_int 1)))]) | ||
1685 | + | ||
1686 | +(define_insn_and_split "*compare_scc" | ||
1687 | [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
1688 | (match_operator:SI 1 "arm_comparison_operator" | ||
1689 | [(match_operand:SI 2 "s_register_operand" "r,r") | ||
1690 | (match_operand:SI 3 "arm_add_operand" "rI,L")])) | ||
1691 | (clobber (reg:CC CC_REGNUM))] | ||
1692 | - "TARGET_ARM" | ||
1693 | - "* | ||
1694 | - if (operands[3] == const0_rtx) | ||
1695 | - { | ||
1696 | - if (GET_CODE (operands[1]) == LT) | ||
1697 | - return \"mov\\t%0, %2, lsr #31\"; | ||
1698 | - | ||
1699 | - if (GET_CODE (operands[1]) == GE) | ||
1700 | - return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\"; | ||
1701 | - | ||
1702 | - if (GET_CODE (operands[1]) == EQ) | ||
1703 | - return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\"; | ||
1704 | - } | ||
1705 | - | ||
1706 | - if (GET_CODE (operands[1]) == NE) | ||
1707 | - { | ||
1708 | - if (which_alternative == 1) | ||
1709 | - return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\"; | ||
1710 | - return \"subs\\t%0, %2, %3\;movne\\t%0, #1\"; | ||
1711 | - } | ||
1712 | - if (which_alternative == 1) | ||
1713 | - output_asm_insn (\"cmn\\t%2, #%n3\", operands); | ||
1714 | - else | ||
1715 | - output_asm_insn (\"cmp\\t%2, %3\", operands); | ||
1716 | - return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; | ||
1717 | - " | ||
1718 | - [(set_attr "conds" "clob") | ||
1719 | - (set_attr "length" "12")] | ||
1720 | -) | ||
1721 | + "TARGET_32BIT" | ||
1722 | + "#" | ||
1723 | + "&& reload_completed" | ||
1724 | + [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3))) | ||
1725 | + (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0))) | ||
1726 | + (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))] | ||
1727 | +{ | ||
1728 | + rtx tmp1; | ||
1729 | + enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), | ||
1730 | + operands[2], operands[3]); | ||
1731 | + enum rtx_code rc = GET_CODE (operands[1]); | ||
1732 | + | ||
1733 | + tmp1 = gen_rtx_REG (mode, CC_REGNUM); | ||
1734 | + | ||
1735 | + operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx); | ||
1736 | + if (mode == CCFPmode || mode == CCFPEmode) | ||
1737 | + rc = reverse_condition_maybe_unordered (rc); | ||
1738 | + else | ||
1739 | + rc = reverse_condition (rc); | ||
1740 | + operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx); | ||
1741 | +}) | ||
1742 | + | ||
1743 | +;; Attempt to improve the sequence generated by the compare_scc splitters | ||
1744 | +;; not to use conditional execution. | ||
1745 | +(define_peephole2 | ||
1746 | + [(set (reg:CC CC_REGNUM) | ||
1747 | + (compare:CC (match_operand:SI 1 "register_operand" "") | ||
1748 | + (match_operand:SI 2 "arm_rhs_operand" ""))) | ||
1749 | + (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0)) | ||
1750 | + (set (match_operand:SI 0 "register_operand" "") (const_int 0))) | ||
1751 | + (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0)) | ||
1752 | + (set (match_dup 0) (const_int 1))) | ||
1753 | + (match_scratch:SI 3 "r")] | ||
1754 | + "TARGET_32BIT" | ||
1755 | + [(set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2))) | ||
1756 | + (parallel | ||
1757 | + [(set (reg:CC CC_REGNUM) | ||
1758 | + (compare:CC (const_int 0) (match_dup 3))) | ||
1759 | + (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))]) | ||
1760 | + (set (match_dup 0) | ||
1761 | + (plus:SI (plus:SI (match_dup 0) (match_dup 3)) | ||
1762 | + (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]) | ||
1763 | |||
1764 | (define_insn "*cond_move" | ||
1765 | [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | ||
1766 | |||
1767 | === modified file 'gcc/config/arm/predicates.md' | ||
1768 | --- old/gcc/config/arm/predicates.md 2010-08-31 09:40:16 +0000 | ||
1769 | +++ new/gcc/config/arm/predicates.md 2010-08-31 10:00:27 +0000 | ||
1770 | @@ -115,6 +115,10 @@ | ||
1771 | (and (match_code "const_int") | ||
1772 | (match_test "const_ok_for_arm (~INTVAL (op))"))) | ||
1773 | |||
1774 | +(define_predicate "const0_operand" | ||
1775 | + (and (match_code "const_int") | ||
1776 | + (match_test "INTVAL (op) == 0"))) | ||
1777 | + | ||
1778 | ;; Something valid on the RHS of an ARM data-processing instruction | ||
1779 | (define_predicate "arm_rhs_operand" | ||
1780 | (ior (match_operand 0 "s_register_operand") | ||
1781 | @@ -233,6 +237,9 @@ | ||
1782 | && (TARGET_FPA || TARGET_VFP)") | ||
1783 | (match_code "unordered,ordered,unlt,unle,unge,ungt")))) | ||
1784 | |||
1785 | +(define_special_predicate "lt_ge_comparison_operator" | ||
1786 | + (match_code "lt,ge")) | ||
1787 | + | ||
1788 | (define_special_predicate "minmax_operator" | ||
1789 | (and (match_code "smin,smax,umin,umax") | ||
1790 | (match_test "mode == GET_MODE (op)"))) | ||
1791 | |||
1792 | === modified file 'gcc/config/arm/thumb2.md' | ||
1793 | --- old/gcc/config/arm/thumb2.md 2010-08-31 09:40:16 +0000 | ||
1794 | +++ new/gcc/config/arm/thumb2.md 2010-08-31 10:00:27 +0000 | ||
1795 | @@ -599,42 +599,6 @@ | ||
1796 | (set_attr "length" "6,10")] | ||
1797 | ) | ||
1798 | |||
1799 | -(define_insn "*thumb2_compare_scc" | ||
1800 | - [(set (match_operand:SI 0 "s_register_operand" "=r,r") | ||
1801 | - (match_operator:SI 1 "arm_comparison_operator" | ||
1802 | - [(match_operand:SI 2 "s_register_operand" "r,r") | ||
1803 | - (match_operand:SI 3 "arm_add_operand" "rI,L")])) | ||
1804 | - (clobber (reg:CC CC_REGNUM))] | ||
1805 | - "TARGET_THUMB2" | ||
1806 | - "* | ||
1807 | - if (operands[3] == const0_rtx) | ||
1808 | - { | ||
1809 | - if (GET_CODE (operands[1]) == LT) | ||
1810 | - return \"lsr\\t%0, %2, #31\"; | ||
1811 | - | ||
1812 | - if (GET_CODE (operands[1]) == GE) | ||
1813 | - return \"mvn\\t%0, %2\;lsr\\t%0, %0, #31\"; | ||
1814 | - | ||
1815 | - if (GET_CODE (operands[1]) == EQ) | ||
1816 | - return \"rsbs\\t%0, %2, #1\;it\\tcc\;movcc\\t%0, #0\"; | ||
1817 | - } | ||
1818 | - | ||
1819 | - if (GET_CODE (operands[1]) == NE) | ||
1820 | - { | ||
1821 | - if (which_alternative == 1) | ||
1822 | - return \"adds\\t%0, %2, #%n3\;it\\tne\;movne\\t%0, #1\"; | ||
1823 | - return \"subs\\t%0, %2, %3\;it\\tne\;movne\\t%0, #1\"; | ||
1824 | - } | ||
1825 | - if (which_alternative == 1) | ||
1826 | - output_asm_insn (\"cmn\\t%2, #%n3\", operands); | ||
1827 | - else | ||
1828 | - output_asm_insn (\"cmp\\t%2, %3\", operands); | ||
1829 | - return \"ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; | ||
1830 | - " | ||
1831 | - [(set_attr "conds" "clob") | ||
1832 | - (set_attr "length" "14")] | ||
1833 | -) | ||
1834 | - | ||
1835 | (define_insn "*thumb2_cond_move" | ||
1836 | [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | ||
1837 | (if_then_else:SI (match_operator 3 "equality_operator" | ||
1838 | |||
1839 | === added file 'gcc/testsuite/gcc.c-torture/execute/pr40657.c' | ||
1840 | --- old/gcc/testsuite/gcc.c-torture/execute/pr40657.c 1970-01-01 00:00:00 +0000 | ||
1841 | +++ new/gcc/testsuite/gcc.c-torture/execute/pr40657.c 2010-08-31 10:00:27 +0000 | ||
1842 | @@ -0,0 +1,23 @@ | ||
1843 | +/* Verify that that Thumb-1 epilogue size optimization does not clobber the | ||
1844 | + return value. */ | ||
1845 | + | ||
1846 | +long long v = 0x123456789abc; | ||
1847 | + | ||
1848 | +__attribute__((noinline)) void bar (int *x) | ||
1849 | +{ | ||
1850 | + asm volatile ("" : "=m" (x) ::); | ||
1851 | +} | ||
1852 | + | ||
1853 | +__attribute__((noinline)) long long foo() | ||
1854 | +{ | ||
1855 | + int x; | ||
1856 | + bar(&x); | ||
1857 | + return v; | ||
1858 | +} | ||
1859 | + | ||
1860 | +int main () | ||
1861 | +{ | ||
1862 | + if (foo () != v) | ||
1863 | + abort (); | ||
1864 | + exit (0); | ||
1865 | +} | ||
1866 | |||
1867 | === added file 'gcc/testsuite/gcc.target/arm/pr40657-1.c' | ||
1868 | --- old/gcc/testsuite/gcc.target/arm/pr40657-1.c 1970-01-01 00:00:00 +0000 | ||
1869 | +++ new/gcc/testsuite/gcc.target/arm/pr40657-1.c 2010-08-31 10:00:27 +0000 | ||
1870 | @@ -0,0 +1,13 @@ | ||
1871 | +/* { dg-options "-Os -march=armv5te -mthumb" } */ | ||
1872 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
1873 | +/* { dg-final { scan-assembler "pop.*r1.*pc" } } */ | ||
1874 | +/* { dg-final { scan-assembler-not "sub\[\\t \]*sp,\[\\t \]*sp" } } */ | ||
1875 | +/* { dg-final { scan-assembler-not "add\[\\t \]*sp,\[\\t \]*sp" } } */ | ||
1876 | + | ||
1877 | +extern void bar(int*); | ||
1878 | +int foo() | ||
1879 | +{ | ||
1880 | + int x; | ||
1881 | + bar(&x); | ||
1882 | + return x; | ||
1883 | +} | ||
1884 | |||
1885 | === added file 'gcc/testsuite/gcc.target/arm/pr40657-2.c' | ||
1886 | --- old/gcc/testsuite/gcc.target/arm/pr40657-2.c 1970-01-01 00:00:00 +0000 | ||
1887 | +++ new/gcc/testsuite/gcc.target/arm/pr40657-2.c 2010-08-31 10:00:27 +0000 | ||
1888 | @@ -0,0 +1,20 @@ | ||
1889 | +/* { dg-options "-Os -march=armv4t -mthumb" } */ | ||
1890 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
1891 | +/* { dg-final { scan-assembler-not "sub\[\\t \]*sp,\[\\t \]*sp" } } */ | ||
1892 | +/* { dg-final { scan-assembler-not "add\[\\t \]*sp,\[\\t \]*sp" } } */ | ||
1893 | + | ||
1894 | +/* Here, we test that if there's a pop of r[4567] in the epilogue, | ||
1895 | + add sp,sp,#12 is removed and replaced by three additional pops | ||
1896 | + of lower-numbered regs. */ | ||
1897 | + | ||
1898 | +extern void bar(int*); | ||
1899 | + | ||
1900 | +int t1, t2, t3, t4, t5; | ||
1901 | +int foo() | ||
1902 | +{ | ||
1903 | + int i,j,k,x = 0; | ||
1904 | + for (i = 0; i < t1; i++) | ||
1905 | + for (j = 0; j < t2; j++) | ||
1906 | + bar(&x); | ||
1907 | + return x; | ||
1908 | +} | ||
1909 | |||
1910 | === added file 'gcc/testsuite/gcc.target/arm/pr42172-1.c' | ||
1911 | --- old/gcc/testsuite/gcc.target/arm/pr42172-1.c 1970-01-01 00:00:00 +0000 | ||
1912 | +++ new/gcc/testsuite/gcc.target/arm/pr42172-1.c 2010-08-31 10:00:27 +0000 | ||
1913 | @@ -0,0 +1,19 @@ | ||
1914 | +/* { dg-options "-O2" } */ | ||
1915 | + | ||
1916 | +struct A { | ||
1917 | + unsigned int f1 : 3; | ||
1918 | + unsigned int f2 : 3; | ||
1919 | + unsigned int f3 : 1; | ||
1920 | + unsigned int f4 : 1; | ||
1921 | + | ||
1922 | +}; | ||
1923 | + | ||
1924 | +void init_A (struct A *this) | ||
1925 | +{ | ||
1926 | + this->f1 = 0; | ||
1927 | + this->f2 = 1; | ||
1928 | + this->f3 = 0; | ||
1929 | + this->f4 = 0; | ||
1930 | +} | ||
1931 | + | ||
1932 | +/* { dg-final { scan-assembler-times "ldr" 1 } } */ | ||
1933 | |||
1934 | === added file 'gcc/testsuite/gcc.target/arm/pr42835.c' | ||
1935 | --- old/gcc/testsuite/gcc.target/arm/pr42835.c 1970-01-01 00:00:00 +0000 | ||
1936 | +++ new/gcc/testsuite/gcc.target/arm/pr42835.c 2010-08-31 10:00:27 +0000 | ||
1937 | @@ -0,0 +1,12 @@ | ||
1938 | +/* { dg-do compile } */ | ||
1939 | +/* { dg-options "-mthumb -Os" } */ | ||
1940 | +/* { dg-require-effective-target arm_thumb2_ok } */ | ||
1941 | + | ||
1942 | +int foo(int *p, int i) | ||
1943 | +{ | ||
1944 | + return( (i < 0 && *p == 1) | ||
1945 | + || (i > 0 && *p == 2) ); | ||
1946 | +} | ||
1947 | + | ||
1948 | +/* { dg-final { scan-assembler-times "movne\[\\t \]*r.,\[\\t \]*#" 1 } } */ | ||
1949 | +/* { dg-final { scan-assembler-times "moveq\[\\t \]*r.,\[\\t \]*#" 1 } } */ | ||
1950 | |||
1951 | === added file 'gcc/testsuite/gcc.target/arm/thumb-cbranchqi.c' | ||
1952 | --- old/gcc/testsuite/gcc.target/arm/thumb-cbranchqi.c 1970-01-01 00:00:00 +0000 | ||
1953 | +++ new/gcc/testsuite/gcc.target/arm/thumb-cbranchqi.c 2010-08-31 10:00:27 +0000 | ||
1954 | @@ -0,0 +1,15 @@ | ||
1955 | +/* { dg-do compile } */ | ||
1956 | +/* { dg-options "-mthumb -Os" } */ | ||
1957 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
1958 | + | ||
1959 | +int ldrb(unsigned char* p) | ||
1960 | +{ | ||
1961 | + if (p[8] <= 0x7F) | ||
1962 | + return 2; | ||
1963 | + else | ||
1964 | + return 5; | ||
1965 | +} | ||
1966 | + | ||
1967 | + | ||
1968 | +/* { dg-final { scan-assembler "127" } } */ | ||
1969 | +/* { dg-final { scan-assembler "bhi" } } */ | ||
1970 | |||
1971 | === added file 'gcc/testsuite/gcc.target/arm/thumb-comparisons.c' | ||
1972 | --- old/gcc/testsuite/gcc.target/arm/thumb-comparisons.c 1970-01-01 00:00:00 +0000 | ||
1973 | +++ new/gcc/testsuite/gcc.target/arm/thumb-comparisons.c 2010-08-31 10:00:27 +0000 | ||
1974 | @@ -0,0 +1,18 @@ | ||
1975 | +/* { dg-do compile } */ | ||
1976 | +/* { dg-options "-mthumb -Os" } */ | ||
1977 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
1978 | + | ||
1979 | +int foo(char ch) | ||
1980 | +{ | ||
1981 | + switch (ch) { | ||
1982 | + case '-': | ||
1983 | + case '?': | ||
1984 | + case '/': | ||
1985 | + case 99: | ||
1986 | + return 1; | ||
1987 | + default: | ||
1988 | + return 0; | ||
1989 | + } | ||
1990 | +} | ||
1991 | + | ||
1992 | +/* { dg-final { scan-assembler-times "cmp\[\\t \]*r.,\[\\t \]*#63" 1 } } */ | ||
1993 | |||
1994 | === added file 'gcc/testsuite/gcc.target/arm/thumb-stackframe.c' | ||
1995 | --- old/gcc/testsuite/gcc.target/arm/thumb-stackframe.c 1970-01-01 00:00:00 +0000 | ||
1996 | +++ new/gcc/testsuite/gcc.target/arm/thumb-stackframe.c 2010-08-31 10:00:27 +0000 | ||
1997 | @@ -0,0 +1,13 @@ | ||
1998 | +/* { dg-do compile } */ | ||
1999 | +/* { dg-options "-mthumb -Os" } */ | ||
2000 | +/* { dg-require-effective-target arm_thumb1_ok } */ | ||
2001 | + | ||
2002 | +extern void bar(int*); | ||
2003 | +int foo() | ||
2004 | +{ | ||
2005 | + int x; | ||
2006 | + bar(&x); | ||
2007 | + return x; | ||
2008 | +} | ||
2009 | + | ||
2010 | +/* { dg-final { scan-assembler-not "sub\[\\t \]*sp,\[\\t \]*sp," } } */ | ||
2011 | |||