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