summaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99379.patch
diff options
context:
space:
mode:
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.patch2011
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 @@
12010-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