summaryrefslogtreecommitdiffstats
path: root/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch')
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch4217
1 files changed, 4217 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch
new file mode 100644
index 0000000000..aa9d6aa368
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch
@@ -0,0 +1,4217 @@
12011-02-08 Andrew Stubbs <ams@codesourcery.com>
2
3 Backport from FSF mainline:
4
5 2010-06-30 H.J. Lu <hongjiu.lu@intel.com>
6
7 PR target/44721
8 * config/i386/i386.md (peephole2 for arithmetic ops with memory):
9 Fix last commit.
10
11 2010-06-30 Richard Guenther <rguenther@suse.de>
12
13 PR target/44722
14 * config/i386/i386.md (peephole2 for fix:SSEMODEI24): Guard
15 against oscillation with reverse peephole2.
16
17 2010-07-01 Bernd Schmidt <bernds@codesourcery.com>
18
19 PR target/44727
20 * config/i386/i386.md (peephole2 for arithmetic ops with memory):
21 Make sure operand 0 dies.
22
232010-12-03 Yao Qi <yao@codesourcery.com>
24
25 * config/arm/arm-ldmstm.ml: Rewrite ldm/stm RTL patterns to fix
26 regressions.
27 * config/arm/ldmstm.md: Regenreate.
28
292010-12-03 Yao Qi <yao@codesourcery.com>
30
31 Backport from FSF mainline:
32
33 2010-08-02 Bernd Schmidt <bernds@codesourcery.com>
34
35 PR target/40457
36 * config/arm/arm.h (arm_regs_in_sequence): Declare.
37 * config/arm/arm-protos.h (emit_ldm_seq, emit_stm_seq,
38 load_multiple_sequence, store_multiple_sequence): Delete
39 declarations.
40 (arm_gen_load_multiple, arm_gen_store_multiple): Adjust
41 declarations.
42 * config/arm/ldmstm.md: New file.
43 * config/arm/arm.c (arm_regs_in_sequence): New array.
44 (load_multiple_sequence): Now static. New args SAVED_ORDER,
45 CHECK_REGS. All callers changed.
46 If SAVED_ORDER is nonnull, copy the computed order into it.
47 If CHECK_REGS is false, don't sort REGS. Handle Thumb mode.
48 (store_multiple_sequence): Now static. New args NOPS_TOTAL,
49 SAVED_ORDER, REG_RTXS and CHECK_REGS. All callers changed.
50 If SAVED_ORDER is nonnull, copy the computed order into it.
51 If CHECK_REGS is false, don't sort REGS. Set up REG_RTXS just
52 like REGS. Handle Thumb mode.
53 (arm_gen_load_multiple_1): New function, broken out of
54 arm_gen_load_multiple.
55 (arm_gen_store_multiple_1): New function, broken out of
56 arm_gen_store_multiple.
57 (arm_gen_multiple_op): New function, with code from
58 arm_gen_load_multiple and arm_gen_store_multiple moved here.
59 (arm_gen_load_multiple, arm_gen_store_multiple): Now just
60 wrappers around arm_gen_multiple_op. Remove argument UP, all callers
61 changed.
62 (gen_ldm_seq, gen_stm_seq, gen_const_stm_seq): New functions.
63 * config/arm/predicates.md (commutative_binary_operator): New.
64 (load_multiple_operation, store_multiple_operation): Handle more
65 variants of these patterns with different starting offsets. Handle
66 Thumb-1.
67 * config/arm/arm.md: Include "ldmstm.md".
68 (ldmsi_postinc4, ldmsi_postinc4_thumb1, ldmsi_postinc3, ldmsi_postinc2,
69 ldmsi4, ldmsi3, ldmsi2, stmsi_postinc4, stmsi_postinc4_thumb1,
70 stmsi_postinc3, stmsi_postinc2, stmsi4, stmsi3, stmsi2 and related
71 peepholes): Delete.
72 * config/arm/ldmstm.md: New file.
73 * config/arm/arm-ldmstm.ml: New file.
74
75 * config/arm/arm.c (arm_rtx_costs_1): Remove second clause from the
76 if statement which adds extra costs to frame-related expressions.
77
78 2010-05-06 Bernd Schmidt <bernds@codesourcery.com>
79
80 * config/arm/arm.h (MAX_LDM_STM_OPS): New macro.
81 * config/arm/arm.c (multiple_operation_profitable_p,
82 compute_offset_order): New static functions.
83 (load_multiple_sequence, store_multiple_sequence): Use them.
84 Replace constant 4 with MAX_LDM_STM_OPS. Compute order[0] from
85 memory offsets, not register numbers.
86 (emit_ldm_seq, emit_stm_seq): Replace constant 4 with MAX_LDM_STM_OPS.
87
88 2010-04-16 Bernd Schmidt <bernds@codesourcery.com>
89
90 * recog.h (struct recog_data): New field is_operator.
91 (struct insn_operand_data): New field is_operator.
92 * recog.c (extract_insn): Set recog_data.is_operator.
93 * genoutput.c (output_operand_data): Emit code to set the
94 is_operator field.
95 * reload.c (find_reloads): Use it rather than testing for an
96 empty constraint string.
97
98=== added file 'gcc/config/arm/arm-ldmstm.ml'
99Index: gcc-4_5-branch/gcc/config/arm/arm-ldmstm.ml
100===================================================================
101--- /dev/null
102+++ gcc-4_5-branch/gcc/config/arm/arm-ldmstm.ml
103@@ -0,0 +1,333 @@
104+(* Auto-generate ARM ldm/stm patterns
105+ Copyright (C) 2010 Free Software Foundation, Inc.
106+ Contributed by CodeSourcery.
107+
108+ This file is part of GCC.
109+
110+ GCC is free software; you can redistribute it and/or modify it under
111+ the terms of the GNU General Public License as published by the Free
112+ Software Foundation; either version 3, or (at your option) any later
113+ version.
114+
115+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
116+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
117+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
118+ for more details.
119+
120+ You should have received a copy of the GNU General Public License
121+ along with GCC; see the file COPYING3. If not see
122+ <http://www.gnu.org/licenses/>.
123+
124+ This is an O'Caml program. The O'Caml compiler is available from:
125+
126+ http://caml.inria.fr/
127+
128+ Or from your favourite OS's friendly packaging system. Tested with version
129+ 3.09.2, though other versions will probably work too.
130+
131+ Run with:
132+ ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.ml
133+*)
134+
135+type amode = IA | IB | DA | DB
136+
137+type optype = IN | OUT | INOUT
138+
139+let rec string_of_addrmode addrmode =
140+ match addrmode with
141+ IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
142+
143+let rec initial_offset addrmode nregs =
144+ match addrmode with
145+ IA -> 0
146+ | IB -> 4
147+ | DA -> -4 * nregs + 4
148+ | DB -> -4 * nregs
149+
150+let rec final_offset addrmode nregs =
151+ match addrmode with
152+ IA -> nregs * 4
153+ | IB -> nregs * 4
154+ | DA -> -4 * nregs
155+ | DB -> -4 * nregs
156+
157+let constr thumb =
158+ if thumb then "l" else "rk"
159+
160+let inout_constr op_type =
161+ match op_type with
162+ OUT -> "="
163+ | INOUT -> "+&"
164+ | IN -> ""
165+
166+let destreg nregs first op_type thumb =
167+ if not first then
168+ Printf.sprintf "(match_dup %d)" (nregs)
169+ else
170+ Printf.sprintf ("(match_operand:SI %d \"s_register_operand\" \"%s%s\")")
171+ (nregs) (inout_constr op_type) (constr thumb)
172+
173+let write_ldm_set thumb nregs offset opnr first =
174+ let indent = " " in
175+ Printf.printf "%s" (if first then " [" else indent);
176+ Printf.printf "(set (match_operand:SI %d \"arm_hard_register_operand\" \"\")\n" opnr;
177+ Printf.printf "%s (mem:SI " indent;
178+ begin if offset != 0 then Printf.printf "(plus:SI " end;
179+ Printf.printf "%s" (destreg nregs first IN thumb);
180+ begin if offset != 0 then Printf.printf "\n%s (const_int %d))" indent offset end;
181+ Printf.printf "))"
182+
183+let write_stm_set thumb nregs offset opnr first =
184+ let indent = " " in
185+ Printf.printf "%s" (if first then " [" else indent);
186+ Printf.printf "(set (mem:SI ";
187+ begin if offset != 0 then Printf.printf "(plus:SI " end;
188+ Printf.printf "%s" (destreg nregs first IN thumb);
189+ begin if offset != 0 then Printf.printf " (const_int %d))" offset end;
190+ Printf.printf ")\n%s (match_operand:SI %d \"arm_hard_register_operand\" \"\"))" indent opnr
191+
192+let write_ldm_peep_set extra_indent nregs opnr first =
193+ let indent = " " ^ extra_indent in
194+ Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
195+ Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
196+ Printf.printf "%s (match_operand:SI %d \"memory_operand\" \"\"))" indent (nregs + opnr)
197+
198+let write_stm_peep_set extra_indent nregs opnr first =
199+ let indent = " " ^ extra_indent in
200+ Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
201+ Printf.printf "(set (match_operand:SI %d \"memory_operand\" \"\")\n" (nregs + opnr);
202+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\"))" indent opnr
203+
204+let write_any_load optype nregs opnr first =
205+ let indent = " " in
206+ Printf.printf "%s" (if first then " [" else indent);
207+ Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
208+ Printf.printf "%s (match_operand:SI %d \"%s\" \"\"))" indent (nregs * 2 + opnr) optype
209+
210+let write_const_store nregs opnr first =
211+ let indent = " " in
212+ Printf.printf "%s(set (match_operand:SI %d \"memory_operand\" \"\")\n" indent (nregs + opnr);
213+ Printf.printf "%s (match_dup %d))" indent opnr
214+
215+let write_const_stm_peep_set nregs opnr first =
216+ write_any_load "const_int_operand" nregs opnr first;
217+ Printf.printf "\n";
218+ write_const_store nregs opnr false
219+
220+
221+let rec write_pat_sets func opnr offset first n_left =
222+ func offset opnr first;
223+ begin
224+ if n_left > 1 then begin
225+ Printf.printf "\n";
226+ write_pat_sets func (opnr + 1) (offset + 4) false (n_left - 1);
227+ end else
228+ Printf.printf "]"
229+ end
230+
231+let rec write_peep_sets func opnr first n_left =
232+ func opnr first;
233+ begin
234+ if n_left > 1 then begin
235+ Printf.printf "\n";
236+ write_peep_sets func (opnr + 1) false (n_left - 1);
237+ end
238+ end
239+
240+let can_thumb addrmode update is_store =
241+ match addrmode, update, is_store with
242+ (* Thumb1 mode only supports IA with update. However, for LDMIA,
243+ if the address register also appears in the list of loaded
244+ registers, the loaded value is stored, hence the RTL pattern
245+ to describe such an insn does not have an update. We check
246+ in the match_parallel predicate that the condition described
247+ above is met. *)
248+ IA, _, false -> true
249+ | IA, true, true -> true
250+ | _ -> false
251+
252+let target addrmode thumb =
253+ match addrmode, thumb with
254+ IA, true -> "TARGET_THUMB1"
255+ | IA, false -> "TARGET_32BIT"
256+ | DB, false -> "TARGET_32BIT"
257+ | _, false -> "TARGET_ARM"
258+
259+let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
260+ let astr = string_of_addrmode addrmode in
261+ Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
262+ (if thumb then "thumb_" else "") name nregs astr
263+ (if update then "_update" else "");
264+ Printf.printf " [(match_parallel 0 \"%s_multiple_operation\"\n" ls;
265+ begin
266+ if update then begin
267+ Printf.printf " [(set %s\n (plus:SI "
268+ (destreg 1 true OUT thumb); (*destreg 2 true IN thumb*)
269+ Printf.printf "(match_operand:SI 2 \"s_register_operand\" \"1\")";
270+ Printf.printf " (const_int %d)))\n"
271+ (final_offset addrmode nregs)
272+ end
273+ end;
274+ write_pat_sets
275+ (write_set_fn thumb (if update then 2 else 1)) (if update then 3 else 2)
276+ (initial_offset addrmode nregs)
277+ (not update) nregs;
278+ Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
279+ (target addrmode thumb)
280+ (if update then nregs + 1 else nregs);
281+ Printf.printf " \"%s%%(%s%%)\\t%%%d%s, {"
282+ name astr (1) (if update then "!" else "");
283+ for n = 1 to nregs; do
284+ Printf.printf "%%%d%s" (n+(if update then 2 else 1)) (if n < nregs then ", " else "")
285+ done;
286+ Printf.printf "}\"\n";
287+ Printf.printf " [(set_attr \"type\" \"%s%d\")" ls nregs;
288+ begin if not thumb then
289+ Printf.printf "\n (set_attr \"predicable\" \"yes\")";
290+ end;
291+ Printf.printf "])\n\n"
292+
293+let write_ldm_pattern addrmode nregs update =
294+ write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update false;
295+ begin if can_thumb addrmode update false then
296+ write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update true;
297+ end
298+
299+let write_stm_pattern addrmode nregs update =
300+ write_pattern_1 "stm" "store" addrmode nregs write_stm_set update false;
301+ begin if can_thumb addrmode update true then
302+ write_pattern_1 "stm" "store" addrmode nregs write_stm_set update true;
303+ end
304+
305+let write_ldm_commutative_peephole thumb =
306+ let nregs = 2 in
307+ Printf.printf "(define_peephole2\n";
308+ write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
309+ let indent = " " in
310+ if thumb then begin
311+ Printf.printf "\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
312+ Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
313+ Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
314+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
315+ end else begin
316+ Printf.printf "\n%s(parallel\n" indent;
317+ Printf.printf "%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
318+ Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
319+ Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
320+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
321+ Printf.printf "%s (clobber (reg:CC CC_REGNUM))])]\n" indent
322+ end;
323+ Printf.printf " \"(((operands[%d] == operands[0] && operands[%d] == operands[1])\n" (nregs * 2 + 2) (nregs * 2 + 3);
324+ Printf.printf " || (operands[%d] == operands[0] && operands[%d] == operands[1]))\n" (nregs * 2 + 3) (nregs * 2 + 2);
325+ Printf.printf " && peep2_reg_dead_p (%d, operands[0]) && peep2_reg_dead_p (%d, operands[1]))\"\n" (nregs + 1) (nregs + 1);
326+ begin
327+ if thumb then
328+ Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
329+ (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
330+ else begin
331+ Printf.printf " [(parallel\n";
332+ Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
333+ (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
334+ Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
335+ end
336+ end;
337+ Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
338+ Printf.printf "})\n\n"
339+
340+let write_ldm_peephole nregs =
341+ Printf.printf "(define_peephole2\n";
342+ write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
343+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
344+ Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
345+
346+let write_ldm_peephole_b nregs =
347+ if nregs > 2 then begin
348+ Printf.printf "(define_peephole2\n";
349+ write_ldm_peep_set "" nregs 0 true;
350+ Printf.printf "\n (parallel\n";
351+ write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
352+ Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
353+ Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
354+ end
355+
356+let write_stm_peephole nregs =
357+ Printf.printf "(define_peephole2\n";
358+ write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
359+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
360+ Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
361+
362+let write_stm_peephole_b nregs =
363+ if nregs > 2 then begin
364+ Printf.printf "(define_peephole2\n";
365+ write_stm_peep_set "" nregs 0 true;
366+ Printf.printf "\n (parallel\n";
367+ write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
368+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
369+ Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
370+ end
371+
372+let write_const_stm_peephole_a nregs =
373+ Printf.printf "(define_peephole2\n";
374+ write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
375+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
376+ Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
377+
378+let write_const_stm_peephole_b nregs =
379+ Printf.printf "(define_peephole2\n";
380+ write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
381+ Printf.printf "\n";
382+ write_peep_sets (write_const_store nregs) 0 false nregs;
383+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
384+ Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
385+
386+let patterns () =
387+ let addrmodes = [ IA; IB; DA; DB ] in
388+ let sizes = [ 4; 3; 2] in
389+ List.iter
390+ (fun n ->
391+ List.iter
392+ (fun addrmode ->
393+ write_ldm_pattern addrmode n false;
394+ write_ldm_pattern addrmode n true;
395+ write_stm_pattern addrmode n false;
396+ write_stm_pattern addrmode n true)
397+ addrmodes;
398+ write_ldm_peephole n;
399+ write_ldm_peephole_b n;
400+ write_const_stm_peephole_a n;
401+ write_const_stm_peephole_b n;
402+ write_stm_peephole n;)
403+ sizes;
404+ write_ldm_commutative_peephole false;
405+ write_ldm_commutative_peephole true
406+
407+let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
408+
409+(* Do it. *)
410+
411+let _ =
412+ print_lines [
413+"/* ARM ldm/stm instruction patterns. This file was automatically generated";
414+" using arm-ldmstm.ml. Please do not edit manually.";
415+"";
416+" Copyright (C) 2010 Free Software Foundation, Inc.";
417+" Contributed by CodeSourcery.";
418+"";
419+" This file is part of GCC.";
420+"";
421+" GCC is free software; you can redistribute it and/or modify it";
422+" under the terms of the GNU General Public License as published";
423+" by the Free Software Foundation; either version 3, or (at your";
424+" option) any later version.";
425+"";
426+" GCC is distributed in the hope that it will be useful, but WITHOUT";
427+" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
428+" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
429+" License for more details.";
430+"";
431+" You should have received a copy of the GNU General Public License and";
432+" a copy of the GCC Runtime Library Exception along with this program;";
433+" see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
434+" <http://www.gnu.org/licenses/>. */";
435+""];
436+ patterns ();
437Index: gcc-4_5-branch/gcc/config/arm/arm-protos.h
438===================================================================
439--- gcc-4_5-branch.orig/gcc/config/arm/arm-protos.h
440+++ gcc-4_5-branch/gcc/config/arm/arm-protos.h
441@@ -100,14 +100,11 @@ extern int symbol_mentioned_p (rtx);
442 extern int label_mentioned_p (rtx);
443 extern RTX_CODE minmax_code (rtx);
444 extern int adjacent_mem_locations (rtx, rtx);
445-extern int load_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
446-extern const char *emit_ldm_seq (rtx *, int);
447-extern int store_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
448-extern const char * emit_stm_seq (rtx *, int);
449-extern rtx arm_gen_load_multiple (int, int, rtx, int, int,
450- rtx, HOST_WIDE_INT *);
451-extern rtx arm_gen_store_multiple (int, int, rtx, int, int,
452- rtx, HOST_WIDE_INT *);
453+extern bool gen_ldm_seq (rtx *, int, bool);
454+extern bool gen_stm_seq (rtx *, int);
455+extern bool gen_const_stm_seq (rtx *, int);
456+extern rtx arm_gen_load_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
457+extern rtx arm_gen_store_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
458 extern int arm_gen_movmemqi (rtx *);
459 extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
460 extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
461Index: gcc-4_5-branch/gcc/config/arm/arm.c
462===================================================================
463--- gcc-4_5-branch.orig/gcc/config/arm/arm.c
464+++ gcc-4_5-branch/gcc/config/arm/arm.c
465@@ -753,6 +753,12 @@ static const char * const arm_condition_
466 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
467 };
468
469+/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
470+int arm_regs_in_sequence[] =
471+{
472+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
473+};
474+
475 #define ARM_LSL_NAME (TARGET_UNIFIED_ASM ? "lsl" : "asl")
476 #define streq(string1, string2) (strcmp (string1, string2) == 0)
477
478@@ -9680,24 +9686,125 @@ adjacent_mem_locations (rtx a, rtx b)
479 return 0;
480 }
481
482-int
483-load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
484- HOST_WIDE_INT *load_offset)
485+
486+/* Return true iff it would be profitable to turn a sequence of NOPS loads
487+ or stores (depending on IS_STORE) into a load-multiple or store-multiple
488+ instruction. ADD_OFFSET is nonzero if the base address register needs
489+ to be modified with an add instruction before we can use it. */
490+
491+static bool
492+multiple_operation_profitable_p (bool is_store ATTRIBUTE_UNUSED,
493+ int nops, HOST_WIDE_INT add_offset)
494+ {
495+ /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
496+ if the offset isn't small enough. The reason 2 ldrs are faster
497+ is because these ARMs are able to do more than one cache access
498+ in a single cycle. The ARM9 and StrongARM have Harvard caches,
499+ whilst the ARM8 has a double bandwidth cache. This means that
500+ these cores can do both an instruction fetch and a data fetch in
501+ a single cycle, so the trick of calculating the address into a
502+ scratch register (one of the result regs) and then doing a load
503+ multiple actually becomes slower (and no smaller in code size).
504+ That is the transformation
505+
506+ ldr rd1, [rbase + offset]
507+ ldr rd2, [rbase + offset + 4]
508+
509+ to
510+
511+ add rd1, rbase, offset
512+ ldmia rd1, {rd1, rd2}
513+
514+ produces worse code -- '3 cycles + any stalls on rd2' instead of
515+ '2 cycles + any stalls on rd2'. On ARMs with only one cache
516+ access per cycle, the first sequence could never complete in less
517+ than 6 cycles, whereas the ldm sequence would only take 5 and
518+ would make better use of sequential accesses if not hitting the
519+ cache.
520+
521+ We cheat here and test 'arm_ld_sched' which we currently know to
522+ only be true for the ARM8, ARM9 and StrongARM. If this ever
523+ changes, then the test below needs to be reworked. */
524+ if (nops == 2 && arm_ld_sched && add_offset != 0)
525+ return false;
526+
527+ return true;
528+}
529+
530+/* Subroutine of load_multiple_sequence and store_multiple_sequence.
531+ Given an array of UNSORTED_OFFSETS, of which there are NOPS, compute
532+ an array ORDER which describes the sequence to use when accessing the
533+ offsets that produces an ascending order. In this sequence, each
534+ offset must be larger by exactly 4 than the previous one. ORDER[0]
535+ must have been filled in with the lowest offset by the caller.
536+ If UNSORTED_REGS is nonnull, it is an array of register numbers that
537+ we use to verify that ORDER produces an ascending order of registers.
538+ Return true if it was possible to construct such an order, false if
539+ not. */
540+
541+static bool
542+compute_offset_order (int nops, HOST_WIDE_INT *unsorted_offsets, int *order,
543+ int *unsorted_regs)
544 {
545- int unsorted_regs[4];
546- HOST_WIDE_INT unsorted_offsets[4];
547- int order[4];
548- int base_reg = -1;
549 int i;
550+ for (i = 1; i < nops; i++)
551+ {
552+ int j;
553+
554+ order[i] = order[i - 1];
555+ for (j = 0; j < nops; j++)
556+ if (unsorted_offsets[j] == unsorted_offsets[order[i - 1]] + 4)
557+ {
558+ /* We must find exactly one offset that is higher than the
559+ previous one by 4. */
560+ if (order[i] != order[i - 1])
561+ return false;
562+ order[i] = j;
563+ }
564+ if (order[i] == order[i - 1])
565+ return false;
566+ /* The register numbers must be ascending. */
567+ if (unsorted_regs != NULL
568+ && unsorted_regs[order[i]] <= unsorted_regs[order[i - 1]])
569+ return false;
570+ }
571+ return true;
572+}
573+
574+/* Used to determine in a peephole whether a sequence of load
575+ instructions can be changed into a load-multiple instruction.
576+ NOPS is the number of separate load instructions we are examining. The
577+ first NOPS entries in OPERANDS are the destination registers, the
578+ next NOPS entries are memory operands. If this function is
579+ successful, *BASE is set to the common base register of the memory
580+ accesses; *LOAD_OFFSET is set to the first memory location's offset
581+ from that base register.
582+ REGS is an array filled in with the destination register numbers.
583+ SAVED_ORDER (if nonnull), is an array filled in with an order that maps
584+ insn numbers to to an ascending order of stores. If CHECK_REGS is true,
585+ the sequence of registers in REGS matches the loads from ascending memory
586+ locations, and the function verifies that the register numbers are
587+ themselves ascending. If CHECK_REGS is false, the register numbers
588+ are stored in the order they are found in the operands. */
589+static int
590+load_multiple_sequence (rtx *operands, int nops, int *regs, int *saved_order,
591+ int *base, HOST_WIDE_INT *load_offset, bool check_regs)
592+{
593+ int unsorted_regs[MAX_LDM_STM_OPS];
594+ HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
595+ int order[MAX_LDM_STM_OPS];
596+ rtx base_reg_rtx = NULL;
597+ int base_reg = -1;
598+ int i, ldm_case;
599
600 if (low_irq_latency)
601 return 0;
602
603- /* Can only handle 2, 3, or 4 insns at present,
604- though could be easily extended if required. */
605- gcc_assert (nops >= 2 && nops <= 4);
606+ /* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
607+ easily extended if required. */
608+ gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
609
610- memset (order, 0, 4 * sizeof (int));
611+ memset (order, 0, MAX_LDM_STM_OPS * sizeof (int));
612
613 /* Loop over the operands and check that the memory references are
614 suitable (i.e. immediate offsets from the same base register). At
615@@ -9735,32 +9842,30 @@ load_multiple_sequence (rtx *operands, i
616 if (i == 0)
617 {
618 base_reg = REGNO (reg);
619- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
620- ? REGNO (operands[i])
621- : REGNO (SUBREG_REG (operands[i])));
622- order[0] = 0;
623- }
624- else
625- {
626- if (base_reg != (int) REGNO (reg))
627- /* Not addressed from the same base register. */
628+ base_reg_rtx = reg;
629+ if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
630 return 0;
631-
632- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
633- ? REGNO (operands[i])
634- : REGNO (SUBREG_REG (operands[i])));
635- if (unsorted_regs[i] < unsorted_regs[order[0]])
636- order[0] = i;
637 }
638+ else if (base_reg != (int) REGNO (reg))
639+ /* Not addressed from the same base register. */
640+ return 0;
641+
642+ unsorted_regs[i] = (GET_CODE (operands[i]) == REG
643+ ? REGNO (operands[i])
644+ : REGNO (SUBREG_REG (operands[i])));
645
646 /* If it isn't an integer register, or if it overwrites the
647 base register but isn't the last insn in the list, then
648 we can't do this. */
649- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14
650+ if (unsorted_regs[i] < 0
651+ || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
652+ || unsorted_regs[i] > 14
653 || (i != nops - 1 && unsorted_regs[i] == base_reg))
654 return 0;
655
656 unsorted_offsets[i] = INTVAL (offset);
657+ if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]])
658+ order[0] = i;
659 }
660 else
661 /* Not a suitable memory address. */
662@@ -9769,167 +9874,90 @@ load_multiple_sequence (rtx *operands, i
663
664 /* All the useful information has now been extracted from the
665 operands into unsorted_regs and unsorted_offsets; additionally,
666- order[0] has been set to the lowest numbered register in the
667- list. Sort the registers into order, and check that the memory
668- offsets are ascending and adjacent. */
669-
670- for (i = 1; i < nops; i++)
671- {
672- int j;
673-
674- order[i] = order[i - 1];
675- for (j = 0; j < nops; j++)
676- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
677- && (order[i] == order[i - 1]
678- || unsorted_regs[j] < unsorted_regs[order[i]]))
679- order[i] = j;
680-
681- /* Have we found a suitable register? if not, one must be used more
682- than once. */
683- if (order[i] == order[i - 1])
684- return 0;
685+ order[0] has been set to the lowest offset in the list. Sort
686+ the offsets into order, verifying that they are adjacent, and
687+ check that the register numbers are ascending. */
688+ if (!compute_offset_order (nops, unsorted_offsets, order,
689+ check_regs ? unsorted_regs : NULL))
690+ return 0;
691
692- /* Is the memory address adjacent and ascending? */
693- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
694- return 0;
695- }
696+ if (saved_order)
697+ memcpy (saved_order, order, sizeof order);
698
699 if (base)
700 {
701 *base = base_reg;
702
703 for (i = 0; i < nops; i++)
704- regs[i] = unsorted_regs[order[i]];
705+ regs[i] = unsorted_regs[check_regs ? order[i] : i];
706
707 *load_offset = unsorted_offsets[order[0]];
708 }
709
710- if (unsorted_offsets[order[0]] == 0)
711- return 1; /* ldmia */
712-
713- if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
714- return 2; /* ldmib */
715-
716- if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
717- return 3; /* ldmda */
718-
719- if (unsorted_offsets[order[nops - 1]] == -4)
720- return 4; /* ldmdb */
721-
722- /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
723- if the offset isn't small enough. The reason 2 ldrs are faster
724- is because these ARMs are able to do more than one cache access
725- in a single cycle. The ARM9 and StrongARM have Harvard caches,
726- whilst the ARM8 has a double bandwidth cache. This means that
727- these cores can do both an instruction fetch and a data fetch in
728- a single cycle, so the trick of calculating the address into a
729- scratch register (one of the result regs) and then doing a load
730- multiple actually becomes slower (and no smaller in code size).
731- That is the transformation
732-
733- ldr rd1, [rbase + offset]
734- ldr rd2, [rbase + offset + 4]
735-
736- to
737-
738- add rd1, rbase, offset
739- ldmia rd1, {rd1, rd2}
740-
741- produces worse code -- '3 cycles + any stalls on rd2' instead of
742- '2 cycles + any stalls on rd2'. On ARMs with only one cache
743- access per cycle, the first sequence could never complete in less
744- than 6 cycles, whereas the ldm sequence would only take 5 and
745- would make better use of sequential accesses if not hitting the
746- cache.
747-
748- We cheat here and test 'arm_ld_sched' which we currently know to
749- only be true for the ARM8, ARM9 and StrongARM. If this ever
750- changes, then the test below needs to be reworked. */
751- if (nops == 2 && arm_ld_sched)
752+ if (TARGET_THUMB1
753+ && !peep2_reg_dead_p (nops, base_reg_rtx))
754 return 0;
755
756- /* Can't do it without setting up the offset, only do this if it takes
757- no more than one insn. */
758- return (const_ok_for_arm (unsorted_offsets[order[0]])
759- || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
760-}
761-
762-const char *
763-emit_ldm_seq (rtx *operands, int nops)
764-{
765- int regs[4];
766- int base_reg;
767- HOST_WIDE_INT offset;
768- char buf[100];
769- int i;
770-
771- switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
772- {
773- case 1:
774- strcpy (buf, "ldm%(ia%)\t");
775- break;
776-
777- case 2:
778- strcpy (buf, "ldm%(ib%)\t");
779- break;
780-
781- case 3:
782- strcpy (buf, "ldm%(da%)\t");
783- break;
784-
785- case 4:
786- strcpy (buf, "ldm%(db%)\t");
787- break;
788-
789- case 5:
790- if (offset >= 0)
791- sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
792- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
793- (long) offset);
794- else
795- sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
796- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
797- (long) -offset);
798- output_asm_insn (buf, operands);
799- base_reg = regs[0];
800- strcpy (buf, "ldm%(ia%)\t");
801- break;
802-
803- default:
804- gcc_unreachable ();
805- }
806-
807- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
808- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
809-
810- for (i = 1; i < nops; i++)
811- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
812- reg_names[regs[i]]);
813+ if (unsorted_offsets[order[0]] == 0)
814+ ldm_case = 1; /* ldmia */
815+ else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
816+ ldm_case = 2; /* ldmib */
817+ else if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
818+ ldm_case = 3; /* ldmda */
819+ else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
820+ ldm_case = 4; /* ldmdb */
821+ else if (const_ok_for_arm (unsorted_offsets[order[0]])
822+ || const_ok_for_arm (-unsorted_offsets[order[0]]))
823+ ldm_case = 5;
824+ else
825+ return 0;
826
827- strcat (buf, "}\t%@ phole ldm");
828+ if (!multiple_operation_profitable_p (false, nops,
829+ ldm_case == 5
830+ ? unsorted_offsets[order[0]] : 0))
831+ return 0;
832
833- output_asm_insn (buf, operands);
834- return "";
835+ return ldm_case;
836 }
837
838-int
839-store_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
840- HOST_WIDE_INT * load_offset)
841-{
842- int unsorted_regs[4];
843- HOST_WIDE_INT unsorted_offsets[4];
844- int order[4];
845+/* Used to determine in a peephole whether a sequence of store instructions can
846+ be changed into a store-multiple instruction.
847+ NOPS is the number of separate store instructions we are examining.
848+ NOPS_TOTAL is the total number of instructions recognized by the peephole
849+ pattern.
850+ The first NOPS entries in OPERANDS are the source registers, the next
851+ NOPS entries are memory operands. If this function is successful, *BASE is
852+ set to the common base register of the memory accesses; *LOAD_OFFSET is set
853+ to the first memory location's offset from that base register. REGS is an
854+ array filled in with the source register numbers, REG_RTXS (if nonnull) is
855+ likewise filled with the corresponding rtx's.
856+ SAVED_ORDER (if nonnull), is an array filled in with an order that maps insn
857+ numbers to to an ascending order of stores.
858+ If CHECK_REGS is true, the sequence of registers in *REGS matches the stores
859+ from ascending memory locations, and the function verifies that the register
860+ numbers are themselves ascending. If CHECK_REGS is false, the register
861+ numbers are stored in the order they are found in the operands. */
862+static int
863+store_multiple_sequence (rtx *operands, int nops, int nops_total,
864+ int *regs, rtx *reg_rtxs, int *saved_order, int *base,
865+ HOST_WIDE_INT *load_offset, bool check_regs)
866+{
867+ int unsorted_regs[MAX_LDM_STM_OPS];
868+ rtx unsorted_reg_rtxs[MAX_LDM_STM_OPS];
869+ HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
870+ int order[MAX_LDM_STM_OPS];
871 int base_reg = -1;
872- int i;
873+ rtx base_reg_rtx = NULL;
874+ int i, stm_case;
875
876 if (low_irq_latency)
877 return 0;
878
879- /* Can only handle 2, 3, or 4 insns at present, though could be easily
880- extended if required. */
881- gcc_assert (nops >= 2 && nops <= 4);
882+ /* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
883+ easily extended if required. */
884+ gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
885
886- memset (order, 0, 4 * sizeof (int));
887+ memset (order, 0, MAX_LDM_STM_OPS * sizeof (int));
888
889 /* Loop over the operands and check that the memory references are
890 suitable (i.e. immediate offsets from the same base register). At
891@@ -9964,32 +9992,32 @@ store_multiple_sequence (rtx *operands,
892 && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
893 == CONST_INT)))
894 {
895+ unsorted_reg_rtxs[i] = (GET_CODE (operands[i]) == REG
896+ ? operands[i] : SUBREG_REG (operands[i]));
897+ unsorted_regs[i] = REGNO (unsorted_reg_rtxs[i]);
898+
899 if (i == 0)
900 {
901 base_reg = REGNO (reg);
902- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
903- ? REGNO (operands[i])
904- : REGNO (SUBREG_REG (operands[i])));
905- order[0] = 0;
906- }
907- else
908- {
909- if (base_reg != (int) REGNO (reg))
910- /* Not addressed from the same base register. */
911+ base_reg_rtx = reg;
912+ if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
913 return 0;
914-
915- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
916- ? REGNO (operands[i])
917- : REGNO (SUBREG_REG (operands[i])));
918- if (unsorted_regs[i] < unsorted_regs[order[0]])
919- order[0] = i;
920 }
921+ else if (base_reg != (int) REGNO (reg))
922+ /* Not addressed from the same base register. */
923+ return 0;
924
925 /* If it isn't an integer register, then we can't do this. */
926- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
927+ if (unsorted_regs[i] < 0
928+ || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
929+ || (TARGET_THUMB2 && unsorted_regs[i] == base_reg)
930+ || (TARGET_THUMB2 && unsorted_regs[i] == SP_REGNUM)
931+ || unsorted_regs[i] > 14)
932 return 0;
933
934 unsorted_offsets[i] = INTVAL (offset);
935+ if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]])
936+ order[0] = i;
937 }
938 else
939 /* Not a suitable memory address. */
940@@ -9998,111 +10026,65 @@ store_multiple_sequence (rtx *operands,
941
942 /* All the useful information has now been extracted from the
943 operands into unsorted_regs and unsorted_offsets; additionally,
944- order[0] has been set to the lowest numbered register in the
945- list. Sort the registers into order, and check that the memory
946- offsets are ascending and adjacent. */
947-
948- for (i = 1; i < nops; i++)
949- {
950- int j;
951-
952- order[i] = order[i - 1];
953- for (j = 0; j < nops; j++)
954- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
955- && (order[i] == order[i - 1]
956- || unsorted_regs[j] < unsorted_regs[order[i]]))
957- order[i] = j;
958-
959- /* Have we found a suitable register? if not, one must be used more
960- than once. */
961- if (order[i] == order[i - 1])
962- return 0;
963+ order[0] has been set to the lowest offset in the list. Sort
964+ the offsets into order, verifying that they are adjacent, and
965+ check that the register numbers are ascending. */
966+ if (!compute_offset_order (nops, unsorted_offsets, order,
967+ check_regs ? unsorted_regs : NULL))
968+ return 0;
969
970- /* Is the memory address adjacent and ascending? */
971- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
972- return 0;
973- }
974+ if (saved_order)
975+ memcpy (saved_order, order, sizeof order);
976
977 if (base)
978 {
979 *base = base_reg;
980
981 for (i = 0; i < nops; i++)
982- regs[i] = unsorted_regs[order[i]];
983+ {
984+ regs[i] = unsorted_regs[check_regs ? order[i] : i];
985+ if (reg_rtxs)
986+ reg_rtxs[i] = unsorted_reg_rtxs[check_regs ? order[i] : i];
987+ }
988
989 *load_offset = unsorted_offsets[order[0]];
990 }
991
992- if (unsorted_offsets[order[0]] == 0)
993- return 1; /* stmia */
994-
995- if (unsorted_offsets[order[0]] == 4)
996- return 2; /* stmib */
997-
998- if (unsorted_offsets[order[nops - 1]] == 0)
999- return 3; /* stmda */
1000-
1001- if (unsorted_offsets[order[nops - 1]] == -4)
1002- return 4; /* stmdb */
1003-
1004- return 0;
1005-}
1006-
1007-const char *
1008-emit_stm_seq (rtx *operands, int nops)
1009-{
1010- int regs[4];
1011- int base_reg;
1012- HOST_WIDE_INT offset;
1013- char buf[100];
1014- int i;
1015-
1016- switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
1017- {
1018- case 1:
1019- strcpy (buf, "stm%(ia%)\t");
1020- break;
1021-
1022- case 2:
1023- strcpy (buf, "stm%(ib%)\t");
1024- break;
1025-
1026- case 3:
1027- strcpy (buf, "stm%(da%)\t");
1028- break;
1029-
1030- case 4:
1031- strcpy (buf, "stm%(db%)\t");
1032- break;
1033-
1034- default:
1035- gcc_unreachable ();
1036- }
1037-
1038- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
1039- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
1040+ if (TARGET_THUMB1
1041+ && !peep2_reg_dead_p (nops_total, base_reg_rtx))
1042+ return 0;
1043
1044- for (i = 1; i < nops; i++)
1045- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
1046- reg_names[regs[i]]);
1047+ if (unsorted_offsets[order[0]] == 0)
1048+ stm_case = 1; /* stmia */
1049+ else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
1050+ stm_case = 2; /* stmib */
1051+ else if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
1052+ stm_case = 3; /* stmda */
1053+ else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
1054+ stm_case = 4; /* stmdb */
1055+ else
1056+ return 0;
1057
1058- strcat (buf, "}\t%@ phole stm");
1059+ if (!multiple_operation_profitable_p (false, nops, 0))
1060+ return 0;
1061
1062- output_asm_insn (buf, operands);
1063- return "";
1064+ return stm_case;
1065 }
1066
1067 /* Routines for use in generating RTL. */
1068
1069-rtx
1070-arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
1071- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1072+/* Generate a load-multiple instruction. COUNT is the number of loads in
1073+ the instruction; REGS and MEMS are arrays containing the operands.
1074+ BASEREG is the base register to be used in addressing the memory operands.
1075+ WBACK_OFFSET is nonzero if the instruction should update the base
1076+ register. */
1077+
1078+static rtx
1079+arm_gen_load_multiple_1 (int count, int *regs, rtx *mems, rtx basereg,
1080+ HOST_WIDE_INT wback_offset)
1081 {
1082- HOST_WIDE_INT offset = *offsetp;
1083 int i = 0, j;
1084 rtx result;
1085- int sign = up ? 1 : -1;
1086- rtx mem, addr;
1087
1088 /* XScale has load-store double instructions, but they have stricter
1089 alignment requirements than load-store multiple, so we cannot
1090@@ -10139,18 +10121,10 @@ arm_gen_load_multiple (int base_regno, i
1091 start_sequence ();
1092
1093 for (i = 0; i < count; i++)
1094- {
1095- addr = plus_constant (from, i * 4 * sign);
1096- mem = adjust_automodify_address (basemem, SImode, addr, offset);
1097- emit_move_insn (gen_rtx_REG (SImode, base_regno + i), mem);
1098- offset += 4 * sign;
1099- }
1100+ emit_move_insn (gen_rtx_REG (SImode, regs[i]), mems[i]);
1101
1102- if (write_back)
1103- {
1104- emit_move_insn (from, plus_constant (from, count * 4 * sign));
1105- *offsetp = offset;
1106- }
1107+ if (wback_offset != 0)
1108+ emit_move_insn (basereg, plus_constant (basereg, wback_offset));
1109
1110 seq = get_insns ();
1111 end_sequence ();
1112@@ -10159,41 +10133,40 @@ arm_gen_load_multiple (int base_regno, i
1113 }
1114
1115 result = gen_rtx_PARALLEL (VOIDmode,
1116- rtvec_alloc (count + (write_back ? 1 : 0)));
1117- if (write_back)
1118+ rtvec_alloc (count + (wback_offset != 0 ? 1 : 0)));
1119+ if (wback_offset != 0)
1120 {
1121 XVECEXP (result, 0, 0)
1122- = gen_rtx_SET (VOIDmode, from, plus_constant (from, count * 4 * sign));
1123+ = gen_rtx_SET (VOIDmode, basereg,
1124+ plus_constant (basereg, wback_offset));
1125 i = 1;
1126 count++;
1127 }
1128
1129 for (j = 0; i < count; i++, j++)
1130- {
1131- addr = plus_constant (from, j * 4 * sign);
1132- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1133- XVECEXP (result, 0, i)
1134- = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, base_regno + j), mem);
1135- offset += 4 * sign;
1136- }
1137-
1138- if (write_back)
1139- *offsetp = offset;
1140+ XVECEXP (result, 0, i)
1141+ = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, regs[j]), mems[j]);
1142
1143 return result;
1144 }
1145
1146-rtx
1147-arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
1148- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1149+/* Generate a store-multiple instruction. COUNT is the number of stores in
1150+ the instruction; REGS and MEMS are arrays containing the operands.
1151+ BASEREG is the base register to be used in addressing the memory operands.
1152+ WBACK_OFFSET is nonzero if the instruction should update the base
1153+ register. */
1154+
1155+static rtx
1156+arm_gen_store_multiple_1 (int count, int *regs, rtx *mems, rtx basereg,
1157+ HOST_WIDE_INT wback_offset)
1158 {
1159- HOST_WIDE_INT offset = *offsetp;
1160 int i = 0, j;
1161 rtx result;
1162- int sign = up ? 1 : -1;
1163- rtx mem, addr;
1164
1165- /* See arm_gen_load_multiple for discussion of
1166+ if (GET_CODE (basereg) == PLUS)
1167+ basereg = XEXP (basereg, 0);
1168+
1169+ /* See arm_gen_load_multiple_1 for discussion of
1170 the pros/cons of ldm/stm usage for XScale. */
1171 if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size))
1172 {
1173@@ -10202,18 +10175,10 @@ arm_gen_store_multiple (int base_regno,
1174 start_sequence ();
1175
1176 for (i = 0; i < count; i++)
1177- {
1178- addr = plus_constant (to, i * 4 * sign);
1179- mem = adjust_automodify_address (basemem, SImode, addr, offset);
1180- emit_move_insn (mem, gen_rtx_REG (SImode, base_regno + i));
1181- offset += 4 * sign;
1182- }
1183+ emit_move_insn (mems[i], gen_rtx_REG (SImode, regs[i]));
1184
1185- if (write_back)
1186- {
1187- emit_move_insn (to, plus_constant (to, count * 4 * sign));
1188- *offsetp = offset;
1189- }
1190+ if (wback_offset != 0)
1191+ emit_move_insn (basereg, plus_constant (basereg, wback_offset));
1192
1193 seq = get_insns ();
1194 end_sequence ();
1195@@ -10222,29 +10187,319 @@ arm_gen_store_multiple (int base_regno,
1196 }
1197
1198 result = gen_rtx_PARALLEL (VOIDmode,
1199- rtvec_alloc (count + (write_back ? 1 : 0)));
1200- if (write_back)
1201+ rtvec_alloc (count + (wback_offset != 0 ? 1 : 0)));
1202+ if (wback_offset != 0)
1203 {
1204 XVECEXP (result, 0, 0)
1205- = gen_rtx_SET (VOIDmode, to,
1206- plus_constant (to, count * 4 * sign));
1207+ = gen_rtx_SET (VOIDmode, basereg,
1208+ plus_constant (basereg, wback_offset));
1209 i = 1;
1210 count++;
1211 }
1212
1213 for (j = 0; i < count; i++, j++)
1214+ XVECEXP (result, 0, i)
1215+ = gen_rtx_SET (VOIDmode, mems[j], gen_rtx_REG (SImode, regs[j]));
1216+
1217+ return result;
1218+}
1219+
1220+/* Generate either a load-multiple or a store-multiple instruction. This
1221+ function can be used in situations where we can start with a single MEM
1222+ rtx and adjust its address upwards.
1223+ COUNT is the number of operations in the instruction, not counting a
1224+ possible update of the base register. REGS is an array containing the
1225+ register operands.
1226+ BASEREG is the base register to be used in addressing the memory operands,
1227+ which are constructed from BASEMEM.
1228+ WRITE_BACK specifies whether the generated instruction should include an
1229+ update of the base register.
1230+ OFFSETP is used to pass an offset to and from this function; this offset
1231+ is not used when constructing the address (instead BASEMEM should have an
1232+ appropriate offset in its address), it is used only for setting
1233+ MEM_OFFSET. It is updated only if WRITE_BACK is true.*/
1234+
1235+static rtx
1236+arm_gen_multiple_op (bool is_load, int *regs, int count, rtx basereg,
1237+ bool write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1238+{
1239+ rtx mems[MAX_LDM_STM_OPS];
1240+ HOST_WIDE_INT offset = *offsetp;
1241+ int i;
1242+
1243+ gcc_assert (count <= MAX_LDM_STM_OPS);
1244+
1245+ if (GET_CODE (basereg) == PLUS)
1246+ basereg = XEXP (basereg, 0);
1247+
1248+ for (i = 0; i < count; i++)
1249 {
1250- addr = plus_constant (to, j * 4 * sign);
1251- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1252- XVECEXP (result, 0, i)
1253- = gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (SImode, base_regno + j));
1254- offset += 4 * sign;
1255+ rtx addr = plus_constant (basereg, i * 4);
1256+ mems[i] = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1257+ offset += 4;
1258 }
1259
1260 if (write_back)
1261 *offsetp = offset;
1262
1263- return result;
1264+ if (is_load)
1265+ return arm_gen_load_multiple_1 (count, regs, mems, basereg,
1266+ write_back ? 4 * count : 0);
1267+ else
1268+ return arm_gen_store_multiple_1 (count, regs, mems, basereg,
1269+ write_back ? 4 * count : 0);
1270+}
1271+
1272+rtx
1273+arm_gen_load_multiple (int *regs, int count, rtx basereg, int write_back,
1274+ rtx basemem, HOST_WIDE_INT *offsetp)
1275+{
1276+ return arm_gen_multiple_op (TRUE, regs, count, basereg, write_back, basemem,
1277+ offsetp);
1278+}
1279+
1280+rtx
1281+arm_gen_store_multiple (int *regs, int count, rtx basereg, int write_back,
1282+ rtx basemem, HOST_WIDE_INT *offsetp)
1283+{
1284+ return arm_gen_multiple_op (FALSE, regs, count, basereg, write_back, basemem,
1285+ offsetp);
1286+}
1287+
1288+/* Called from a peephole2 expander to turn a sequence of loads into an
1289+ LDM instruction. OPERANDS are the operands found by the peephole matcher;
1290+ NOPS indicates how many separate loads we are trying to combine. SORT_REGS
1291+ is true if we can reorder the registers because they are used commutatively
1292+ subsequently.
1293+ Returns true iff we could generate a new instruction. */
1294+
1295+bool
1296+gen_ldm_seq (rtx *operands, int nops, bool sort_regs)
1297+{
1298+ int regs[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1299+ rtx mems[MAX_LDM_STM_OPS];
1300+ int i, j, base_reg;
1301+ rtx base_reg_rtx;
1302+ HOST_WIDE_INT offset;
1303+ int write_back = FALSE;
1304+ int ldm_case;
1305+ rtx addr;
1306+
1307+ ldm_case = load_multiple_sequence (operands, nops, regs, mem_order,
1308+ &base_reg, &offset, !sort_regs);
1309+
1310+ if (ldm_case == 0)
1311+ return false;
1312+
1313+ if (sort_regs)
1314+ for (i = 0; i < nops - 1; i++)
1315+ for (j = i + 1; j < nops; j++)
1316+ if (regs[i] > regs[j])
1317+ {
1318+ int t = regs[i];
1319+ regs[i] = regs[j];
1320+ regs[j] = t;
1321+ }
1322+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1323+
1324+ if (TARGET_THUMB1)
1325+ {
1326+ gcc_assert (peep2_reg_dead_p (nops, base_reg_rtx));
1327+ gcc_assert (ldm_case == 1 || ldm_case == 5);
1328+ write_back = TRUE;
1329+ }
1330+
1331+ if (ldm_case == 5)
1332+ {
1333+ rtx newbase = TARGET_THUMB1 ? base_reg_rtx : gen_rtx_REG (SImode, regs[0]);
1334+ emit_insn (gen_addsi3 (newbase, base_reg_rtx, GEN_INT (offset)));
1335+ offset = 0;
1336+ if (!TARGET_THUMB1)
1337+ {
1338+ base_reg = regs[0];
1339+ base_reg_rtx = newbase;
1340+ }
1341+ }
1342+
1343+ for (i = 0; i < nops; i++)
1344+ {
1345+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1346+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1347+ SImode, addr, 0);
1348+ }
1349+ emit_insn (arm_gen_load_multiple_1 (nops, regs, mems, base_reg_rtx,
1350+ write_back ? offset + i * 4 : 0));
1351+ return true;
1352+}
1353+
1354+/* Called from a peephole2 expander to turn a sequence of stores into an
1355+ STM instruction. OPERANDS are the operands found by the peephole matcher;
1356+ NOPS indicates how many separate stores we are trying to combine.
1357+ Returns true iff we could generate a new instruction. */
1358+
1359+bool
1360+gen_stm_seq (rtx *operands, int nops)
1361+{
1362+ int i;
1363+ int regs[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1364+ rtx mems[MAX_LDM_STM_OPS];
1365+ int base_reg;
1366+ rtx base_reg_rtx;
1367+ HOST_WIDE_INT offset;
1368+ int write_back = FALSE;
1369+ int stm_case;
1370+ rtx addr;
1371+ bool base_reg_dies;
1372+
1373+ stm_case = store_multiple_sequence (operands, nops, nops, regs, NULL,
1374+ mem_order, &base_reg, &offset, true);
1375+
1376+ if (stm_case == 0)
1377+ return false;
1378+
1379+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1380+
1381+ base_reg_dies = peep2_reg_dead_p (nops, base_reg_rtx);
1382+ if (TARGET_THUMB1)
1383+ {
1384+ gcc_assert (base_reg_dies);
1385+ write_back = TRUE;
1386+ }
1387+
1388+ if (stm_case == 5)
1389+ {
1390+ gcc_assert (base_reg_dies);
1391+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, GEN_INT (offset)));
1392+ offset = 0;
1393+ }
1394+
1395+ addr = plus_constant (base_reg_rtx, offset);
1396+
1397+ for (i = 0; i < nops; i++)
1398+ {
1399+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1400+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1401+ SImode, addr, 0);
1402+ }
1403+ emit_insn (arm_gen_store_multiple_1 (nops, regs, mems, base_reg_rtx,
1404+ write_back ? offset + i * 4 : 0));
1405+ return true;
1406+}
1407+
1408+/* Called from a peephole2 expander to turn a sequence of stores that are
1409+ preceded by constant loads into an STM instruction. OPERANDS are the
1410+ operands found by the peephole matcher; NOPS indicates how many
1411+ separate stores we are trying to combine; there are 2 * NOPS
1412+ instructions in the peephole.
1413+ Returns true iff we could generate a new instruction. */
1414+
1415+bool
1416+gen_const_stm_seq (rtx *operands, int nops)
1417+{
1418+ int regs[MAX_LDM_STM_OPS], sorted_regs[MAX_LDM_STM_OPS];
1419+ int reg_order[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1420+ rtx reg_rtxs[MAX_LDM_STM_OPS], orig_reg_rtxs[MAX_LDM_STM_OPS];
1421+ rtx mems[MAX_LDM_STM_OPS];
1422+ int base_reg;
1423+ rtx base_reg_rtx;
1424+ HOST_WIDE_INT offset;
1425+ int write_back = FALSE;
1426+ int stm_case;
1427+ rtx addr;
1428+ bool base_reg_dies;
1429+ int i, j;
1430+ HARD_REG_SET allocated;
1431+
1432+ stm_case = store_multiple_sequence (operands, nops, 2 * nops, regs, reg_rtxs,
1433+ mem_order, &base_reg, &offset, false);
1434+
1435+ if (stm_case == 0)
1436+ return false;
1437+
1438+ memcpy (orig_reg_rtxs, reg_rtxs, sizeof orig_reg_rtxs);
1439+
1440+ /* If the same register is used more than once, try to find a free
1441+ register. */
1442+ CLEAR_HARD_REG_SET (allocated);
1443+ for (i = 0; i < nops; i++)
1444+ {
1445+ for (j = i + 1; j < nops; j++)
1446+ if (regs[i] == regs[j])
1447+ {
1448+ rtx t = peep2_find_free_register (0, nops * 2,
1449+ TARGET_THUMB1 ? "l" : "r",
1450+ SImode, &allocated);
1451+ if (t == NULL_RTX)
1452+ return false;
1453+ reg_rtxs[i] = t;
1454+ regs[i] = REGNO (t);
1455+ }
1456+ }
1457+
1458+ /* Compute an ordering that maps the register numbers to an ascending
1459+ sequence. */
1460+ reg_order[0] = 0;
1461+ for (i = 0; i < nops; i++)
1462+ if (regs[i] < regs[reg_order[0]])
1463+ reg_order[0] = i;
1464+
1465+ for (i = 1; i < nops; i++)
1466+ {
1467+ int this_order = reg_order[i - 1];
1468+ for (j = 0; j < nops; j++)
1469+ if (regs[j] > regs[reg_order[i - 1]]
1470+ && (this_order == reg_order[i - 1]
1471+ || regs[j] < regs[this_order]))
1472+ this_order = j;
1473+ reg_order[i] = this_order;
1474+ }
1475+
1476+ /* Ensure that registers that must be live after the instruction end
1477+ up with the correct value. */
1478+ for (i = 0; i < nops; i++)
1479+ {
1480+ int this_order = reg_order[i];
1481+ if ((this_order != mem_order[i]
1482+ || orig_reg_rtxs[this_order] != reg_rtxs[this_order])
1483+ && !peep2_reg_dead_p (nops * 2, orig_reg_rtxs[this_order]))
1484+ return false;
1485+ }
1486+
1487+ /* Load the constants. */
1488+ for (i = 0; i < nops; i++)
1489+ {
1490+ rtx op = operands[2 * nops + mem_order[i]];
1491+ sorted_regs[i] = regs[reg_order[i]];
1492+ emit_move_insn (reg_rtxs[reg_order[i]], op);
1493+ }
1494+
1495+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1496+
1497+ base_reg_dies = peep2_reg_dead_p (nops * 2, base_reg_rtx);
1498+ if (TARGET_THUMB1)
1499+ {
1500+ gcc_assert (base_reg_dies);
1501+ write_back = TRUE;
1502+ }
1503+
1504+ if (stm_case == 5)
1505+ {
1506+ gcc_assert (base_reg_dies);
1507+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, GEN_INT (offset)));
1508+ offset = 0;
1509+ }
1510+
1511+ addr = plus_constant (base_reg_rtx, offset);
1512+
1513+ for (i = 0; i < nops; i++)
1514+ {
1515+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1516+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1517+ SImode, addr, 0);
1518+ }
1519+ emit_insn (arm_gen_store_multiple_1 (nops, sorted_regs, mems, base_reg_rtx,
1520+ write_back ? offset + i * 4 : 0));
1521+ return true;
1522 }
1523
1524 int
1525@@ -10280,20 +10535,21 @@ arm_gen_movmemqi (rtx *operands)
1526 for (i = 0; in_words_to_go >= 2; i+=4)
1527 {
1528 if (in_words_to_go > 4)
1529- emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
1530- srcbase, &srcoffset));
1531+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, src,
1532+ TRUE, srcbase, &srcoffset));
1533 else
1534- emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
1535- FALSE, srcbase, &srcoffset));
1536+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, in_words_to_go,
1537+ src, FALSE, srcbase,
1538+ &srcoffset));
1539
1540 if (out_words_to_go)
1541 {
1542 if (out_words_to_go > 4)
1543- emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
1544- dstbase, &dstoffset));
1545+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, dst,
1546+ TRUE, dstbase, &dstoffset));
1547 else if (out_words_to_go != 1)
1548- emit_insn (arm_gen_store_multiple (0, out_words_to_go,
1549- dst, TRUE,
1550+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence,
1551+ out_words_to_go, dst,
1552 (last_bytes == 0
1553 ? FALSE : TRUE),
1554 dstbase, &dstoffset));
1555Index: gcc-4_5-branch/gcc/config/arm/arm.h
1556===================================================================
1557--- gcc-4_5-branch.orig/gcc/config/arm/arm.h
1558+++ gcc-4_5-branch/gcc/config/arm/arm.h
1559@@ -1143,6 +1143,9 @@ extern int arm_structure_size_boundary;
1560 ((MODE) == TImode || (MODE) == EImode || (MODE) == OImode \
1561 || (MODE) == CImode || (MODE) == XImode)
1562
1563+/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
1564+extern int arm_regs_in_sequence[];
1565+
1566 /* The order in which register should be allocated. It is good to use ip
1567 since no saving is required (though calls clobber it) and it never contains
1568 function parameters. It is quite good to use lr since other calls may
1569@@ -2823,4 +2826,8 @@ enum arm_builtins
1570 #define NEED_INDICATE_EXEC_STACK 0
1571 #endif
1572
1573+/* The maximum number of parallel loads or stores we support in an ldm/stm
1574+ instruction. */
1575+#define MAX_LDM_STM_OPS 4
1576+
1577 #endif /* ! GCC_ARM_H */
1578Index: gcc-4_5-branch/gcc/config/arm/arm.md
1579===================================================================
1580--- gcc-4_5-branch.orig/gcc/config/arm/arm.md
1581+++ gcc-4_5-branch/gcc/config/arm/arm.md
1582@@ -6282,7 +6282,7 @@
1583
1584 ;; load- and store-multiple insns
1585 ;; The arm can load/store any set of registers, provided that they are in
1586-;; ascending order; but that is beyond GCC so stick with what it knows.
1587+;; ascending order, but these expanders assume a contiguous set.
1588
1589 (define_expand "load_multiple"
1590 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
1591@@ -6303,126 +6303,12 @@
1592 FAIL;
1593
1594 operands[3]
1595- = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
1596+ = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
1597+ INTVAL (operands[2]),
1598 force_reg (SImode, XEXP (operands[1], 0)),
1599- TRUE, FALSE, operands[1], &offset);
1600+ FALSE, operands[1], &offset);
1601 })
1602
1603-;; Load multiple with write-back
1604-
1605-(define_insn "*ldmsi_postinc4"
1606- [(match_parallel 0 "load_multiple_operation"
1607- [(set (match_operand:SI 1 "s_register_operand" "=r")
1608- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1609- (const_int 16)))
1610- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1611- (mem:SI (match_dup 2)))
1612- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1613- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1614- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1615- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
1616- (set (match_operand:SI 6 "arm_hard_register_operand" "")
1617- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
1618- "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
1619- "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
1620- [(set_attr "type" "load4")
1621- (set_attr "predicable" "yes")]
1622-)
1623-
1624-(define_insn "*ldmsi_postinc4_thumb1"
1625- [(match_parallel 0 "load_multiple_operation"
1626- [(set (match_operand:SI 1 "s_register_operand" "=l")
1627- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1628- (const_int 16)))
1629- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1630- (mem:SI (match_dup 2)))
1631- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1632- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1633- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1634- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
1635- (set (match_operand:SI 6 "arm_hard_register_operand" "")
1636- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
1637- "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
1638- "ldmia\\t%1!, {%3, %4, %5, %6}"
1639- [(set_attr "type" "load4")]
1640-)
1641-
1642-(define_insn "*ldmsi_postinc3"
1643- [(match_parallel 0 "load_multiple_operation"
1644- [(set (match_operand:SI 1 "s_register_operand" "=r")
1645- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1646- (const_int 12)))
1647- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1648- (mem:SI (match_dup 2)))
1649- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1650- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1651- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1652- (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
1653- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1654- "ldm%(ia%)\\t%1!, {%3, %4, %5}"
1655- [(set_attr "type" "load3")
1656- (set_attr "predicable" "yes")]
1657-)
1658-
1659-(define_insn "*ldmsi_postinc2"
1660- [(match_parallel 0 "load_multiple_operation"
1661- [(set (match_operand:SI 1 "s_register_operand" "=r")
1662- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1663- (const_int 8)))
1664- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1665- (mem:SI (match_dup 2)))
1666- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1667- (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
1668- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1669- "ldm%(ia%)\\t%1!, {%3, %4}"
1670- [(set_attr "type" "load2")
1671- (set_attr "predicable" "yes")]
1672-)
1673-
1674-;; Ordinary load multiple
1675-
1676-(define_insn "*ldmsi4"
1677- [(match_parallel 0 "load_multiple_operation"
1678- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1679- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1680- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1681- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
1682- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1683- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
1684- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1685- (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
1686- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1687- "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
1688- [(set_attr "type" "load4")
1689- (set_attr "predicable" "yes")]
1690-)
1691-
1692-(define_insn "*ldmsi3"
1693- [(match_parallel 0 "load_multiple_operation"
1694- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1695- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1696- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1697- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
1698- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1699- (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
1700- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1701- "ldm%(ia%)\\t%1, {%2, %3, %4}"
1702- [(set_attr "type" "load3")
1703- (set_attr "predicable" "yes")]
1704-)
1705-
1706-(define_insn "*ldmsi2"
1707- [(match_parallel 0 "load_multiple_operation"
1708- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1709- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1710- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1711- (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
1712- "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
1713- "ldm%(ia%)\\t%1, {%2, %3}"
1714- [(set_attr "type" "load2")
1715- (set_attr "predicable" "yes")]
1716-)
1717-
1718 (define_expand "store_multiple"
1719 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
1720 (match_operand:SI 1 "" ""))
1721@@ -6442,125 +6328,12 @@
1722 FAIL;
1723
1724 operands[3]
1725- = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
1726+ = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
1727+ INTVAL (operands[2]),
1728 force_reg (SImode, XEXP (operands[0], 0)),
1729- TRUE, FALSE, operands[0], &offset);
1730+ FALSE, operands[0], &offset);
1731 })
1732
1733-;; Store multiple with write-back
1734-
1735-(define_insn "*stmsi_postinc4"
1736- [(match_parallel 0 "store_multiple_operation"
1737- [(set (match_operand:SI 1 "s_register_operand" "=r")
1738- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1739- (const_int 16)))
1740- (set (mem:SI (match_dup 2))
1741- (match_operand:SI 3 "arm_hard_register_operand" ""))
1742- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1743- (match_operand:SI 4 "arm_hard_register_operand" ""))
1744- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1745- (match_operand:SI 5 "arm_hard_register_operand" ""))
1746- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
1747- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
1748- "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
1749- "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
1750- [(set_attr "predicable" "yes")
1751- (set_attr "type" "store4")]
1752-)
1753-
1754-(define_insn "*stmsi_postinc4_thumb1"
1755- [(match_parallel 0 "store_multiple_operation"
1756- [(set (match_operand:SI 1 "s_register_operand" "=l")
1757- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1758- (const_int 16)))
1759- (set (mem:SI (match_dup 2))
1760- (match_operand:SI 3 "arm_hard_register_operand" ""))
1761- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1762- (match_operand:SI 4 "arm_hard_register_operand" ""))
1763- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1764- (match_operand:SI 5 "arm_hard_register_operand" ""))
1765- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
1766- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
1767- "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
1768- "stmia\\t%1!, {%3, %4, %5, %6}"
1769- [(set_attr "type" "store4")]
1770-)
1771-
1772-(define_insn "*stmsi_postinc3"
1773- [(match_parallel 0 "store_multiple_operation"
1774- [(set (match_operand:SI 1 "s_register_operand" "=r")
1775- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1776- (const_int 12)))
1777- (set (mem:SI (match_dup 2))
1778- (match_operand:SI 3 "arm_hard_register_operand" ""))
1779- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1780- (match_operand:SI 4 "arm_hard_register_operand" ""))
1781- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1782- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
1783- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1784- "stm%(ia%)\\t%1!, {%3, %4, %5}"
1785- [(set_attr "predicable" "yes")
1786- (set_attr "type" "store3")]
1787-)
1788-
1789-(define_insn "*stmsi_postinc2"
1790- [(match_parallel 0 "store_multiple_operation"
1791- [(set (match_operand:SI 1 "s_register_operand" "=r")
1792- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1793- (const_int 8)))
1794- (set (mem:SI (match_dup 2))
1795- (match_operand:SI 3 "arm_hard_register_operand" ""))
1796- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1797- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
1798- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1799- "stm%(ia%)\\t%1!, {%3, %4}"
1800- [(set_attr "predicable" "yes")
1801- (set_attr "type" "store2")]
1802-)
1803-
1804-;; Ordinary store multiple
1805-
1806-(define_insn "*stmsi4"
1807- [(match_parallel 0 "store_multiple_operation"
1808- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1809- (match_operand:SI 2 "arm_hard_register_operand" ""))
1810- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1811- (match_operand:SI 3 "arm_hard_register_operand" ""))
1812- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
1813- (match_operand:SI 4 "arm_hard_register_operand" ""))
1814- (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
1815- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
1816- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1817- "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
1818- [(set_attr "predicable" "yes")
1819- (set_attr "type" "store4")]
1820-)
1821-
1822-(define_insn "*stmsi3"
1823- [(match_parallel 0 "store_multiple_operation"
1824- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1825- (match_operand:SI 2 "arm_hard_register_operand" ""))
1826- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1827- (match_operand:SI 3 "arm_hard_register_operand" ""))
1828- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
1829- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
1830- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1831- "stm%(ia%)\\t%1, {%2, %3, %4}"
1832- [(set_attr "predicable" "yes")
1833- (set_attr "type" "store3")]
1834-)
1835-
1836-(define_insn "*stmsi2"
1837- [(match_parallel 0 "store_multiple_operation"
1838- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1839- (match_operand:SI 2 "arm_hard_register_operand" ""))
1840- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1841- (match_operand:SI 3 "arm_hard_register_operand" ""))])]
1842- "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
1843- "stm%(ia%)\\t%1, {%2, %3}"
1844- [(set_attr "predicable" "yes")
1845- (set_attr "type" "store2")]
1846-)
1847
1848 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
1849 ;; We could let this apply for blocks of less than this, but it clobbers so
1850@@ -9031,8 +8804,8 @@
1851 if (REGNO (reg) == R0_REGNUM)
1852 {
1853 /* On thumb we have to use a write-back instruction. */
1854- emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
1855- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1856+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
1857+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1858 size = TARGET_ARM ? 16 : 0;
1859 }
1860 else
1861@@ -9078,8 +8851,8 @@
1862 if (REGNO (reg) == R0_REGNUM)
1863 {
1864 /* On thumb we have to use a write-back instruction. */
1865- emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
1866- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1867+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
1868+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1869 size = TARGET_ARM ? 16 : 0;
1870 }
1871 else
1872@@ -10672,87 +10445,6 @@
1873 ""
1874 )
1875
1876-; Peepholes to spot possible load- and store-multiples, if the ordering is
1877-; reversed, check that the memory references aren't volatile.
1878-
1879-(define_peephole
1880- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1881- (match_operand:SI 4 "memory_operand" "m"))
1882- (set (match_operand:SI 1 "s_register_operand" "=rk")
1883- (match_operand:SI 5 "memory_operand" "m"))
1884- (set (match_operand:SI 2 "s_register_operand" "=rk")
1885- (match_operand:SI 6 "memory_operand" "m"))
1886- (set (match_operand:SI 3 "s_register_operand" "=rk")
1887- (match_operand:SI 7 "memory_operand" "m"))]
1888- "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
1889- "*
1890- return emit_ldm_seq (operands, 4);
1891- "
1892-)
1893-
1894-(define_peephole
1895- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1896- (match_operand:SI 3 "memory_operand" "m"))
1897- (set (match_operand:SI 1 "s_register_operand" "=rk")
1898- (match_operand:SI 4 "memory_operand" "m"))
1899- (set (match_operand:SI 2 "s_register_operand" "=rk")
1900- (match_operand:SI 5 "memory_operand" "m"))]
1901- "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
1902- "*
1903- return emit_ldm_seq (operands, 3);
1904- "
1905-)
1906-
1907-(define_peephole
1908- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1909- (match_operand:SI 2 "memory_operand" "m"))
1910- (set (match_operand:SI 1 "s_register_operand" "=rk")
1911- (match_operand:SI 3 "memory_operand" "m"))]
1912- "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
1913- "*
1914- return emit_ldm_seq (operands, 2);
1915- "
1916-)
1917-
1918-(define_peephole
1919- [(set (match_operand:SI 4 "memory_operand" "=m")
1920- (match_operand:SI 0 "s_register_operand" "rk"))
1921- (set (match_operand:SI 5 "memory_operand" "=m")
1922- (match_operand:SI 1 "s_register_operand" "rk"))
1923- (set (match_operand:SI 6 "memory_operand" "=m")
1924- (match_operand:SI 2 "s_register_operand" "rk"))
1925- (set (match_operand:SI 7 "memory_operand" "=m")
1926- (match_operand:SI 3 "s_register_operand" "rk"))]
1927- "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
1928- "*
1929- return emit_stm_seq (operands, 4);
1930- "
1931-)
1932-
1933-(define_peephole
1934- [(set (match_operand:SI 3 "memory_operand" "=m")
1935- (match_operand:SI 0 "s_register_operand" "rk"))
1936- (set (match_operand:SI 4 "memory_operand" "=m")
1937- (match_operand:SI 1 "s_register_operand" "rk"))
1938- (set (match_operand:SI 5 "memory_operand" "=m")
1939- (match_operand:SI 2 "s_register_operand" "rk"))]
1940- "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
1941- "*
1942- return emit_stm_seq (operands, 3);
1943- "
1944-)
1945-
1946-(define_peephole
1947- [(set (match_operand:SI 2 "memory_operand" "=m")
1948- (match_operand:SI 0 "s_register_operand" "rk"))
1949- (set (match_operand:SI 3 "memory_operand" "=m")
1950- (match_operand:SI 1 "s_register_operand" "rk"))]
1951- "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
1952- "*
1953- return emit_stm_seq (operands, 2);
1954- "
1955-)
1956-
1957 (define_split
1958 [(set (match_operand:SI 0 "s_register_operand" "")
1959 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
1960@@ -11554,6 +11246,8 @@
1961 "
1962 )
1963
1964+;; Load the load/store multiple patterns
1965+(include "ldmstm.md")
1966 ;; Load the FPA co-processor patterns
1967 (include "fpa.md")
1968 ;; Load the Maverick co-processor patterns
1969Index: gcc-4_5-branch/gcc/config/arm/ldmstm.md
1970===================================================================
1971--- /dev/null
1972+++ gcc-4_5-branch/gcc/config/arm/ldmstm.md
1973@@ -0,0 +1,1191 @@
1974+/* ARM ldm/stm instruction patterns. This file was automatically generated
1975+ using arm-ldmstm.ml. Please do not edit manually.
1976+
1977+ Copyright (C) 2010 Free Software Foundation, Inc.
1978+ Contributed by CodeSourcery.
1979+
1980+ This file is part of GCC.
1981+
1982+ GCC is free software; you can redistribute it and/or modify it
1983+ under the terms of the GNU General Public License as published
1984+ by the Free Software Foundation; either version 3, or (at your
1985+ option) any later version.
1986+
1987+ GCC is distributed in the hope that it will be useful, but WITHOUT
1988+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1989+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1990+ License for more details.
1991+
1992+ You should have received a copy of the GNU General Public License and
1993+ a copy of the GCC Runtime Library Exception along with this program;
1994+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
1995+ <http://www.gnu.org/licenses/>. */
1996+
1997+(define_insn "*ldm4_ia"
1998+ [(match_parallel 0 "load_multiple_operation"
1999+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2000+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2001+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2002+ (mem:SI (plus:SI (match_dup 1)
2003+ (const_int 4))))
2004+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2005+ (mem:SI (plus:SI (match_dup 1)
2006+ (const_int 8))))
2007+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2008+ (mem:SI (plus:SI (match_dup 1)
2009+ (const_int 12))))])]
2010+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2011+ "ldm%(ia%)\t%1, {%2, %3, %4, %5}"
2012+ [(set_attr "type" "load4")
2013+ (set_attr "predicable" "yes")])
2014+
2015+(define_insn "*thumb_ldm4_ia"
2016+ [(match_parallel 0 "load_multiple_operation"
2017+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2018+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2019+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2020+ (mem:SI (plus:SI (match_dup 1)
2021+ (const_int 4))))
2022+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2023+ (mem:SI (plus:SI (match_dup 1)
2024+ (const_int 8))))
2025+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2026+ (mem:SI (plus:SI (match_dup 1)
2027+ (const_int 12))))])]
2028+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2029+ "ldm%(ia%)\t%1, {%2, %3, %4, %5}"
2030+ [(set_attr "type" "load4")])
2031+
2032+(define_insn "*ldm4_ia_update"
2033+ [(match_parallel 0 "load_multiple_operation"
2034+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2035+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2036+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2037+ (mem:SI (match_dup 2)))
2038+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2039+ (mem:SI (plus:SI (match_dup 2)
2040+ (const_int 4))))
2041+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2042+ (mem:SI (plus:SI (match_dup 2)
2043+ (const_int 8))))
2044+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2045+ (mem:SI (plus:SI (match_dup 2)
2046+ (const_int 12))))])]
2047+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2048+ "ldm%(ia%)\t%1!, {%3, %4, %5, %6}"
2049+ [(set_attr "type" "load4")
2050+ (set_attr "predicable" "yes")])
2051+
2052+(define_insn "*thumb_ldm4_ia_update"
2053+ [(match_parallel 0 "load_multiple_operation"
2054+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2055+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2056+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2057+ (mem:SI (match_dup 2)))
2058+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2059+ (mem:SI (plus:SI (match_dup 2)
2060+ (const_int 4))))
2061+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2062+ (mem:SI (plus:SI (match_dup 2)
2063+ (const_int 8))))
2064+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2065+ (mem:SI (plus:SI (match_dup 2)
2066+ (const_int 12))))])]
2067+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
2068+ "ldm%(ia%)\t%1!, {%3, %4, %5, %6}"
2069+ [(set_attr "type" "load4")])
2070+
2071+(define_insn "*stm4_ia"
2072+ [(match_parallel 0 "store_multiple_operation"
2073+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2074+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2075+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2076+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2077+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2078+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2079+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2080+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2081+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2082+ "stm%(ia%)\t%1, {%2, %3, %4, %5}"
2083+ [(set_attr "type" "store4")
2084+ (set_attr "predicable" "yes")])
2085+
2086+(define_insn "*stm4_ia_update"
2087+ [(match_parallel 0 "store_multiple_operation"
2088+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2089+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2090+ (set (mem:SI (match_dup 2))
2091+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2092+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2093+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2094+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2095+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2096+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2097+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2098+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2099+ "stm%(ia%)\t%1!, {%3, %4, %5, %6}"
2100+ [(set_attr "type" "store4")
2101+ (set_attr "predicable" "yes")])
2102+
2103+(define_insn "*thumb_stm4_ia_update"
2104+ [(match_parallel 0 "store_multiple_operation"
2105+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2106+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2107+ (set (mem:SI (match_dup 2))
2108+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2109+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2110+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2111+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2112+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2113+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2114+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2115+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
2116+ "stm%(ia%)\t%1!, {%3, %4, %5, %6}"
2117+ [(set_attr "type" "store4")])
2118+
2119+(define_insn "*ldm4_ib"
2120+ [(match_parallel 0 "load_multiple_operation"
2121+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2122+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2123+ (const_int 4))))
2124+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2125+ (mem:SI (plus:SI (match_dup 1)
2126+ (const_int 8))))
2127+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2128+ (mem:SI (plus:SI (match_dup 1)
2129+ (const_int 12))))
2130+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2131+ (mem:SI (plus:SI (match_dup 1)
2132+ (const_int 16))))])]
2133+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2134+ "ldm%(ib%)\t%1, {%2, %3, %4, %5}"
2135+ [(set_attr "type" "load4")
2136+ (set_attr "predicable" "yes")])
2137+
2138+(define_insn "*ldm4_ib_update"
2139+ [(match_parallel 0 "load_multiple_operation"
2140+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2141+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2142+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2143+ (mem:SI (plus:SI (match_dup 2)
2144+ (const_int 4))))
2145+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2146+ (mem:SI (plus:SI (match_dup 2)
2147+ (const_int 8))))
2148+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2149+ (mem:SI (plus:SI (match_dup 2)
2150+ (const_int 12))))
2151+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2152+ (mem:SI (plus:SI (match_dup 2)
2153+ (const_int 16))))])]
2154+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2155+ "ldm%(ib%)\t%1!, {%3, %4, %5, %6}"
2156+ [(set_attr "type" "load4")
2157+ (set_attr "predicable" "yes")])
2158+
2159+(define_insn "*stm4_ib"
2160+ [(match_parallel 0 "store_multiple_operation"
2161+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2162+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2163+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2164+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2165+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2166+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2167+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
2168+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2169+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2170+ "stm%(ib%)\t%1, {%2, %3, %4, %5}"
2171+ [(set_attr "type" "store4")
2172+ (set_attr "predicable" "yes")])
2173+
2174+(define_insn "*stm4_ib_update"
2175+ [(match_parallel 0 "store_multiple_operation"
2176+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2177+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2178+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2179+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2180+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2181+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2182+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2183+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2184+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16)))
2185+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2186+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2187+ "stm%(ib%)\t%1!, {%3, %4, %5, %6}"
2188+ [(set_attr "type" "store4")
2189+ (set_attr "predicable" "yes")])
2190+
2191+(define_insn "*ldm4_da"
2192+ [(match_parallel 0 "load_multiple_operation"
2193+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2194+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2195+ (const_int -12))))
2196+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2197+ (mem:SI (plus:SI (match_dup 1)
2198+ (const_int -8))))
2199+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2200+ (mem:SI (plus:SI (match_dup 1)
2201+ (const_int -4))))
2202+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2203+ (mem:SI (match_dup 1)))])]
2204+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2205+ "ldm%(da%)\t%1, {%2, %3, %4, %5}"
2206+ [(set_attr "type" "load4")
2207+ (set_attr "predicable" "yes")])
2208+
2209+(define_insn "*ldm4_da_update"
2210+ [(match_parallel 0 "load_multiple_operation"
2211+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2212+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2213+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2214+ (mem:SI (plus:SI (match_dup 2)
2215+ (const_int -12))))
2216+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2217+ (mem:SI (plus:SI (match_dup 2)
2218+ (const_int -8))))
2219+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2220+ (mem:SI (plus:SI (match_dup 2)
2221+ (const_int -4))))
2222+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2223+ (mem:SI (match_dup 2)))])]
2224+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2225+ "ldm%(da%)\t%1!, {%3, %4, %5, %6}"
2226+ [(set_attr "type" "load4")
2227+ (set_attr "predicable" "yes")])
2228+
2229+(define_insn "*stm4_da"
2230+ [(match_parallel 0 "store_multiple_operation"
2231+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -12)))
2232+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2233+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2234+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2235+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2236+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2237+ (set (mem:SI (match_dup 1))
2238+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2239+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2240+ "stm%(da%)\t%1, {%2, %3, %4, %5}"
2241+ [(set_attr "type" "store4")
2242+ (set_attr "predicable" "yes")])
2243+
2244+(define_insn "*stm4_da_update"
2245+ [(match_parallel 0 "store_multiple_operation"
2246+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2247+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2248+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2249+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2250+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2251+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2252+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2253+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2254+ (set (mem:SI (match_dup 2))
2255+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2256+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2257+ "stm%(da%)\t%1!, {%3, %4, %5, %6}"
2258+ [(set_attr "type" "store4")
2259+ (set_attr "predicable" "yes")])
2260+
2261+(define_insn "*ldm4_db"
2262+ [(match_parallel 0 "load_multiple_operation"
2263+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2264+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2265+ (const_int -16))))
2266+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2267+ (mem:SI (plus:SI (match_dup 1)
2268+ (const_int -12))))
2269+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2270+ (mem:SI (plus:SI (match_dup 1)
2271+ (const_int -8))))
2272+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2273+ (mem:SI (plus:SI (match_dup 1)
2274+ (const_int -4))))])]
2275+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2276+ "ldm%(db%)\t%1, {%2, %3, %4, %5}"
2277+ [(set_attr "type" "load4")
2278+ (set_attr "predicable" "yes")])
2279+
2280+(define_insn "*ldm4_db_update"
2281+ [(match_parallel 0 "load_multiple_operation"
2282+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2283+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2284+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2285+ (mem:SI (plus:SI (match_dup 2)
2286+ (const_int -16))))
2287+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2288+ (mem:SI (plus:SI (match_dup 2)
2289+ (const_int -12))))
2290+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2291+ (mem:SI (plus:SI (match_dup 2)
2292+ (const_int -8))))
2293+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2294+ (mem:SI (plus:SI (match_dup 2)
2295+ (const_int -4))))])]
2296+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2297+ "ldm%(db%)\t%1!, {%3, %4, %5, %6}"
2298+ [(set_attr "type" "load4")
2299+ (set_attr "predicable" "yes")])
2300+
2301+(define_insn "*stm4_db"
2302+ [(match_parallel 0 "store_multiple_operation"
2303+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -16)))
2304+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2305+ (set (mem:SI (plus:SI (match_dup 1) (const_int -12)))
2306+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2307+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2308+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2309+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2310+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2311+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2312+ "stm%(db%)\t%1, {%2, %3, %4, %5}"
2313+ [(set_attr "type" "store4")
2314+ (set_attr "predicable" "yes")])
2315+
2316+(define_insn "*stm4_db_update"
2317+ [(match_parallel 0 "store_multiple_operation"
2318+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2319+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2320+ (set (mem:SI (plus:SI (match_dup 2) (const_int -16)))
2321+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2322+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2323+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2324+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2325+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2326+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2327+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2328+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2329+ "stm%(db%)\t%1!, {%3, %4, %5, %6}"
2330+ [(set_attr "type" "store4")
2331+ (set_attr "predicable" "yes")])
2332+
2333+(define_peephole2
2334+ [(set (match_operand:SI 0 "s_register_operand" "")
2335+ (match_operand:SI 4 "memory_operand" ""))
2336+ (set (match_operand:SI 1 "s_register_operand" "")
2337+ (match_operand:SI 5 "memory_operand" ""))
2338+ (set (match_operand:SI 2 "s_register_operand" "")
2339+ (match_operand:SI 6 "memory_operand" ""))
2340+ (set (match_operand:SI 3 "s_register_operand" "")
2341+ (match_operand:SI 7 "memory_operand" ""))]
2342+ ""
2343+ [(const_int 0)]
2344+{
2345+ if (gen_ldm_seq (operands, 4, false))
2346+ DONE;
2347+ else
2348+ FAIL;
2349+})
2350+
2351+(define_peephole2
2352+ [(set (match_operand:SI 0 "s_register_operand" "")
2353+ (match_operand:SI 4 "memory_operand" ""))
2354+ (parallel
2355+ [(set (match_operand:SI 1 "s_register_operand" "")
2356+ (match_operand:SI 5 "memory_operand" ""))
2357+ (set (match_operand:SI 2 "s_register_operand" "")
2358+ (match_operand:SI 6 "memory_operand" ""))
2359+ (set (match_operand:SI 3 "s_register_operand" "")
2360+ (match_operand:SI 7 "memory_operand" ""))])]
2361+ ""
2362+ [(const_int 0)]
2363+{
2364+ if (gen_ldm_seq (operands, 4, false))
2365+ DONE;
2366+ else
2367+ FAIL;
2368+})
2369+
2370+(define_peephole2
2371+ [(set (match_operand:SI 0 "s_register_operand" "")
2372+ (match_operand:SI 8 "const_int_operand" ""))
2373+ (set (match_operand:SI 4 "memory_operand" "")
2374+ (match_dup 0))
2375+ (set (match_operand:SI 1 "s_register_operand" "")
2376+ (match_operand:SI 9 "const_int_operand" ""))
2377+ (set (match_operand:SI 5 "memory_operand" "")
2378+ (match_dup 1))
2379+ (set (match_operand:SI 2 "s_register_operand" "")
2380+ (match_operand:SI 10 "const_int_operand" ""))
2381+ (set (match_operand:SI 6 "memory_operand" "")
2382+ (match_dup 2))
2383+ (set (match_operand:SI 3 "s_register_operand" "")
2384+ (match_operand:SI 11 "const_int_operand" ""))
2385+ (set (match_operand:SI 7 "memory_operand" "")
2386+ (match_dup 3))]
2387+ ""
2388+ [(const_int 0)]
2389+{
2390+ if (gen_const_stm_seq (operands, 4))
2391+ DONE;
2392+ else
2393+ FAIL;
2394+})
2395+
2396+(define_peephole2
2397+ [(set (match_operand:SI 0 "s_register_operand" "")
2398+ (match_operand:SI 8 "const_int_operand" ""))
2399+ (set (match_operand:SI 1 "s_register_operand" "")
2400+ (match_operand:SI 9 "const_int_operand" ""))
2401+ (set (match_operand:SI 2 "s_register_operand" "")
2402+ (match_operand:SI 10 "const_int_operand" ""))
2403+ (set (match_operand:SI 3 "s_register_operand" "")
2404+ (match_operand:SI 11 "const_int_operand" ""))
2405+ (set (match_operand:SI 4 "memory_operand" "")
2406+ (match_dup 0))
2407+ (set (match_operand:SI 5 "memory_operand" "")
2408+ (match_dup 1))
2409+ (set (match_operand:SI 6 "memory_operand" "")
2410+ (match_dup 2))
2411+ (set (match_operand:SI 7 "memory_operand" "")
2412+ (match_dup 3))]
2413+ ""
2414+ [(const_int 0)]
2415+{
2416+ if (gen_const_stm_seq (operands, 4))
2417+ DONE;
2418+ else
2419+ FAIL;
2420+})
2421+
2422+(define_peephole2
2423+ [(set (match_operand:SI 4 "memory_operand" "")
2424+ (match_operand:SI 0 "s_register_operand" ""))
2425+ (set (match_operand:SI 5 "memory_operand" "")
2426+ (match_operand:SI 1 "s_register_operand" ""))
2427+ (set (match_operand:SI 6 "memory_operand" "")
2428+ (match_operand:SI 2 "s_register_operand" ""))
2429+ (set (match_operand:SI 7 "memory_operand" "")
2430+ (match_operand:SI 3 "s_register_operand" ""))]
2431+ ""
2432+ [(const_int 0)]
2433+{
2434+ if (gen_stm_seq (operands, 4))
2435+ DONE;
2436+ else
2437+ FAIL;
2438+})
2439+
2440+(define_insn "*ldm3_ia"
2441+ [(match_parallel 0 "load_multiple_operation"
2442+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2443+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2444+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2445+ (mem:SI (plus:SI (match_dup 1)
2446+ (const_int 4))))
2447+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2448+ (mem:SI (plus:SI (match_dup 1)
2449+ (const_int 8))))])]
2450+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2451+ "ldm%(ia%)\t%1, {%2, %3, %4}"
2452+ [(set_attr "type" "load3")
2453+ (set_attr "predicable" "yes")])
2454+
2455+(define_insn "*thumb_ldm3_ia"
2456+ [(match_parallel 0 "load_multiple_operation"
2457+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2458+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2459+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2460+ (mem:SI (plus:SI (match_dup 1)
2461+ (const_int 4))))
2462+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2463+ (mem:SI (plus:SI (match_dup 1)
2464+ (const_int 8))))])]
2465+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2466+ "ldm%(ia%)\t%1, {%2, %3, %4}"
2467+ [(set_attr "type" "load3")])
2468+
2469+(define_insn "*ldm3_ia_update"
2470+ [(match_parallel 0 "load_multiple_operation"
2471+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2472+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2473+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2474+ (mem:SI (match_dup 2)))
2475+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2476+ (mem:SI (plus:SI (match_dup 2)
2477+ (const_int 4))))
2478+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2479+ (mem:SI (plus:SI (match_dup 2)
2480+ (const_int 8))))])]
2481+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2482+ "ldm%(ia%)\t%1!, {%3, %4, %5}"
2483+ [(set_attr "type" "load3")
2484+ (set_attr "predicable" "yes")])
2485+
2486+(define_insn "*thumb_ldm3_ia_update"
2487+ [(match_parallel 0 "load_multiple_operation"
2488+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2489+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2490+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2491+ (mem:SI (match_dup 2)))
2492+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2493+ (mem:SI (plus:SI (match_dup 2)
2494+ (const_int 4))))
2495+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2496+ (mem:SI (plus:SI (match_dup 2)
2497+ (const_int 8))))])]
2498+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2499+ "ldm%(ia%)\t%1!, {%3, %4, %5}"
2500+ [(set_attr "type" "load3")])
2501+
2502+(define_insn "*stm3_ia"
2503+ [(match_parallel 0 "store_multiple_operation"
2504+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2505+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2506+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2507+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2508+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2509+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2510+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2511+ "stm%(ia%)\t%1, {%2, %3, %4}"
2512+ [(set_attr "type" "store3")
2513+ (set_attr "predicable" "yes")])
2514+
2515+(define_insn "*stm3_ia_update"
2516+ [(match_parallel 0 "store_multiple_operation"
2517+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2518+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2519+ (set (mem:SI (match_dup 2))
2520+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2521+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2522+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2523+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2524+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2525+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2526+ "stm%(ia%)\t%1!, {%3, %4, %5}"
2527+ [(set_attr "type" "store3")
2528+ (set_attr "predicable" "yes")])
2529+
2530+(define_insn "*thumb_stm3_ia_update"
2531+ [(match_parallel 0 "store_multiple_operation"
2532+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2533+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2534+ (set (mem:SI (match_dup 2))
2535+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2536+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2537+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2538+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2539+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2540+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2541+ "stm%(ia%)\t%1!, {%3, %4, %5}"
2542+ [(set_attr "type" "store3")])
2543+
2544+(define_insn "*ldm3_ib"
2545+ [(match_parallel 0 "load_multiple_operation"
2546+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2547+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2548+ (const_int 4))))
2549+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2550+ (mem:SI (plus:SI (match_dup 1)
2551+ (const_int 8))))
2552+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2553+ (mem:SI (plus:SI (match_dup 1)
2554+ (const_int 12))))])]
2555+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2556+ "ldm%(ib%)\t%1, {%2, %3, %4}"
2557+ [(set_attr "type" "load3")
2558+ (set_attr "predicable" "yes")])
2559+
2560+(define_insn "*ldm3_ib_update"
2561+ [(match_parallel 0 "load_multiple_operation"
2562+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2563+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2564+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2565+ (mem:SI (plus:SI (match_dup 2)
2566+ (const_int 4))))
2567+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2568+ (mem:SI (plus:SI (match_dup 2)
2569+ (const_int 8))))
2570+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2571+ (mem:SI (plus:SI (match_dup 2)
2572+ (const_int 12))))])]
2573+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2574+ "ldm%(ib%)\t%1!, {%3, %4, %5}"
2575+ [(set_attr "type" "load3")
2576+ (set_attr "predicable" "yes")])
2577+
2578+(define_insn "*stm3_ib"
2579+ [(match_parallel 0 "store_multiple_operation"
2580+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2581+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2582+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2583+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2584+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2585+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2586+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2587+ "stm%(ib%)\t%1, {%2, %3, %4}"
2588+ [(set_attr "type" "store3")
2589+ (set_attr "predicable" "yes")])
2590+
2591+(define_insn "*stm3_ib_update"
2592+ [(match_parallel 0 "store_multiple_operation"
2593+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2594+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2595+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2596+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2597+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2598+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2599+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2600+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2601+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2602+ "stm%(ib%)\t%1!, {%3, %4, %5}"
2603+ [(set_attr "type" "store3")
2604+ (set_attr "predicable" "yes")])
2605+
2606+(define_insn "*ldm3_da"
2607+ [(match_parallel 0 "load_multiple_operation"
2608+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2609+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2610+ (const_int -8))))
2611+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2612+ (mem:SI (plus:SI (match_dup 1)
2613+ (const_int -4))))
2614+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2615+ (mem:SI (match_dup 1)))])]
2616+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2617+ "ldm%(da%)\t%1, {%2, %3, %4}"
2618+ [(set_attr "type" "load3")
2619+ (set_attr "predicable" "yes")])
2620+
2621+(define_insn "*ldm3_da_update"
2622+ [(match_parallel 0 "load_multiple_operation"
2623+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2624+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2625+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2626+ (mem:SI (plus:SI (match_dup 2)
2627+ (const_int -8))))
2628+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2629+ (mem:SI (plus:SI (match_dup 2)
2630+ (const_int -4))))
2631+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2632+ (mem:SI (match_dup 2)))])]
2633+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2634+ "ldm%(da%)\t%1!, {%3, %4, %5}"
2635+ [(set_attr "type" "load3")
2636+ (set_attr "predicable" "yes")])
2637+
2638+(define_insn "*stm3_da"
2639+ [(match_parallel 0 "store_multiple_operation"
2640+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -8)))
2641+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2642+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2643+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2644+ (set (mem:SI (match_dup 1))
2645+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2646+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2647+ "stm%(da%)\t%1, {%2, %3, %4}"
2648+ [(set_attr "type" "store3")
2649+ (set_attr "predicable" "yes")])
2650+
2651+(define_insn "*stm3_da_update"
2652+ [(match_parallel 0 "store_multiple_operation"
2653+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2654+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2655+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2656+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2657+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2658+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2659+ (set (mem:SI (match_dup 2))
2660+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2661+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2662+ "stm%(da%)\t%1!, {%3, %4, %5}"
2663+ [(set_attr "type" "store3")
2664+ (set_attr "predicable" "yes")])
2665+
2666+(define_insn "*ldm3_db"
2667+ [(match_parallel 0 "load_multiple_operation"
2668+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2669+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2670+ (const_int -12))))
2671+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2672+ (mem:SI (plus:SI (match_dup 1)
2673+ (const_int -8))))
2674+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2675+ (mem:SI (plus:SI (match_dup 1)
2676+ (const_int -4))))])]
2677+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2678+ "ldm%(db%)\t%1, {%2, %3, %4}"
2679+ [(set_attr "type" "load3")
2680+ (set_attr "predicable" "yes")])
2681+
2682+(define_insn "*ldm3_db_update"
2683+ [(match_parallel 0 "load_multiple_operation"
2684+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2685+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2686+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2687+ (mem:SI (plus:SI (match_dup 2)
2688+ (const_int -12))))
2689+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2690+ (mem:SI (plus:SI (match_dup 2)
2691+ (const_int -8))))
2692+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2693+ (mem:SI (plus:SI (match_dup 2)
2694+ (const_int -4))))])]
2695+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2696+ "ldm%(db%)\t%1!, {%3, %4, %5}"
2697+ [(set_attr "type" "load3")
2698+ (set_attr "predicable" "yes")])
2699+
2700+(define_insn "*stm3_db"
2701+ [(match_parallel 0 "store_multiple_operation"
2702+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -12)))
2703+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2704+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2705+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2706+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2707+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2708+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2709+ "stm%(db%)\t%1, {%2, %3, %4}"
2710+ [(set_attr "type" "store3")
2711+ (set_attr "predicable" "yes")])
2712+
2713+(define_insn "*stm3_db_update"
2714+ [(match_parallel 0 "store_multiple_operation"
2715+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2716+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2717+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2718+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2719+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2720+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2721+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2722+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2723+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2724+ "stm%(db%)\t%1!, {%3, %4, %5}"
2725+ [(set_attr "type" "store3")
2726+ (set_attr "predicable" "yes")])
2727+
2728+(define_peephole2
2729+ [(set (match_operand:SI 0 "s_register_operand" "")
2730+ (match_operand:SI 3 "memory_operand" ""))
2731+ (set (match_operand:SI 1 "s_register_operand" "")
2732+ (match_operand:SI 4 "memory_operand" ""))
2733+ (set (match_operand:SI 2 "s_register_operand" "")
2734+ (match_operand:SI 5 "memory_operand" ""))]
2735+ ""
2736+ [(const_int 0)]
2737+{
2738+ if (gen_ldm_seq (operands, 3, false))
2739+ DONE;
2740+ else
2741+ FAIL;
2742+})
2743+
2744+(define_peephole2
2745+ [(set (match_operand:SI 0 "s_register_operand" "")
2746+ (match_operand:SI 3 "memory_operand" ""))
2747+ (parallel
2748+ [(set (match_operand:SI 1 "s_register_operand" "")
2749+ (match_operand:SI 4 "memory_operand" ""))
2750+ (set (match_operand:SI 2 "s_register_operand" "")
2751+ (match_operand:SI 5 "memory_operand" ""))])]
2752+ ""
2753+ [(const_int 0)]
2754+{
2755+ if (gen_ldm_seq (operands, 3, false))
2756+ DONE;
2757+ else
2758+ FAIL;
2759+})
2760+
2761+(define_peephole2
2762+ [(set (match_operand:SI 0 "s_register_operand" "")
2763+ (match_operand:SI 6 "const_int_operand" ""))
2764+ (set (match_operand:SI 3 "memory_operand" "")
2765+ (match_dup 0))
2766+ (set (match_operand:SI 1 "s_register_operand" "")
2767+ (match_operand:SI 7 "const_int_operand" ""))
2768+ (set (match_operand:SI 4 "memory_operand" "")
2769+ (match_dup 1))
2770+ (set (match_operand:SI 2 "s_register_operand" "")
2771+ (match_operand:SI 8 "const_int_operand" ""))
2772+ (set (match_operand:SI 5 "memory_operand" "")
2773+ (match_dup 2))]
2774+ ""
2775+ [(const_int 0)]
2776+{
2777+ if (gen_const_stm_seq (operands, 3))
2778+ DONE;
2779+ else
2780+ FAIL;
2781+})
2782+
2783+(define_peephole2
2784+ [(set (match_operand:SI 0 "s_register_operand" "")
2785+ (match_operand:SI 6 "const_int_operand" ""))
2786+ (set (match_operand:SI 1 "s_register_operand" "")
2787+ (match_operand:SI 7 "const_int_operand" ""))
2788+ (set (match_operand:SI 2 "s_register_operand" "")
2789+ (match_operand:SI 8 "const_int_operand" ""))
2790+ (set (match_operand:SI 3 "memory_operand" "")
2791+ (match_dup 0))
2792+ (set (match_operand:SI 4 "memory_operand" "")
2793+ (match_dup 1))
2794+ (set (match_operand:SI 5 "memory_operand" "")
2795+ (match_dup 2))]
2796+ ""
2797+ [(const_int 0)]
2798+{
2799+ if (gen_const_stm_seq (operands, 3))
2800+ DONE;
2801+ else
2802+ FAIL;
2803+})
2804+
2805+(define_peephole2
2806+ [(set (match_operand:SI 3 "memory_operand" "")
2807+ (match_operand:SI 0 "s_register_operand" ""))
2808+ (set (match_operand:SI 4 "memory_operand" "")
2809+ (match_operand:SI 1 "s_register_operand" ""))
2810+ (set (match_operand:SI 5 "memory_operand" "")
2811+ (match_operand:SI 2 "s_register_operand" ""))]
2812+ ""
2813+ [(const_int 0)]
2814+{
2815+ if (gen_stm_seq (operands, 3))
2816+ DONE;
2817+ else
2818+ FAIL;
2819+})
2820+
2821+(define_insn "*ldm2_ia"
2822+ [(match_parallel 0 "load_multiple_operation"
2823+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2824+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2825+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2826+ (mem:SI (plus:SI (match_dup 1)
2827+ (const_int 4))))])]
2828+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
2829+ "ldm%(ia%)\t%1, {%2, %3}"
2830+ [(set_attr "type" "load2")
2831+ (set_attr "predicable" "yes")])
2832+
2833+(define_insn "*thumb_ldm2_ia"
2834+ [(match_parallel 0 "load_multiple_operation"
2835+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2836+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2837+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2838+ (mem:SI (plus:SI (match_dup 1)
2839+ (const_int 4))))])]
2840+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 2"
2841+ "ldm%(ia%)\t%1, {%2, %3}"
2842+ [(set_attr "type" "load2")])
2843+
2844+(define_insn "*ldm2_ia_update"
2845+ [(match_parallel 0 "load_multiple_operation"
2846+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2847+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2848+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2849+ (mem:SI (match_dup 2)))
2850+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2851+ (mem:SI (plus:SI (match_dup 2)
2852+ (const_int 4))))])]
2853+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2854+ "ldm%(ia%)\t%1!, {%3, %4}"
2855+ [(set_attr "type" "load2")
2856+ (set_attr "predicable" "yes")])
2857+
2858+(define_insn "*thumb_ldm2_ia_update"
2859+ [(match_parallel 0 "load_multiple_operation"
2860+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2861+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2862+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2863+ (mem:SI (match_dup 2)))
2864+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2865+ (mem:SI (plus:SI (match_dup 2)
2866+ (const_int 4))))])]
2867+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2868+ "ldm%(ia%)\t%1!, {%3, %4}"
2869+ [(set_attr "type" "load2")])
2870+
2871+(define_insn "*stm2_ia"
2872+ [(match_parallel 0 "store_multiple_operation"
2873+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2874+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2875+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2876+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
2877+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
2878+ "stm%(ia%)\t%1, {%2, %3}"
2879+ [(set_attr "type" "store2")
2880+ (set_attr "predicable" "yes")])
2881+
2882+(define_insn "*stm2_ia_update"
2883+ [(match_parallel 0 "store_multiple_operation"
2884+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2885+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2886+ (set (mem:SI (match_dup 2))
2887+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2888+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2889+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2890+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2891+ "stm%(ia%)\t%1!, {%3, %4}"
2892+ [(set_attr "type" "store2")
2893+ (set_attr "predicable" "yes")])
2894+
2895+(define_insn "*thumb_stm2_ia_update"
2896+ [(match_parallel 0 "store_multiple_operation"
2897+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2898+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2899+ (set (mem:SI (match_dup 2))
2900+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2901+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2902+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2903+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2904+ "stm%(ia%)\t%1!, {%3, %4}"
2905+ [(set_attr "type" "store2")])
2906+
2907+(define_insn "*ldm2_ib"
2908+ [(match_parallel 0 "load_multiple_operation"
2909+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2910+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2911+ (const_int 4))))
2912+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2913+ (mem:SI (plus:SI (match_dup 1)
2914+ (const_int 8))))])]
2915+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2916+ "ldm%(ib%)\t%1, {%2, %3}"
2917+ [(set_attr "type" "load2")
2918+ (set_attr "predicable" "yes")])
2919+
2920+(define_insn "*ldm2_ib_update"
2921+ [(match_parallel 0 "load_multiple_operation"
2922+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2923+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2924+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2925+ (mem:SI (plus:SI (match_dup 2)
2926+ (const_int 4))))
2927+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2928+ (mem:SI (plus:SI (match_dup 2)
2929+ (const_int 8))))])]
2930+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2931+ "ldm%(ib%)\t%1!, {%3, %4}"
2932+ [(set_attr "type" "load2")
2933+ (set_attr "predicable" "yes")])
2934+
2935+(define_insn "*stm2_ib"
2936+ [(match_parallel 0 "store_multiple_operation"
2937+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2938+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2939+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2940+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
2941+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2942+ "stm%(ib%)\t%1, {%2, %3}"
2943+ [(set_attr "type" "store2")
2944+ (set_attr "predicable" "yes")])
2945+
2946+(define_insn "*stm2_ib_update"
2947+ [(match_parallel 0 "store_multiple_operation"
2948+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2949+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2950+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2951+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2952+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2953+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2954+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2955+ "stm%(ib%)\t%1!, {%3, %4}"
2956+ [(set_attr "type" "store2")
2957+ (set_attr "predicable" "yes")])
2958+
2959+(define_insn "*ldm2_da"
2960+ [(match_parallel 0 "load_multiple_operation"
2961+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2962+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2963+ (const_int -4))))
2964+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2965+ (mem:SI (match_dup 1)))])]
2966+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2967+ "ldm%(da%)\t%1, {%2, %3}"
2968+ [(set_attr "type" "load2")
2969+ (set_attr "predicable" "yes")])
2970+
2971+(define_insn "*ldm2_da_update"
2972+ [(match_parallel 0 "load_multiple_operation"
2973+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2974+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
2975+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2976+ (mem:SI (plus:SI (match_dup 2)
2977+ (const_int -4))))
2978+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2979+ (mem:SI (match_dup 2)))])]
2980+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2981+ "ldm%(da%)\t%1!, {%3, %4}"
2982+ [(set_attr "type" "load2")
2983+ (set_attr "predicable" "yes")])
2984+
2985+(define_insn "*stm2_da"
2986+ [(match_parallel 0 "store_multiple_operation"
2987+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -4)))
2988+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2989+ (set (mem:SI (match_dup 1))
2990+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
2991+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2992+ "stm%(da%)\t%1, {%2, %3}"
2993+ [(set_attr "type" "store2")
2994+ (set_attr "predicable" "yes")])
2995+
2996+(define_insn "*stm2_da_update"
2997+ [(match_parallel 0 "store_multiple_operation"
2998+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2999+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3000+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
3001+ (match_operand:SI 3 "arm_hard_register_operand" ""))
3002+ (set (mem:SI (match_dup 2))
3003+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
3004+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
3005+ "stm%(da%)\t%1!, {%3, %4}"
3006+ [(set_attr "type" "store2")
3007+ (set_attr "predicable" "yes")])
3008+
3009+(define_insn "*ldm2_db"
3010+ [(match_parallel 0 "load_multiple_operation"
3011+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
3012+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
3013+ (const_int -8))))
3014+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
3015+ (mem:SI (plus:SI (match_dup 1)
3016+ (const_int -4))))])]
3017+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
3018+ "ldm%(db%)\t%1, {%2, %3}"
3019+ [(set_attr "type" "load2")
3020+ (set_attr "predicable" "yes")])
3021+
3022+(define_insn "*ldm2_db_update"
3023+ [(match_parallel 0 "load_multiple_operation"
3024+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
3025+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3026+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
3027+ (mem:SI (plus:SI (match_dup 2)
3028+ (const_int -8))))
3029+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
3030+ (mem:SI (plus:SI (match_dup 2)
3031+ (const_int -4))))])]
3032+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
3033+ "ldm%(db%)\t%1!, {%3, %4}"
3034+ [(set_attr "type" "load2")
3035+ (set_attr "predicable" "yes")])
3036+
3037+(define_insn "*stm2_db"
3038+ [(match_parallel 0 "store_multiple_operation"
3039+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -8)))
3040+ (match_operand:SI 2 "arm_hard_register_operand" ""))
3041+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
3042+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
3043+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
3044+ "stm%(db%)\t%1, {%2, %3}"
3045+ [(set_attr "type" "store2")
3046+ (set_attr "predicable" "yes")])
3047+
3048+(define_insn "*stm2_db_update"
3049+ [(match_parallel 0 "store_multiple_operation"
3050+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
3051+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3052+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
3053+ (match_operand:SI 3 "arm_hard_register_operand" ""))
3054+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
3055+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
3056+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
3057+ "stm%(db%)\t%1!, {%3, %4}"
3058+ [(set_attr "type" "store2")
3059+ (set_attr "predicable" "yes")])
3060+
3061+(define_peephole2
3062+ [(set (match_operand:SI 0 "s_register_operand" "")
3063+ (match_operand:SI 2 "memory_operand" ""))
3064+ (set (match_operand:SI 1 "s_register_operand" "")
3065+ (match_operand:SI 3 "memory_operand" ""))]
3066+ ""
3067+ [(const_int 0)]
3068+{
3069+ if (gen_ldm_seq (operands, 2, false))
3070+ DONE;
3071+ else
3072+ FAIL;
3073+})
3074+
3075+(define_peephole2
3076+ [(set (match_operand:SI 0 "s_register_operand" "")
3077+ (match_operand:SI 4 "const_int_operand" ""))
3078+ (set (match_operand:SI 2 "memory_operand" "")
3079+ (match_dup 0))
3080+ (set (match_operand:SI 1 "s_register_operand" "")
3081+ (match_operand:SI 5 "const_int_operand" ""))
3082+ (set (match_operand:SI 3 "memory_operand" "")
3083+ (match_dup 1))]
3084+ ""
3085+ [(const_int 0)]
3086+{
3087+ if (gen_const_stm_seq (operands, 2))
3088+ DONE;
3089+ else
3090+ FAIL;
3091+})
3092+
3093+(define_peephole2
3094+ [(set (match_operand:SI 0 "s_register_operand" "")
3095+ (match_operand:SI 4 "const_int_operand" ""))
3096+ (set (match_operand:SI 1 "s_register_operand" "")
3097+ (match_operand:SI 5 "const_int_operand" ""))
3098+ (set (match_operand:SI 2 "memory_operand" "")
3099+ (match_dup 0))
3100+ (set (match_operand:SI 3 "memory_operand" "")
3101+ (match_dup 1))]
3102+ ""
3103+ [(const_int 0)]
3104+{
3105+ if (gen_const_stm_seq (operands, 2))
3106+ DONE;
3107+ else
3108+ FAIL;
3109+})
3110+
3111+(define_peephole2
3112+ [(set (match_operand:SI 2 "memory_operand" "")
3113+ (match_operand:SI 0 "s_register_operand" ""))
3114+ (set (match_operand:SI 3 "memory_operand" "")
3115+ (match_operand:SI 1 "s_register_operand" ""))]
3116+ ""
3117+ [(const_int 0)]
3118+{
3119+ if (gen_stm_seq (operands, 2))
3120+ DONE;
3121+ else
3122+ FAIL;
3123+})
3124+
3125+(define_peephole2
3126+ [(set (match_operand:SI 0 "s_register_operand" "")
3127+ (match_operand:SI 2 "memory_operand" ""))
3128+ (set (match_operand:SI 1 "s_register_operand" "")
3129+ (match_operand:SI 3 "memory_operand" ""))
3130+ (parallel
3131+ [(set (match_operand:SI 4 "s_register_operand" "")
3132+ (match_operator:SI 5 "commutative_binary_operator"
3133+ [(match_operand:SI 6 "s_register_operand" "")
3134+ (match_operand:SI 7 "s_register_operand" "")]))
3135+ (clobber (reg:CC CC_REGNUM))])]
3136+ "(((operands[6] == operands[0] && operands[7] == operands[1])
3137+ || (operands[7] == operands[0] && operands[6] == operands[1]))
3138+ && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[1]))"
3139+ [(parallel
3140+ [(set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))
3141+ (clobber (reg:CC CC_REGNUM))])]
3142+{
3143+ if (!gen_ldm_seq (operands, 2, true))
3144+ FAIL;
3145+})
3146+
3147+(define_peephole2
3148+ [(set (match_operand:SI 0 "s_register_operand" "")
3149+ (match_operand:SI 2 "memory_operand" ""))
3150+ (set (match_operand:SI 1 "s_register_operand" "")
3151+ (match_operand:SI 3 "memory_operand" ""))
3152+ (set (match_operand:SI 4 "s_register_operand" "")
3153+ (match_operator:SI 5 "commutative_binary_operator"
3154+ [(match_operand:SI 6 "s_register_operand" "")
3155+ (match_operand:SI 7 "s_register_operand" "")]))]
3156+ "(((operands[6] == operands[0] && operands[7] == operands[1])
3157+ || (operands[7] == operands[0] && operands[6] == operands[1]))
3158+ && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[1]))"
3159+ [(set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))]
3160+{
3161+ if (!gen_ldm_seq (operands, 2, true))
3162+ FAIL;
3163+})
3164+
3165Index: gcc-4_5-branch/gcc/config/arm/predicates.md
3166===================================================================
3167--- gcc-4_5-branch.orig/gcc/config/arm/predicates.md
3168+++ gcc-4_5-branch/gcc/config/arm/predicates.md
3169@@ -211,6 +211,11 @@
3170 (and (match_code "ior,xor,and")
3171 (match_test "mode == GET_MODE (op)")))
3172
3173+;; True for commutative operators
3174+(define_special_predicate "commutative_binary_operator"
3175+ (and (match_code "ior,xor,and,plus")
3176+ (match_test "mode == GET_MODE (op)")))
3177+
3178 ;; True for shift operators.
3179 (define_special_predicate "shift_operator"
3180 (and (ior (ior (and (match_code "mult")
3181@@ -334,16 +339,20 @@
3182 (match_code "parallel")
3183 {
3184 HOST_WIDE_INT count = XVECLEN (op, 0);
3185- int dest_regno;
3186+ unsigned dest_regno;
3187 rtx src_addr;
3188 HOST_WIDE_INT i = 1, base = 0;
3189+ HOST_WIDE_INT offset = 0;
3190 rtx elt;
3191+ bool addr_reg_loaded = false;
3192+ bool update = false;
3193
3194 if (low_irq_latency)
3195 return false;
3196
3197 if (count <= 1
3198- || GET_CODE (XVECEXP (op, 0, 0)) != SET)
3199+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
3200+ || !REG_P (SET_DEST (XVECEXP (op, 0, 0))))
3201 return false;
3202
3203 /* Check to see if this might be a write-back. */
3204@@ -351,6 +360,7 @@
3205 {
3206 i++;
3207 base = 1;
3208+ update = true;
3209
3210 /* Now check it more carefully. */
3211 if (GET_CODE (SET_DEST (elt)) != REG
3212@@ -369,6 +379,15 @@
3213
3214 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
3215 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
3216+ if (GET_CODE (src_addr) == PLUS)
3217+ {
3218+ if (GET_CODE (XEXP (src_addr, 1)) != CONST_INT)
3219+ return false;
3220+ offset = INTVAL (XEXP (src_addr, 1));
3221+ src_addr = XEXP (src_addr, 0);
3222+ }
3223+ if (!REG_P (src_addr))
3224+ return false;
3225
3226 for (; i < count; i++)
3227 {
3228@@ -377,16 +396,28 @@
3229 if (GET_CODE (elt) != SET
3230 || GET_CODE (SET_DEST (elt)) != REG
3231 || GET_MODE (SET_DEST (elt)) != SImode
3232- || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
3233+ || REGNO (SET_DEST (elt)) <= dest_regno
3234 || GET_CODE (SET_SRC (elt)) != MEM
3235 || GET_MODE (SET_SRC (elt)) != SImode
3236- || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
3237- || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
3238- || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
3239- || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4)
3240+ || ((GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
3241+ || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
3242+ || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
3243+ || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != offset + (i - base) * 4)
3244+ && (!REG_P (XEXP (SET_SRC (elt), 0))
3245+ || offset + (i - base) * 4 != 0)))
3246 return false;
3247+ dest_regno = REGNO (SET_DEST (elt));
3248+ if (dest_regno == REGNO (src_addr))
3249+ addr_reg_loaded = true;
3250 }
3251-
3252+ /* For Thumb, we only have updating instructions. If the pattern does
3253+ not describe an update, it must be because the address register is
3254+ in the list of loaded registers - on the hardware, this has the effect
3255+ of overriding the update. */
3256+ if (update && addr_reg_loaded)
3257+ return false;
3258+ if (TARGET_THUMB1)
3259+ return update || addr_reg_loaded;
3260 return true;
3261 })
3262
3263@@ -394,9 +425,9 @@
3264 (match_code "parallel")
3265 {
3266 HOST_WIDE_INT count = XVECLEN (op, 0);
3267- int src_regno;
3268+ unsigned src_regno;
3269 rtx dest_addr;
3270- HOST_WIDE_INT i = 1, base = 0;
3271+ HOST_WIDE_INT i = 1, base = 0, offset = 0;
3272 rtx elt;
3273
3274 if (low_irq_latency)
3275@@ -430,6 +461,16 @@
3276 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
3277 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
3278
3279+ if (GET_CODE (dest_addr) == PLUS)
3280+ {
3281+ if (GET_CODE (XEXP (dest_addr, 1)) != CONST_INT)
3282+ return false;
3283+ offset = INTVAL (XEXP (dest_addr, 1));
3284+ dest_addr = XEXP (dest_addr, 0);
3285+ }
3286+ if (!REG_P (dest_addr))
3287+ return false;
3288+
3289 for (; i < count; i++)
3290 {
3291 elt = XVECEXP (op, 0, i);
3292@@ -437,14 +478,17 @@
3293 if (GET_CODE (elt) != SET
3294 || GET_CODE (SET_SRC (elt)) != REG
3295 || GET_MODE (SET_SRC (elt)) != SImode
3296- || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
3297+ || REGNO (SET_SRC (elt)) <= src_regno
3298 || GET_CODE (SET_DEST (elt)) != MEM
3299 || GET_MODE (SET_DEST (elt)) != SImode
3300- || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
3301- || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
3302- || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
3303- || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
3304+ || ((GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
3305+ || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
3306+ || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
3307+ || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != offset + (i - base) * 4)
3308+ && (!REG_P (XEXP (SET_DEST (elt), 0))
3309+ || offset + (i - base) * 4 != 0)))
3310 return false;
3311+ src_regno = REGNO (SET_SRC (elt));
3312 }
3313
3314 return true;
3315Index: gcc-4_5-branch/gcc/config/i386/i386.md
3316===================================================================
3317--- gcc-4_5-branch.orig/gcc/config/i386/i386.md
3318+++ gcc-4_5-branch/gcc/config/i386/i386.md
3319@@ -4934,6 +4934,7 @@
3320 (set (match_operand:SSEMODEI24 2 "register_operand" "")
3321 (fix:SSEMODEI24 (match_dup 0)))]
3322 "TARGET_SHORTEN_X87_SSE
3323+ && !(TARGET_AVOID_VECTOR_DECODE && optimize_insn_for_speed_p ())
3324 && peep2_reg_dead_p (2, operands[0])"
3325 [(set (match_dup 2) (fix:SSEMODEI24 (match_dup 1)))]
3326 "")
3327@@ -20036,15 +20037,14 @@
3328 ;; leal (%edx,%eax,4), %eax
3329
3330 (define_peephole2
3331- [(parallel [(set (match_operand 0 "register_operand" "")
3332+ [(match_scratch:P 5 "r")
3333+ (parallel [(set (match_operand 0 "register_operand" "")
3334 (ashift (match_operand 1 "register_operand" "")
3335 (match_operand 2 "const_int_operand" "")))
3336 (clobber (reg:CC FLAGS_REG))])
3337- (set (match_operand 3 "register_operand")
3338- (match_operand 4 "x86_64_general_operand" ""))
3339- (parallel [(set (match_operand 5 "register_operand" "")
3340- (plus (match_operand 6 "register_operand" "")
3341- (match_operand 7 "register_operand" "")))
3342+ (parallel [(set (match_operand 3 "register_operand" "")
3343+ (plus (match_dup 0)
3344+ (match_operand 4 "x86_64_general_operand" "")))
3345 (clobber (reg:CC FLAGS_REG))])]
3346 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
3347 /* Validate MODE for lea. */
3348@@ -20053,31 +20053,27 @@
3349 || GET_MODE (operands[0]) == HImode))
3350 || GET_MODE (operands[0]) == SImode
3351 || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
3352+ && (rtx_equal_p (operands[0], operands[3])
3353+ || peep2_reg_dead_p (2, operands[0]))
3354 /* We reorder load and the shift. */
3355- && !rtx_equal_p (operands[1], operands[3])
3356- && !reg_overlap_mentioned_p (operands[0], operands[4])
3357- /* Last PLUS must consist of operand 0 and 3. */
3358- && !rtx_equal_p (operands[0], operands[3])
3359- && (rtx_equal_p (operands[3], operands[6])
3360- || rtx_equal_p (operands[3], operands[7]))
3361- && (rtx_equal_p (operands[0], operands[6])
3362- || rtx_equal_p (operands[0], operands[7]))
3363- /* The intermediate operand 0 must die or be same as output. */
3364- && (rtx_equal_p (operands[0], operands[5])
3365- || peep2_reg_dead_p (3, operands[0]))"
3366- [(set (match_dup 3) (match_dup 4))
3367+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
3368+ [(set (match_dup 5) (match_dup 4))
3369 (set (match_dup 0) (match_dup 1))]
3370 {
3371- enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
3372+ enum machine_mode mode = GET_MODE (operands[1]) == DImode ? DImode : SImode;
3373 int scale = 1 << INTVAL (operands[2]);
3374 rtx index = gen_lowpart (Pmode, operands[1]);
3375- rtx base = gen_lowpart (Pmode, operands[3]);
3376- rtx dest = gen_lowpart (mode, operands[5]);
3377+ rtx base = gen_lowpart (Pmode, operands[5]);
3378+ rtx dest = gen_lowpart (mode, operands[3]);
3379
3380 operands[1] = gen_rtx_PLUS (Pmode, base,
3381 gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
3382+ operands[5] = base;
3383 if (mode != Pmode)
3384- operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
3385+ {
3386+ operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
3387+ operands[5] = gen_rtx_SUBREG (mode, operands[5], 0);
3388+ }
3389 operands[0] = dest;
3390 })
3391
3392Index: gcc-4_5-branch/gcc/df-problems.c
3393===================================================================
3394--- gcc-4_5-branch.orig/gcc/df-problems.c
3395+++ gcc-4_5-branch/gcc/df-problems.c
3396@@ -3748,9 +3748,22 @@ df_simulate_find_defs (rtx insn, bitmap
3397 for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
3398 {
3399 df_ref def = *def_rec;
3400- /* If the def is to only part of the reg, it does
3401- not kill the other defs that reach here. */
3402- if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
3403+ bitmap_set_bit (defs, DF_REF_REGNO (def));
3404+ }
3405+}
3406+
3407+/* Find the set of real DEFs, which are not clobbers, for INSN. */
3408+
3409+void
3410+df_simulate_find_noclobber_defs (rtx insn, bitmap defs)
3411+{
3412+ df_ref *def_rec;
3413+ unsigned int uid = INSN_UID (insn);
3414+
3415+ for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
3416+ {
3417+ df_ref def = *def_rec;
3418+ if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
3419 bitmap_set_bit (defs, DF_REF_REGNO (def));
3420 }
3421 }
3422@@ -3921,7 +3934,7 @@ df_simulate_initialize_forwards (basic_b
3423 {
3424 df_ref def = *def_rec;
3425 if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
3426- bitmap_clear_bit (live, DF_REF_REGNO (def));
3427+ bitmap_set_bit (live, DF_REF_REGNO (def));
3428 }
3429 }
3430
3431@@ -3942,7 +3955,7 @@ df_simulate_one_insn_forwards (basic_blo
3432 while here the scan is performed forwards! So, first assume that the
3433 def is live, and if this is not true REG_UNUSED notes will rectify the
3434 situation. */
3435- df_simulate_find_defs (insn, live);
3436+ df_simulate_find_noclobber_defs (insn, live);
3437
3438 /* Clear all of the registers that go dead. */
3439 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
3440Index: gcc-4_5-branch/gcc/df.h
3441===================================================================
3442--- gcc-4_5-branch.orig/gcc/df.h
3443+++ gcc-4_5-branch/gcc/df.h
3444@@ -978,6 +978,7 @@ extern void df_note_add_problem (void);
3445 extern void df_md_add_problem (void);
3446 extern void df_md_simulate_artificial_defs_at_top (basic_block, bitmap);
3447 extern void df_md_simulate_one_insn (basic_block, rtx, bitmap);
3448+extern void df_simulate_find_noclobber_defs (rtx, bitmap);
3449 extern void df_simulate_find_defs (rtx, bitmap);
3450 extern void df_simulate_defs (rtx, bitmap);
3451 extern void df_simulate_uses (rtx, bitmap);
3452Index: gcc-4_5-branch/gcc/fwprop.c
3453===================================================================
3454--- gcc-4_5-branch.orig/gcc/fwprop.c
3455+++ gcc-4_5-branch/gcc/fwprop.c
3456@@ -228,7 +228,10 @@ single_def_use_enter_block (struct dom_w
3457
3458 process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP);
3459 process_defs (df_get_artificial_defs (bb_index), DF_REF_AT_TOP);
3460- df_simulate_initialize_forwards (bb, local_lr);
3461+
3462+ /* We don't call df_simulate_initialize_forwards, as it may overestimate
3463+ the live registers if there are unused artificial defs. We prefer
3464+ liveness to be underestimated. */
3465
3466 FOR_BB_INSNS (bb, insn)
3467 if (INSN_P (insn))
3468Index: gcc-4_5-branch/gcc/genoutput.c
3469===================================================================
3470--- gcc-4_5-branch.orig/gcc/genoutput.c
3471+++ gcc-4_5-branch/gcc/genoutput.c
3472@@ -266,6 +266,8 @@ output_operand_data (void)
3473
3474 printf (" %d,\n", d->strict_low);
3475
3476+ printf (" %d,\n", d->constraint == NULL ? 1 : 0);
3477+
3478 printf (" %d\n", d->eliminable);
3479
3480 printf(" },\n");
3481Index: gcc-4_5-branch/gcc/genrecog.c
3482===================================================================
3483--- gcc-4_5-branch.orig/gcc/genrecog.c
3484+++ gcc-4_5-branch/gcc/genrecog.c
3485@@ -1782,20 +1782,11 @@ change_state (const char *oldpos, const
3486 int odepth = strlen (oldpos);
3487 int ndepth = strlen (newpos);
3488 int depth;
3489- int old_has_insn, new_has_insn;
3490
3491 /* Pop up as many levels as necessary. */
3492 for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
3493 continue;
3494
3495- /* Hunt for the last [A-Z] in both strings. */
3496- for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
3497- if (ISUPPER (oldpos[old_has_insn]))
3498- break;
3499- for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
3500- if (ISUPPER (newpos[new_has_insn]))
3501- break;
3502-
3503 /* Go down to desired level. */
3504 while (depth < ndepth)
3505 {
3506Index: gcc-4_5-branch/gcc/ifcvt.c
3507===================================================================
3508--- gcc-4_5-branch.orig/gcc/ifcvt.c
3509+++ gcc-4_5-branch/gcc/ifcvt.c
3510@@ -4011,6 +4011,7 @@ dead_or_predicable (basic_block test_bb,
3511 basic_block new_dest = dest_edge->dest;
3512 rtx head, end, jump, earliest = NULL_RTX, old_dest;
3513 bitmap merge_set = NULL;
3514+ bitmap merge_set_noclobber = NULL;
3515 /* Number of pending changes. */
3516 int n_validated_changes = 0;
3517 rtx new_dest_label;
3518@@ -4169,6 +4170,7 @@ dead_or_predicable (basic_block test_bb,
3519 end of the block. */
3520
3521 merge_set = BITMAP_ALLOC (&reg_obstack);
3522+ merge_set_noclobber = BITMAP_ALLOC (&reg_obstack);
3523
3524 /* If we allocated new pseudos (e.g. in the conditional move
3525 expander called from noce_emit_cmove), we must resize the
3526@@ -4187,6 +4189,7 @@ dead_or_predicable (basic_block test_bb,
3527 df_ref def = *def_rec;
3528 bitmap_set_bit (merge_set, DF_REF_REGNO (def));
3529 }
3530+ df_simulate_find_noclobber_defs (insn, merge_set_noclobber);
3531 }
3532 }
3533
3534@@ -4197,7 +4200,7 @@ dead_or_predicable (basic_block test_bb,
3535 unsigned i;
3536 bitmap_iterator bi;
3537
3538- EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
3539+ EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi)
3540 {
3541 if (i < FIRST_PSEUDO_REGISTER
3542 && ! fixed_regs[i]
3543@@ -4233,7 +4236,7 @@ dead_or_predicable (basic_block test_bb,
3544 TEST_SET & DF_LIVE_IN (merge_bb)
3545 are empty. */
3546
3547- if (bitmap_intersect_p (merge_set, test_set)
3548+ if (bitmap_intersect_p (merge_set_noclobber, test_set)
3549 || bitmap_intersect_p (merge_set, test_live)
3550 || bitmap_intersect_p (test_set, df_get_live_in (merge_bb)))
3551 intersect = true;
3552@@ -4320,6 +4323,7 @@ dead_or_predicable (basic_block test_bb,
3553 remove_reg_equal_equiv_notes_for_regno (i);
3554
3555 BITMAP_FREE (merge_set);
3556+ BITMAP_FREE (merge_set_noclobber);
3557 }
3558
3559 reorder_insns (head, end, PREV_INSN (earliest));
3560@@ -4340,7 +4344,10 @@ dead_or_predicable (basic_block test_bb,
3561 cancel_changes (0);
3562 fail:
3563 if (merge_set)
3564- BITMAP_FREE (merge_set);
3565+ {
3566+ BITMAP_FREE (merge_set);
3567+ BITMAP_FREE (merge_set_noclobber);
3568+ }
3569 return FALSE;
3570 }
3571
3572Index: gcc-4_5-branch/gcc/recog.c
3573===================================================================
3574--- gcc-4_5-branch.orig/gcc/recog.c
3575+++ gcc-4_5-branch/gcc/recog.c
3576@@ -2082,6 +2082,7 @@ extract_insn (rtx insn)
3577 recog_data.operand_loc,
3578 recog_data.constraints,
3579 recog_data.operand_mode, NULL);
3580+ memset (recog_data.is_operator, 0, sizeof recog_data.is_operator);
3581 if (noperands > 0)
3582 {
3583 const char *p = recog_data.constraints[0];
3584@@ -2111,6 +2112,7 @@ extract_insn (rtx insn)
3585 for (i = 0; i < noperands; i++)
3586 {
3587 recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
3588+ recog_data.is_operator[i] = insn_data[icode].operand[i].is_operator;
3589 recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
3590 /* VOIDmode match_operands gets mode from their real operand. */
3591 if (recog_data.operand_mode[i] == VOIDmode)
3592@@ -2909,6 +2911,10 @@ struct peep2_insn_data
3593
3594 static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
3595 static int peep2_current;
3596+
3597+static bool peep2_do_rebuild_jump_labels;
3598+static bool peep2_do_cleanup_cfg;
3599+
3600 /* The number of instructions available to match a peep2. */
3601 int peep2_current_count;
3602
3603@@ -2917,6 +2923,16 @@ int peep2_current_count;
3604 DF_LIVE_OUT for the block. */
3605 #define PEEP2_EOB pc_rtx
3606
3607+/* Wrap N to fit into the peep2_insn_data buffer. */
3608+
3609+static int
3610+peep2_buf_position (int n)
3611+{
3612+ if (n >= MAX_INSNS_PER_PEEP2 + 1)
3613+ n -= MAX_INSNS_PER_PEEP2 + 1;
3614+ return n;
3615+}
3616+
3617 /* Return the Nth non-note insn after `current', or return NULL_RTX if it
3618 does not exist. Used by the recognizer to find the next insn to match
3619 in a multi-insn pattern. */
3620@@ -2926,9 +2942,7 @@ peep2_next_insn (int n)
3621 {
3622 gcc_assert (n <= peep2_current_count);
3623
3624- n += peep2_current;
3625- if (n >= MAX_INSNS_PER_PEEP2 + 1)
3626- n -= MAX_INSNS_PER_PEEP2 + 1;
3627+ n = peep2_buf_position (peep2_current + n);
3628
3629 return peep2_insn_data[n].insn;
3630 }
3631@@ -2941,9 +2955,7 @@ peep2_regno_dead_p (int ofs, int regno)
3632 {
3633 gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3634
3635- ofs += peep2_current;
3636- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
3637- ofs -= MAX_INSNS_PER_PEEP2 + 1;
3638+ ofs = peep2_buf_position (peep2_current + ofs);
3639
3640 gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3641
3642@@ -2959,9 +2971,7 @@ peep2_reg_dead_p (int ofs, rtx reg)
3643
3644 gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3645
3646- ofs += peep2_current;
3647- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
3648- ofs -= MAX_INSNS_PER_PEEP2 + 1;
3649+ ofs = peep2_buf_position (peep2_current + ofs);
3650
3651 gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3652
3653@@ -2996,12 +3006,8 @@ peep2_find_free_register (int from, int
3654 gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
3655 gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
3656
3657- from += peep2_current;
3658- if (from >= MAX_INSNS_PER_PEEP2 + 1)
3659- from -= MAX_INSNS_PER_PEEP2 + 1;
3660- to += peep2_current;
3661- if (to >= MAX_INSNS_PER_PEEP2 + 1)
3662- to -= MAX_INSNS_PER_PEEP2 + 1;
3663+ from = peep2_buf_position (peep2_current + from);
3664+ to = peep2_buf_position (peep2_current + to);
3665
3666 gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3667 REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
3668@@ -3010,8 +3016,7 @@ peep2_find_free_register (int from, int
3669 {
3670 HARD_REG_SET this_live;
3671
3672- if (++from >= MAX_INSNS_PER_PEEP2 + 1)
3673- from = 0;
3674+ from = peep2_buf_position (from + 1);
3675 gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3676 REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
3677 IOR_HARD_REG_SET (live, this_live);
3678@@ -3104,19 +3109,234 @@ peep2_reinit_state (regset live)
3679 COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
3680 }
3681
3682+/* While scanning basic block BB, we found a match of length MATCH_LEN,
3683+ starting at INSN. Perform the replacement, removing the old insns and
3684+ replacing them with ATTEMPT. Returns the last insn emitted. */
3685+
3686+static rtx
3687+peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt)
3688+{
3689+ int i;
3690+ rtx last, note, before_try, x;
3691+ bool was_call = false;
3692+
3693+ /* If we are splitting a CALL_INSN, look for the CALL_INSN
3694+ in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
3695+ cfg-related call notes. */
3696+ for (i = 0; i <= match_len; ++i)
3697+ {
3698+ int j;
3699+ rtx old_insn, new_insn, note;
3700+
3701+ j = peep2_buf_position (peep2_current + i);
3702+ old_insn = peep2_insn_data[j].insn;
3703+ if (!CALL_P (old_insn))
3704+ continue;
3705+ was_call = true;
3706+
3707+ new_insn = attempt;
3708+ while (new_insn != NULL_RTX)
3709+ {
3710+ if (CALL_P (new_insn))
3711+ break;
3712+ new_insn = NEXT_INSN (new_insn);
3713+ }
3714+
3715+ gcc_assert (new_insn != NULL_RTX);
3716+
3717+ CALL_INSN_FUNCTION_USAGE (new_insn)
3718+ = CALL_INSN_FUNCTION_USAGE (old_insn);
3719+
3720+ for (note = REG_NOTES (old_insn);
3721+ note;
3722+ note = XEXP (note, 1))
3723+ switch (REG_NOTE_KIND (note))
3724+ {
3725+ case REG_NORETURN:
3726+ case REG_SETJMP:
3727+ add_reg_note (new_insn, REG_NOTE_KIND (note),
3728+ XEXP (note, 0));
3729+ break;
3730+ default:
3731+ /* Discard all other reg notes. */
3732+ break;
3733+ }
3734+
3735+ /* Croak if there is another call in the sequence. */
3736+ while (++i <= match_len)
3737+ {
3738+ j = peep2_buf_position (peep2_current + i);
3739+ old_insn = peep2_insn_data[j].insn;
3740+ gcc_assert (!CALL_P (old_insn));
3741+ }
3742+ break;
3743+ }
3744+
3745+ i = peep2_buf_position (peep2_current + match_len);
3746+
3747+ note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX);
3748+
3749+ /* Replace the old sequence with the new. */
3750+ last = emit_insn_after_setloc (attempt,
3751+ peep2_insn_data[i].insn,
3752+ INSN_LOCATOR (peep2_insn_data[i].insn));
3753+ before_try = PREV_INSN (insn);
3754+ delete_insn_chain (insn, peep2_insn_data[i].insn, false);
3755+
3756+ /* Re-insert the EH_REGION notes. */
3757+ if (note || (was_call && nonlocal_goto_handler_labels))
3758+ {
3759+ edge eh_edge;
3760+ edge_iterator ei;
3761+
3762+ FOR_EACH_EDGE (eh_edge, ei, bb->succs)
3763+ if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
3764+ break;
3765+
3766+ if (note)
3767+ copy_reg_eh_region_note_backward (note, last, before_try);
3768+
3769+ if (eh_edge)
3770+ for (x = last; x != before_try; x = PREV_INSN (x))
3771+ if (x != BB_END (bb)
3772+ && (can_throw_internal (x)
3773+ || can_nonlocal_goto (x)))
3774+ {
3775+ edge nfte, nehe;
3776+ int flags;
3777+
3778+ nfte = split_block (bb, x);
3779+ flags = (eh_edge->flags
3780+ & (EDGE_EH | EDGE_ABNORMAL));
3781+ if (CALL_P (x))
3782+ flags |= EDGE_ABNORMAL_CALL;
3783+ nehe = make_edge (nfte->src, eh_edge->dest,
3784+ flags);
3785+
3786+ nehe->probability = eh_edge->probability;
3787+ nfte->probability
3788+ = REG_BR_PROB_BASE - nehe->probability;
3789+
3790+ peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
3791+ bb = nfte->src;
3792+ eh_edge = nehe;
3793+ }
3794+
3795+ /* Converting possibly trapping insn to non-trapping is
3796+ possible. Zap dummy outgoing edges. */
3797+ peep2_do_cleanup_cfg |= purge_dead_edges (bb);
3798+ }
3799+
3800+ /* If we generated a jump instruction, it won't have
3801+ JUMP_LABEL set. Recompute after we're done. */
3802+ for (x = last; x != before_try; x = PREV_INSN (x))
3803+ if (JUMP_P (x))
3804+ {
3805+ peep2_do_rebuild_jump_labels = true;
3806+ break;
3807+ }
3808+
3809+ return last;
3810+}
3811+
3812+/* After performing a replacement in basic block BB, fix up the life
3813+ information in our buffer. LAST is the last of the insns that we
3814+ emitted as a replacement. PREV is the insn before the start of
3815+ the replacement. MATCH_LEN is the number of instructions that were
3816+ matched, and which now need to be replaced in the buffer. */
3817+
3818+static void
3819+peep2_update_life (basic_block bb, int match_len, rtx last, rtx prev)
3820+{
3821+ int i = peep2_buf_position (peep2_current + match_len + 1);
3822+ rtx x;
3823+ regset_head live;
3824+
3825+ INIT_REG_SET (&live);
3826+ COPY_REG_SET (&live, peep2_insn_data[i].live_before);
3827+
3828+ gcc_assert (peep2_current_count >= match_len + 1);
3829+ peep2_current_count -= match_len + 1;
3830+
3831+ x = last;
3832+ do
3833+ {
3834+ if (INSN_P (x))
3835+ {
3836+ df_insn_rescan (x);
3837+ if (peep2_current_count < MAX_INSNS_PER_PEEP2)
3838+ {
3839+ peep2_current_count++;
3840+ if (--i < 0)
3841+ i = MAX_INSNS_PER_PEEP2;
3842+ peep2_insn_data[i].insn = x;
3843+ df_simulate_one_insn_backwards (bb, x, &live);
3844+ COPY_REG_SET (peep2_insn_data[i].live_before, &live);
3845+ }
3846+ }
3847+ x = PREV_INSN (x);
3848+ }
3849+ while (x != prev);
3850+ CLEAR_REG_SET (&live);
3851+
3852+ peep2_current = i;
3853+}
3854+
3855+/* Add INSN, which is in BB, at the end of the peep2 insn buffer if possible.
3856+ Return true if we added it, false otherwise. The caller will try to match
3857+ peepholes against the buffer if we return false; otherwise it will try to
3858+ add more instructions to the buffer. */
3859+
3860+static bool
3861+peep2_fill_buffer (basic_block bb, rtx insn, regset live)
3862+{
3863+ int pos;
3864+
3865+ /* Once we have filled the maximum number of insns the buffer can hold,
3866+ allow the caller to match the insns against peepholes. We wait until
3867+ the buffer is full in case the target has similar peepholes of different
3868+ length; we always want to match the longest if possible. */
3869+ if (peep2_current_count == MAX_INSNS_PER_PEEP2)
3870+ return false;
3871+
3872+ /* If an insn has RTX_FRAME_RELATED_P set, peephole substitution would lose
3873+ the REG_FRAME_RELATED_EXPR that is attached. */
3874+ if (RTX_FRAME_RELATED_P (insn))
3875+ {
3876+ /* Let the buffer drain first. */
3877+ if (peep2_current_count > 0)
3878+ return false;
3879+ /* Step over the insn then return true without adding the insn
3880+ to the buffer; this will cause us to process the next
3881+ insn. */
3882+ df_simulate_one_insn_forwards (bb, insn, live);
3883+ return true;
3884+ }
3885+
3886+ pos = peep2_buf_position (peep2_current + peep2_current_count);
3887+ peep2_insn_data[pos].insn = insn;
3888+ COPY_REG_SET (peep2_insn_data[pos].live_before, live);
3889+ peep2_current_count++;
3890+
3891+ df_simulate_one_insn_forwards (bb, insn, live);
3892+ return true;
3893+}
3894+
3895 /* Perform the peephole2 optimization pass. */
3896
3897 static void
3898 peephole2_optimize (void)
3899 {
3900- rtx insn, prev;
3901+ rtx insn;
3902 bitmap live;
3903 int i;
3904 basic_block bb;
3905- bool do_cleanup_cfg = false;
3906- bool do_rebuild_jump_labels = false;
3907+
3908+ peep2_do_cleanup_cfg = false;
3909+ peep2_do_rebuild_jump_labels = false;
3910
3911 df_set_flags (DF_LR_RUN_DCE);
3912+ df_note_add_problem ();
3913 df_analyze ();
3914
3915 /* Initialize the regsets we're going to use. */
3916@@ -3126,214 +3346,59 @@ peephole2_optimize (void)
3917
3918 FOR_EACH_BB_REVERSE (bb)
3919 {
3920+ bool past_end = false;
3921+ int pos;
3922+
3923 rtl_profile_for_bb (bb);
3924
3925 /* Start up propagation. */
3926- bitmap_copy (live, DF_LR_OUT (bb));
3927- df_simulate_initialize_backwards (bb, live);
3928+ bitmap_copy (live, DF_LR_IN (bb));
3929+ df_simulate_initialize_forwards (bb, live);
3930 peep2_reinit_state (live);
3931
3932- for (insn = BB_END (bb); ; insn = prev)
3933+ insn = BB_HEAD (bb);
3934+ for (;;)
3935 {
3936- prev = PREV_INSN (insn);
3937- if (NONDEBUG_INSN_P (insn))
3938- {
3939- rtx attempt, before_try, x;
3940- int match_len;
3941- rtx note;
3942- bool was_call = false;
3943-
3944- /* Record this insn. */
3945- if (--peep2_current < 0)
3946- peep2_current = MAX_INSNS_PER_PEEP2;
3947- if (peep2_current_count < MAX_INSNS_PER_PEEP2
3948- && peep2_insn_data[peep2_current].insn == NULL_RTX)
3949- peep2_current_count++;
3950- peep2_insn_data[peep2_current].insn = insn;
3951- df_simulate_one_insn_backwards (bb, insn, live);
3952- COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
3953-
3954- if (RTX_FRAME_RELATED_P (insn))
3955- {
3956- /* If an insn has RTX_FRAME_RELATED_P set, peephole
3957- substitution would lose the
3958- REG_FRAME_RELATED_EXPR that is attached. */
3959- peep2_reinit_state (live);
3960- attempt = NULL;
3961- }
3962- else
3963- /* Match the peephole. */
3964- attempt = peephole2_insns (PATTERN (insn), insn, &match_len);
3965-
3966- if (attempt != NULL)
3967- {
3968- /* If we are splitting a CALL_INSN, look for the CALL_INSN
3969- in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
3970- cfg-related call notes. */
3971- for (i = 0; i <= match_len; ++i)
3972- {
3973- int j;
3974- rtx old_insn, new_insn, note;
3975+ rtx attempt, head;
3976+ int match_len;
3977
3978- j = i + peep2_current;
3979- if (j >= MAX_INSNS_PER_PEEP2 + 1)
3980- j -= MAX_INSNS_PER_PEEP2 + 1;
3981- old_insn = peep2_insn_data[j].insn;
3982- if (!CALL_P (old_insn))
3983- continue;
3984- was_call = true;
3985-
3986- new_insn = attempt;
3987- while (new_insn != NULL_RTX)
3988- {
3989- if (CALL_P (new_insn))
3990- break;
3991- new_insn = NEXT_INSN (new_insn);
3992- }
3993-
3994- gcc_assert (new_insn != NULL_RTX);
3995-
3996- CALL_INSN_FUNCTION_USAGE (new_insn)
3997- = CALL_INSN_FUNCTION_USAGE (old_insn);
3998-
3999- for (note = REG_NOTES (old_insn);
4000- note;
4001- note = XEXP (note, 1))
4002- switch (REG_NOTE_KIND (note))
4003- {
4004- case REG_NORETURN:
4005- case REG_SETJMP:
4006- add_reg_note (new_insn, REG_NOTE_KIND (note),
4007- XEXP (note, 0));
4008- break;
4009- default:
4010- /* Discard all other reg notes. */
4011- break;
4012- }
4013-
4014- /* Croak if there is another call in the sequence. */
4015- while (++i <= match_len)
4016- {
4017- j = i + peep2_current;
4018- if (j >= MAX_INSNS_PER_PEEP2 + 1)
4019- j -= MAX_INSNS_PER_PEEP2 + 1;
4020- old_insn = peep2_insn_data[j].insn;
4021- gcc_assert (!CALL_P (old_insn));
4022- }
4023- break;
4024- }
4025-
4026- i = match_len + peep2_current;
4027- if (i >= MAX_INSNS_PER_PEEP2 + 1)
4028- i -= MAX_INSNS_PER_PEEP2 + 1;
4029-
4030- note = find_reg_note (peep2_insn_data[i].insn,
4031- REG_EH_REGION, NULL_RTX);
4032-
4033- /* Replace the old sequence with the new. */
4034- attempt = emit_insn_after_setloc (attempt,
4035- peep2_insn_data[i].insn,
4036- INSN_LOCATOR (peep2_insn_data[i].insn));
4037- before_try = PREV_INSN (insn);
4038- delete_insn_chain (insn, peep2_insn_data[i].insn, false);
4039-
4040- /* Re-insert the EH_REGION notes. */
4041- if (note || (was_call && nonlocal_goto_handler_labels))
4042- {
4043- edge eh_edge;
4044- edge_iterator ei;
4045-
4046- FOR_EACH_EDGE (eh_edge, ei, bb->succs)
4047- if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
4048- break;
4049-
4050- if (note)
4051- copy_reg_eh_region_note_backward (note, attempt,
4052- before_try);
4053-
4054- if (eh_edge)
4055- for (x = attempt ; x != before_try ; x = PREV_INSN (x))
4056- if (x != BB_END (bb)
4057- && (can_throw_internal (x)
4058- || can_nonlocal_goto (x)))
4059- {
4060- edge nfte, nehe;
4061- int flags;
4062-
4063- nfte = split_block (bb, x);
4064- flags = (eh_edge->flags
4065- & (EDGE_EH | EDGE_ABNORMAL));
4066- if (CALL_P (x))
4067- flags |= EDGE_ABNORMAL_CALL;
4068- nehe = make_edge (nfte->src, eh_edge->dest,
4069- flags);
4070-
4071- nehe->probability = eh_edge->probability;
4072- nfte->probability
4073- = REG_BR_PROB_BASE - nehe->probability;
4074-
4075- do_cleanup_cfg |= purge_dead_edges (nfte->dest);
4076- bb = nfte->src;
4077- eh_edge = nehe;
4078- }
4079-
4080- /* Converting possibly trapping insn to non-trapping is
4081- possible. Zap dummy outgoing edges. */
4082- do_cleanup_cfg |= purge_dead_edges (bb);
4083- }
4084+ if (!past_end && !NONDEBUG_INSN_P (insn))
4085+ {
4086+ next_insn:
4087+ insn = NEXT_INSN (insn);
4088+ if (insn == NEXT_INSN (BB_END (bb)))
4089+ past_end = true;
4090+ continue;
4091+ }
4092+ if (!past_end && peep2_fill_buffer (bb, insn, live))
4093+ goto next_insn;
4094
4095- if (targetm.have_conditional_execution ())
4096- {
4097- for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
4098- peep2_insn_data[i].insn = NULL_RTX;
4099- peep2_insn_data[peep2_current].insn = PEEP2_EOB;
4100- peep2_current_count = 0;
4101- }
4102- else
4103- {
4104- /* Back up lifetime information past the end of the
4105- newly created sequence. */
4106- if (++i >= MAX_INSNS_PER_PEEP2 + 1)
4107- i = 0;
4108- bitmap_copy (live, peep2_insn_data[i].live_before);
4109-
4110- /* Update life information for the new sequence. */
4111- x = attempt;
4112- do
4113- {
4114- if (INSN_P (x))
4115- {
4116- if (--i < 0)
4117- i = MAX_INSNS_PER_PEEP2;
4118- if (peep2_current_count < MAX_INSNS_PER_PEEP2
4119- && peep2_insn_data[i].insn == NULL_RTX)
4120- peep2_current_count++;
4121- peep2_insn_data[i].insn = x;
4122- df_insn_rescan (x);
4123- df_simulate_one_insn_backwards (bb, x, live);
4124- bitmap_copy (peep2_insn_data[i].live_before,
4125- live);
4126- }
4127- x = PREV_INSN (x);
4128- }
4129- while (x != prev);
4130+ /* If we did not fill an empty buffer, it signals the end of the
4131+ block. */
4132+ if (peep2_current_count == 0)
4133+ break;
4134
4135- peep2_current = i;
4136- }
4137+ /* The buffer filled to the current maximum, so try to match. */
4138
4139- /* If we generated a jump instruction, it won't have
4140- JUMP_LABEL set. Recompute after we're done. */
4141- for (x = attempt; x != before_try; x = PREV_INSN (x))
4142- if (JUMP_P (x))
4143- {
4144- do_rebuild_jump_labels = true;
4145- break;
4146- }
4147- }
4148+ pos = peep2_buf_position (peep2_current + peep2_current_count);
4149+ peep2_insn_data[pos].insn = PEEP2_EOB;
4150+ COPY_REG_SET (peep2_insn_data[pos].live_before, live);
4151+
4152+ /* Match the peephole. */
4153+ head = peep2_insn_data[peep2_current].insn;
4154+ attempt = peephole2_insns (PATTERN (head), head, &match_len);
4155+ if (attempt != NULL)
4156+ {
4157+ rtx last;
4158+ last = peep2_attempt (bb, head, match_len, attempt);
4159+ peep2_update_life (bb, match_len, last, PREV_INSN (attempt));
4160+ }
4161+ else
4162+ {
4163+ /* If no match, advance the buffer by one insn. */
4164+ peep2_current = peep2_buf_position (peep2_current + 1);
4165+ peep2_current_count--;
4166 }
4167-
4168- if (insn == BB_HEAD (bb))
4169- break;
4170 }
4171 }
4172
4173@@ -3341,7 +3406,7 @@ peephole2_optimize (void)
4174 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
4175 BITMAP_FREE (peep2_insn_data[i].live_before);
4176 BITMAP_FREE (live);
4177- if (do_rebuild_jump_labels)
4178+ if (peep2_do_rebuild_jump_labels)
4179 rebuild_jump_labels (get_insns ());
4180 }
4181 #endif /* HAVE_peephole2 */
4182Index: gcc-4_5-branch/gcc/recog.h
4183===================================================================
4184--- gcc-4_5-branch.orig/gcc/recog.h
4185+++ gcc-4_5-branch/gcc/recog.h
4186@@ -194,6 +194,9 @@ struct recog_data
4187 /* Gives the constraint string for operand N. */
4188 const char *constraints[MAX_RECOG_OPERANDS];
4189
4190+ /* Nonzero if operand N is a match_operator or a match_parallel. */
4191+ char is_operator[MAX_RECOG_OPERANDS];
4192+
4193 /* Gives the mode of operand N. */
4194 enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
4195
4196@@ -260,6 +263,8 @@ struct insn_operand_data
4197
4198 const char strict_low;
4199
4200+ const char is_operator;
4201+
4202 const char eliminable;
4203 };
4204
4205Index: gcc-4_5-branch/gcc/reload.c
4206===================================================================
4207--- gcc-4_5-branch.orig/gcc/reload.c
4208+++ gcc-4_5-branch/gcc/reload.c
4209@@ -3631,7 +3631,7 @@ find_reloads (rtx insn, int replace, int
4210 || modified[j] != RELOAD_WRITE)
4211 && j != i
4212 /* Ignore things like match_operator operands. */
4213- && *recog_data.constraints[j] != 0
4214+ && !recog_data.is_operator[j]
4215 /* Don't count an input operand that is constrained to match
4216 the early clobber operand. */
4217 && ! (this_alternative_matches[j] == i