aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch4075
1 files changed, 0 insertions, 4075 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch
deleted file mode 100644
index 337b055805..0000000000
--- a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch
+++ /dev/null
@@ -1,4075 +0,0 @@
-2011-02-08 Andrew Stubbs <ams@codesourcery.com>
-
- Backport from FSF mainline:
-
- 2010-06-30 H.J. Lu <hongjiu.lu@intel.com>
-
- PR target/44721
- * config/i386/i386.md (peephole2 for arithmetic ops with memory):
- Fix last commit.
-
- 2010-06-30 Richard Guenther <rguenther@suse.de>
-
- PR target/44722
- * config/i386/i386.md (peephole2 for fix:SSEMODEI24): Guard
- against oscillation with reverse peephole2.
-
- 2010-07-01 Bernd Schmidt <bernds@codesourcery.com>
-
- PR target/44727
- * config/i386/i386.md (peephole2 for arithmetic ops with memory):
- Make sure operand 0 dies.
-
-2010-12-03 Yao Qi <yao@codesourcery.com>
-
- * config/arm/arm-ldmstm.ml: Rewrite ldm/stm RTL patterns to fix
- regressions.
- * config/arm/ldmstm.md: Regenreate.
-
-2010-12-03 Yao Qi <yao@codesourcery.com>
-
- Backport from FSF mainline:
-
- 2010-08-02 Bernd Schmidt <bernds@codesourcery.com>
-
- PR target/40457
- * config/arm/arm.h (arm_regs_in_sequence): Declare.
- * config/arm/arm-protos.h (emit_ldm_seq, emit_stm_seq,
- load_multiple_sequence, store_multiple_sequence): Delete
- declarations.
- (arm_gen_load_multiple, arm_gen_store_multiple): Adjust
- declarations.
- * config/arm/ldmstm.md: New file.
- * config/arm/arm.c (arm_regs_in_sequence): New array.
- (load_multiple_sequence): Now static. New args SAVED_ORDER,
- CHECK_REGS. All callers changed.
- If SAVED_ORDER is nonnull, copy the computed order into it.
- If CHECK_REGS is false, don't sort REGS. Handle Thumb mode.
- (store_multiple_sequence): Now static. New args NOPS_TOTAL,
- SAVED_ORDER, REG_RTXS and CHECK_REGS. All callers changed.
- If SAVED_ORDER is nonnull, copy the computed order into it.
- If CHECK_REGS is false, don't sort REGS. Set up REG_RTXS just
- like REGS. Handle Thumb mode.
- (arm_gen_load_multiple_1): New function, broken out of
- arm_gen_load_multiple.
- (arm_gen_store_multiple_1): New function, broken out of
- arm_gen_store_multiple.
- (arm_gen_multiple_op): New function, with code from
- arm_gen_load_multiple and arm_gen_store_multiple moved here.
- (arm_gen_load_multiple, arm_gen_store_multiple): Now just
- wrappers around arm_gen_multiple_op. Remove argument UP, all callers
- changed.
- (gen_ldm_seq, gen_stm_seq, gen_const_stm_seq): New functions.
- * config/arm/predicates.md (commutative_binary_operator): New.
- (load_multiple_operation, store_multiple_operation): Handle more
- variants of these patterns with different starting offsets. Handle
- Thumb-1.
- * config/arm/arm.md: Include "ldmstm.md".
- (ldmsi_postinc4, ldmsi_postinc4_thumb1, ldmsi_postinc3, ldmsi_postinc2,
- ldmsi4, ldmsi3, ldmsi2, stmsi_postinc4, stmsi_postinc4_thumb1,
- stmsi_postinc3, stmsi_postinc2, stmsi4, stmsi3, stmsi2 and related
- peepholes): Delete.
- * config/arm/ldmstm.md: New file.
- * config/arm/arm-ldmstm.ml: New file.
-
- * config/arm/arm.c (arm_rtx_costs_1): Remove second clause from the
- if statement which adds extra costs to frame-related expressions.
-
- 2010-05-06 Bernd Schmidt <bernds@codesourcery.com>
-
- * config/arm/arm.h (MAX_LDM_STM_OPS): New macro.
- * config/arm/arm.c (multiple_operation_profitable_p,
- compute_offset_order): New static functions.
- (load_multiple_sequence, store_multiple_sequence): Use them.
- Replace constant 4 with MAX_LDM_STM_OPS. Compute order[0] from
- memory offsets, not register numbers.
- (emit_ldm_seq, emit_stm_seq): Replace constant 4 with MAX_LDM_STM_OPS.
-
- 2010-04-16 Bernd Schmidt <bernds@codesourcery.com>
-
- * recog.h (struct recog_data): New field is_operator.
- (struct insn_operand_data): New field is_operator.
- * recog.c (extract_insn): Set recog_data.is_operator.
- * genoutput.c (output_operand_data): Emit code to set the
- is_operator field.
- * reload.c (find_reloads): Use it rather than testing for an
- empty constraint string.
-
-=== added file 'gcc/config/arm/arm-ldmstm.ml'
-Index: gcc-4_5-branch/gcc/config/arm/arm-ldmstm.ml
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/config/arm/arm-ldmstm.ml 2012-03-06 12:51:19.980547615 -0800
-@@ -0,0 +1,333 @@
-+(* Auto-generate ARM ldm/stm patterns
-+ Copyright (C) 2010 Free Software Foundation, Inc.
-+ Contributed by CodeSourcery.
-+
-+ This file is part of GCC.
-+
-+ GCC is free software; you can redistribute it and/or modify it under
-+ the terms of the GNU General Public License as published by the Free
-+ Software Foundation; either version 3, or (at your option) any later
-+ version.
-+
-+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+ for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with GCC; see the file COPYING3. If not see
-+ <http://www.gnu.org/licenses/>.
-+
-+ This is an O'Caml program. The O'Caml compiler is available from:
-+
-+ http://caml.inria.fr/
-+
-+ Or from your favourite OS's friendly packaging system. Tested with version
-+ 3.09.2, though other versions will probably work too.
-+
-+ Run with:
-+ ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.ml
-+*)
-+
-+type amode = IA | IB | DA | DB
-+
-+type optype = IN | OUT | INOUT
-+
-+let rec string_of_addrmode addrmode =
-+ match addrmode with
-+ IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
-+
-+let rec initial_offset addrmode nregs =
-+ match addrmode with
-+ IA -> 0
-+ | IB -> 4
-+ | DA -> -4 * nregs + 4
-+ | DB -> -4 * nregs
-+
-+let rec final_offset addrmode nregs =
-+ match addrmode with
-+ IA -> nregs * 4
-+ | IB -> nregs * 4
-+ | DA -> -4 * nregs
-+ | DB -> -4 * nregs
-+
-+let constr thumb =
-+ if thumb then "l" else "rk"
-+
-+let inout_constr op_type =
-+ match op_type with
-+ OUT -> "="
-+ | INOUT -> "+&"
-+ | IN -> ""
-+
-+let destreg nregs first op_type thumb =
-+ if not first then
-+ Printf.sprintf "(match_dup %d)" (nregs)
-+ else
-+ Printf.sprintf ("(match_operand:SI %d \"s_register_operand\" \"%s%s\")")
-+ (nregs) (inout_constr op_type) (constr thumb)
-+
-+let write_ldm_set thumb nregs offset opnr first =
-+ let indent = " " in
-+ Printf.printf "%s" (if first then " [" else indent);
-+ Printf.printf "(set (match_operand:SI %d \"arm_hard_register_operand\" \"\")\n" opnr;
-+ Printf.printf "%s (mem:SI " indent;
-+ begin if offset != 0 then Printf.printf "(plus:SI " end;
-+ Printf.printf "%s" (destreg nregs first IN thumb);
-+ begin if offset != 0 then Printf.printf "\n%s (const_int %d))" indent offset end;
-+ Printf.printf "))"
-+
-+let write_stm_set thumb nregs offset opnr first =
-+ let indent = " " in
-+ Printf.printf "%s" (if first then " [" else indent);
-+ Printf.printf "(set (mem:SI ";
-+ begin if offset != 0 then Printf.printf "(plus:SI " end;
-+ Printf.printf "%s" (destreg nregs first IN thumb);
-+ begin if offset != 0 then Printf.printf " (const_int %d))" offset end;
-+ Printf.printf ")\n%s (match_operand:SI %d \"arm_hard_register_operand\" \"\"))" indent opnr
-+
-+let write_ldm_peep_set extra_indent nregs opnr first =
-+ let indent = " " ^ extra_indent in
-+ Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
-+ Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
-+ Printf.printf "%s (match_operand:SI %d \"memory_operand\" \"\"))" indent (nregs + opnr)
-+
-+let write_stm_peep_set extra_indent nregs opnr first =
-+ let indent = " " ^ extra_indent in
-+ Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
-+ Printf.printf "(set (match_operand:SI %d \"memory_operand\" \"\")\n" (nregs + opnr);
-+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\"))" indent opnr
-+
-+let write_any_load optype nregs opnr first =
-+ let indent = " " in
-+ Printf.printf "%s" (if first then " [" else indent);
-+ Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
-+ Printf.printf "%s (match_operand:SI %d \"%s\" \"\"))" indent (nregs * 2 + opnr) optype
-+
-+let write_const_store nregs opnr first =
-+ let indent = " " in
-+ Printf.printf "%s(set (match_operand:SI %d \"memory_operand\" \"\")\n" indent (nregs + opnr);
-+ Printf.printf "%s (match_dup %d))" indent opnr
-+
-+let write_const_stm_peep_set nregs opnr first =
-+ write_any_load "const_int_operand" nregs opnr first;
-+ Printf.printf "\n";
-+ write_const_store nregs opnr false
-+
-+
-+let rec write_pat_sets func opnr offset first n_left =
-+ func offset opnr first;
-+ begin
-+ if n_left > 1 then begin
-+ Printf.printf "\n";
-+ write_pat_sets func (opnr + 1) (offset + 4) false (n_left - 1);
-+ end else
-+ Printf.printf "]"
-+ end
-+
-+let rec write_peep_sets func opnr first n_left =
-+ func opnr first;
-+ begin
-+ if n_left > 1 then begin
-+ Printf.printf "\n";
-+ write_peep_sets func (opnr + 1) false (n_left - 1);
-+ end
-+ end
-+
-+let can_thumb addrmode update is_store =
-+ match addrmode, update, is_store with
-+ (* Thumb1 mode only supports IA with update. However, for LDMIA,
-+ if the address register also appears in the list of loaded
-+ registers, the loaded value is stored, hence the RTL pattern
-+ to describe such an insn does not have an update. We check
-+ in the match_parallel predicate that the condition described
-+ above is met. *)
-+ IA, _, false -> true
-+ | IA, true, true -> true
-+ | _ -> false
-+
-+let target addrmode thumb =
-+ match addrmode, thumb with
-+ IA, true -> "TARGET_THUMB1"
-+ | IA, false -> "TARGET_32BIT"
-+ | DB, false -> "TARGET_32BIT"
-+ | _, false -> "TARGET_ARM"
-+
-+let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
-+ let astr = string_of_addrmode addrmode in
-+ Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
-+ (if thumb then "thumb_" else "") name nregs astr
-+ (if update then "_update" else "");
-+ Printf.printf " [(match_parallel 0 \"%s_multiple_operation\"\n" ls;
-+ begin
-+ if update then begin
-+ Printf.printf " [(set %s\n (plus:SI "
-+ (destreg 1 true OUT thumb); (*destreg 2 true IN thumb*)
-+ Printf.printf "(match_operand:SI 2 \"s_register_operand\" \"1\")";
-+ Printf.printf " (const_int %d)))\n"
-+ (final_offset addrmode nregs)
-+ end
-+ end;
-+ write_pat_sets
-+ (write_set_fn thumb (if update then 2 else 1)) (if update then 3 else 2)
-+ (initial_offset addrmode nregs)
-+ (not update) nregs;
-+ Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
-+ (target addrmode thumb)
-+ (if update then nregs + 1 else nregs);
-+ Printf.printf " \"%s%%(%s%%)\\t%%%d%s, {"
-+ name astr (1) (if update then "!" else "");
-+ for n = 1 to nregs; do
-+ Printf.printf "%%%d%s" (n+(if update then 2 else 1)) (if n < nregs then ", " else "")
-+ done;
-+ Printf.printf "}\"\n";
-+ Printf.printf " [(set_attr \"type\" \"%s%d\")" ls nregs;
-+ begin if not thumb then
-+ Printf.printf "\n (set_attr \"predicable\" \"yes\")";
-+ end;
-+ Printf.printf "])\n\n"
-+
-+let write_ldm_pattern addrmode nregs update =
-+ write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update false;
-+ begin if can_thumb addrmode update false then
-+ write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update true;
-+ end
-+
-+let write_stm_pattern addrmode nregs update =
-+ write_pattern_1 "stm" "store" addrmode nregs write_stm_set update false;
-+ begin if can_thumb addrmode update true then
-+ write_pattern_1 "stm" "store" addrmode nregs write_stm_set update true;
-+ end
-+
-+let write_ldm_commutative_peephole thumb =
-+ let nregs = 2 in
-+ Printf.printf "(define_peephole2\n";
-+ write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
-+ let indent = " " in
-+ if thumb then begin
-+ Printf.printf "\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
-+ Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
-+ Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
-+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
-+ end else begin
-+ Printf.printf "\n%s(parallel\n" indent;
-+ Printf.printf "%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
-+ Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
-+ Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
-+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
-+ Printf.printf "%s (clobber (reg:CC CC_REGNUM))])]\n" indent
-+ end;
-+ Printf.printf " \"(((operands[%d] == operands[0] && operands[%d] == operands[1])\n" (nregs * 2 + 2) (nregs * 2 + 3);
-+ Printf.printf " || (operands[%d] == operands[0] && operands[%d] == operands[1]))\n" (nregs * 2 + 3) (nregs * 2 + 2);
-+ Printf.printf " && peep2_reg_dead_p (%d, operands[0]) && peep2_reg_dead_p (%d, operands[1]))\"\n" (nregs + 1) (nregs + 1);
-+ begin
-+ if thumb then
-+ Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
-+ (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
-+ else begin
-+ Printf.printf " [(parallel\n";
-+ Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
-+ (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
-+ Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
-+ end
-+ end;
-+ Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
-+ Printf.printf "})\n\n"
-+
-+let write_ldm_peephole nregs =
-+ Printf.printf "(define_peephole2\n";
-+ write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
-+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
-+ Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
-+
-+let write_ldm_peephole_b nregs =
-+ if nregs > 2 then begin
-+ Printf.printf "(define_peephole2\n";
-+ write_ldm_peep_set "" nregs 0 true;
-+ Printf.printf "\n (parallel\n";
-+ write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
-+ Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
-+ Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
-+ end
-+
-+let write_stm_peephole nregs =
-+ Printf.printf "(define_peephole2\n";
-+ write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
-+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
-+ Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
-+
-+let write_stm_peephole_b nregs =
-+ if nregs > 2 then begin
-+ Printf.printf "(define_peephole2\n";
-+ write_stm_peep_set "" nregs 0 true;
-+ Printf.printf "\n (parallel\n";
-+ write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
-+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
-+ Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
-+ end
-+
-+let write_const_stm_peephole_a nregs =
-+ Printf.printf "(define_peephole2\n";
-+ write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
-+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
-+ Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
-+
-+let write_const_stm_peephole_b nregs =
-+ Printf.printf "(define_peephole2\n";
-+ write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
-+ Printf.printf "\n";
-+ write_peep_sets (write_const_store nregs) 0 false nregs;
-+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
-+ Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
-+
-+let patterns () =
-+ let addrmodes = [ IA; IB; DA; DB ] in
-+ let sizes = [ 4; 3; 2] in
-+ List.iter
-+ (fun n ->
-+ List.iter
-+ (fun addrmode ->
-+ write_ldm_pattern addrmode n false;
-+ write_ldm_pattern addrmode n true;
-+ write_stm_pattern addrmode n false;
-+ write_stm_pattern addrmode n true)
-+ addrmodes;
-+ write_ldm_peephole n;
-+ write_ldm_peephole_b n;
-+ write_const_stm_peephole_a n;
-+ write_const_stm_peephole_b n;
-+ write_stm_peephole n;)
-+ sizes;
-+ write_ldm_commutative_peephole false;
-+ write_ldm_commutative_peephole true
-+
-+let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
-+
-+(* Do it. *)
-+
-+let _ =
-+ print_lines [
-+"/* ARM ldm/stm instruction patterns. This file was automatically generated";
-+" using arm-ldmstm.ml. Please do not edit manually.";
-+"";
-+" Copyright (C) 2010 Free Software Foundation, Inc.";
-+" Contributed by CodeSourcery.";
-+"";
-+" This file is part of GCC.";
-+"";
-+" GCC is free software; you can redistribute it and/or modify it";
-+" under the terms of the GNU General Public License as published";
-+" by the Free Software Foundation; either version 3, or (at your";
-+" option) any later version.";
-+"";
-+" GCC is distributed in the hope that it will be useful, but WITHOUT";
-+" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
-+" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
-+" License for more details.";
-+"";
-+" You should have received a copy of the GNU General Public License and";
-+" a copy of the GCC Runtime Library Exception along with this program;";
-+" see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
-+" <http://www.gnu.org/licenses/>. */";
-+""];
-+ patterns ();
-Index: gcc-4_5-branch/gcc/config/arm/arm-protos.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/arm-protos.h 2012-03-06 12:47:54.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/arm-protos.h 2012-03-06 12:51:19.980547615 -0800
-@@ -99,14 +99,11 @@
- extern int label_mentioned_p (rtx);
- extern RTX_CODE minmax_code (rtx);
- extern int adjacent_mem_locations (rtx, rtx);
--extern int load_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
--extern const char *emit_ldm_seq (rtx *, int);
--extern int store_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
--extern const char * emit_stm_seq (rtx *, int);
--extern rtx arm_gen_load_multiple (int, int, rtx, int, int,
-- rtx, HOST_WIDE_INT *);
--extern rtx arm_gen_store_multiple (int, int, rtx, int, int,
-- rtx, HOST_WIDE_INT *);
-+extern bool gen_ldm_seq (rtx *, int, bool);
-+extern bool gen_stm_seq (rtx *, int);
-+extern bool gen_const_stm_seq (rtx *, int);
-+extern rtx arm_gen_load_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
-+extern rtx arm_gen_store_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
- extern int arm_gen_movmemqi (rtx *);
- extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
- extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
-Index: gcc-4_5-branch/gcc/config/arm/arm.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/arm.c 2012-03-06 12:47:56.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/arm.c 2012-03-06 12:51:19.988547639 -0800
-@@ -753,6 +753,12 @@
- "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
- };
-
-+/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
-+int arm_regs_in_sequence[] =
-+{
-+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
-+};
-+
- #define ARM_LSL_NAME (TARGET_UNIFIED_ASM ? "lsl" : "asl")
- #define streq(string1, string2) (strcmp (string1, string2) == 0)
-
-@@ -9647,24 +9653,125 @@
- return 0;
- }
-
--int
--load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
-- HOST_WIDE_INT *load_offset)
-+
-+/* Return true iff it would be profitable to turn a sequence of NOPS loads
-+ or stores (depending on IS_STORE) into a load-multiple or store-multiple
-+ instruction. ADD_OFFSET is nonzero if the base address register needs
-+ to be modified with an add instruction before we can use it. */
-+
-+static bool
-+multiple_operation_profitable_p (bool is_store ATTRIBUTE_UNUSED,
-+ int nops, HOST_WIDE_INT add_offset)
-+ {
-+ /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
-+ if the offset isn't small enough. The reason 2 ldrs are faster
-+ is because these ARMs are able to do more than one cache access
-+ in a single cycle. The ARM9 and StrongARM have Harvard caches,
-+ whilst the ARM8 has a double bandwidth cache. This means that
-+ these cores can do both an instruction fetch and a data fetch in
-+ a single cycle, so the trick of calculating the address into a
-+ scratch register (one of the result regs) and then doing a load
-+ multiple actually becomes slower (and no smaller in code size).
-+ That is the transformation
-+
-+ ldr rd1, [rbase + offset]
-+ ldr rd2, [rbase + offset + 4]
-+
-+ to
-+
-+ add rd1, rbase, offset
-+ ldmia rd1, {rd1, rd2}
-+
-+ produces worse code -- '3 cycles + any stalls on rd2' instead of
-+ '2 cycles + any stalls on rd2'. On ARMs with only one cache
-+ access per cycle, the first sequence could never complete in less
-+ than 6 cycles, whereas the ldm sequence would only take 5 and
-+ would make better use of sequential accesses if not hitting the
-+ cache.
-+
-+ We cheat here and test 'arm_ld_sched' which we currently know to
-+ only be true for the ARM8, ARM9 and StrongARM. If this ever
-+ changes, then the test below needs to be reworked. */
-+ if (nops == 2 && arm_ld_sched && add_offset != 0)
-+ return false;
-+
-+ return true;
-+}
-+
-+/* Subroutine of load_multiple_sequence and store_multiple_sequence.
-+ Given an array of UNSORTED_OFFSETS, of which there are NOPS, compute
-+ an array ORDER which describes the sequence to use when accessing the
-+ offsets that produces an ascending order. In this sequence, each
-+ offset must be larger by exactly 4 than the previous one. ORDER[0]
-+ must have been filled in with the lowest offset by the caller.
-+ If UNSORTED_REGS is nonnull, it is an array of register numbers that
-+ we use to verify that ORDER produces an ascending order of registers.
-+ Return true if it was possible to construct such an order, false if
-+ not. */
-+
-+static bool
-+compute_offset_order (int nops, HOST_WIDE_INT *unsorted_offsets, int *order,
-+ int *unsorted_regs)
- {
-- int unsorted_regs[4];
-- HOST_WIDE_INT unsorted_offsets[4];
-- int order[4];
-- int base_reg = -1;
- int i;
-+ for (i = 1; i < nops; i++)
-+ {
-+ int j;
-+
-+ order[i] = order[i - 1];
-+ for (j = 0; j < nops; j++)
-+ if (unsorted_offsets[j] == unsorted_offsets[order[i - 1]] + 4)
-+ {
-+ /* We must find exactly one offset that is higher than the
-+ previous one by 4. */
-+ if (order[i] != order[i - 1])
-+ return false;
-+ order[i] = j;
-+ }
-+ if (order[i] == order[i - 1])
-+ return false;
-+ /* The register numbers must be ascending. */
-+ if (unsorted_regs != NULL
-+ && unsorted_regs[order[i]] <= unsorted_regs[order[i - 1]])
-+ return false;
-+ }
-+ return true;
-+}
-+
-+/* Used to determine in a peephole whether a sequence of load
-+ instructions can be changed into a load-multiple instruction.
-+ NOPS is the number of separate load instructions we are examining. The
-+ first NOPS entries in OPERANDS are the destination registers, the
-+ next NOPS entries are memory operands. If this function is
-+ successful, *BASE is set to the common base register of the memory
-+ accesses; *LOAD_OFFSET is set to the first memory location's offset
-+ from that base register.
-+ REGS is an array filled in with the destination register numbers.
-+ SAVED_ORDER (if nonnull), is an array filled in with an order that maps
-+ insn numbers to to an ascending order of stores. If CHECK_REGS is true,
-+ the sequence of registers in REGS matches the loads from ascending memory
-+ locations, and the function verifies that the register numbers are
-+ themselves ascending. If CHECK_REGS is false, the register numbers
-+ are stored in the order they are found in the operands. */
-+static int
-+load_multiple_sequence (rtx *operands, int nops, int *regs, int *saved_order,
-+ int *base, HOST_WIDE_INT *load_offset, bool check_regs)
-+{
-+ int unsorted_regs[MAX_LDM_STM_OPS];
-+ HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
-+ int order[MAX_LDM_STM_OPS];
-+ rtx base_reg_rtx = NULL;
-+ int base_reg = -1;
-+ int i, ldm_case;
-
- if (low_irq_latency)
- return 0;
-
-- /* Can only handle 2, 3, or 4 insns at present,
-- though could be easily extended if required. */
-- gcc_assert (nops >= 2 && nops <= 4);
-+ /* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
-+ easily extended if required. */
-+ gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
-
-- memset (order, 0, 4 * sizeof (int));
-+ memset (order, 0, MAX_LDM_STM_OPS * sizeof (int));
-
- /* Loop over the operands and check that the memory references are
- suitable (i.e. immediate offsets from the same base register). At
-@@ -9702,32 +9809,30 @@
- if (i == 0)
- {
- base_reg = REGNO (reg);
-- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
-- ? REGNO (operands[i])
-- : REGNO (SUBREG_REG (operands[i])));
-- order[0] = 0;
-- }
-- else
-- {
-- if (base_reg != (int) REGNO (reg))
-- /* Not addressed from the same base register. */
-+ base_reg_rtx = reg;
-+ if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
- return 0;
--
-- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
-- ? REGNO (operands[i])
-- : REGNO (SUBREG_REG (operands[i])));
-- if (unsorted_regs[i] < unsorted_regs[order[0]])
-- order[0] = i;
- }
-+ else if (base_reg != (int) REGNO (reg))
-+ /* Not addressed from the same base register. */
-+ return 0;
-+
-+ unsorted_regs[i] = (GET_CODE (operands[i]) == REG
-+ ? REGNO (operands[i])
-+ : REGNO (SUBREG_REG (operands[i])));
-
- /* If it isn't an integer register, or if it overwrites the
- base register but isn't the last insn in the list, then
- we can't do this. */
-- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14
-+ if (unsorted_regs[i] < 0
-+ || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
-+ || unsorted_regs[i] > 14
- || (i != nops - 1 && unsorted_regs[i] == base_reg))
- return 0;
-
- unsorted_offsets[i] = INTVAL (offset);
-+ if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]])
-+ order[0] = i;
- }
- else
- /* Not a suitable memory address. */
-@@ -9736,167 +9841,90 @@
-
- /* All the useful information has now been extracted from the
- operands into unsorted_regs and unsorted_offsets; additionally,
-- order[0] has been set to the lowest numbered register in the
-- list. Sort the registers into order, and check that the memory
-- offsets are ascending and adjacent. */
--
-- for (i = 1; i < nops; i++)
-- {
-- int j;
--
-- order[i] = order[i - 1];
-- for (j = 0; j < nops; j++)
-- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
-- && (order[i] == order[i - 1]
-- || unsorted_regs[j] < unsorted_regs[order[i]]))
-- order[i] = j;
--
-- /* Have we found a suitable register? if not, one must be used more
-- than once. */
-- if (order[i] == order[i - 1])
-- return 0;
-+ order[0] has been set to the lowest offset in the list. Sort
-+ the offsets into order, verifying that they are adjacent, and
-+ check that the register numbers are ascending. */
-+ if (!compute_offset_order (nops, unsorted_offsets, order,
-+ check_regs ? unsorted_regs : NULL))
-+ return 0;
-
-- /* Is the memory address adjacent and ascending? */
-- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
-- return 0;
-- }
-+ if (saved_order)
-+ memcpy (saved_order, order, sizeof order);
-
- if (base)
- {
- *base = base_reg;
-
- for (i = 0; i < nops; i++)
-- regs[i] = unsorted_regs[order[i]];
-+ regs[i] = unsorted_regs[check_regs ? order[i] : i];
-
- *load_offset = unsorted_offsets[order[0]];
- }
-
-- if (unsorted_offsets[order[0]] == 0)
-- return 1; /* ldmia */
--
-- if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
-- return 2; /* ldmib */
--
-- if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
-- return 3; /* ldmda */
--
-- if (unsorted_offsets[order[nops - 1]] == -4)
-- return 4; /* ldmdb */
--
-- /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
-- if the offset isn't small enough. The reason 2 ldrs are faster
-- is because these ARMs are able to do more than one cache access
-- in a single cycle. The ARM9 and StrongARM have Harvard caches,
-- whilst the ARM8 has a double bandwidth cache. This means that
-- these cores can do both an instruction fetch and a data fetch in
-- a single cycle, so the trick of calculating the address into a
-- scratch register (one of the result regs) and then doing a load
-- multiple actually becomes slower (and no smaller in code size).
-- That is the transformation
--
-- ldr rd1, [rbase + offset]
-- ldr rd2, [rbase + offset + 4]
--
-- to
--
-- add rd1, rbase, offset
-- ldmia rd1, {rd1, rd2}
--
-- produces worse code -- '3 cycles + any stalls on rd2' instead of
-- '2 cycles + any stalls on rd2'. On ARMs with only one cache
-- access per cycle, the first sequence could never complete in less
-- than 6 cycles, whereas the ldm sequence would only take 5 and
-- would make better use of sequential accesses if not hitting the
-- cache.
--
-- We cheat here and test 'arm_ld_sched' which we currently know to
-- only be true for the ARM8, ARM9 and StrongARM. If this ever
-- changes, then the test below needs to be reworked. */
-- if (nops == 2 && arm_ld_sched)
-+ if (TARGET_THUMB1
-+ && !peep2_reg_dead_p (nops, base_reg_rtx))
- return 0;
-
-- /* Can't do it without setting up the offset, only do this if it takes
-- no more than one insn. */
-- return (const_ok_for_arm (unsorted_offsets[order[0]])
-- || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
--}
--
--const char *
--emit_ldm_seq (rtx *operands, int nops)
--{
-- int regs[4];
-- int base_reg;
-- HOST_WIDE_INT offset;
-- char buf[100];
-- int i;
--
-- switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
-- {
-- case 1:
-- strcpy (buf, "ldm%(ia%)\t");
-- break;
--
-- case 2:
-- strcpy (buf, "ldm%(ib%)\t");
-- break;
--
-- case 3:
-- strcpy (buf, "ldm%(da%)\t");
-- break;
--
-- case 4:
-- strcpy (buf, "ldm%(db%)\t");
-- break;
--
-- case 5:
-- if (offset >= 0)
-- sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
-- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
-- (long) offset);
-- else
-- sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
-- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
-- (long) -offset);
-- output_asm_insn (buf, operands);
-- base_reg = regs[0];
-- strcpy (buf, "ldm%(ia%)\t");
-- break;
--
-- default:
-- gcc_unreachable ();
-- }
--
-- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
-- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
--
-- for (i = 1; i < nops; i++)
-- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
-- reg_names[regs[i]]);
-+ if (unsorted_offsets[order[0]] == 0)
-+ ldm_case = 1; /* ldmia */
-+ else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
-+ ldm_case = 2; /* ldmib */
-+ else if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
-+ ldm_case = 3; /* ldmda */
-+ else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
-+ ldm_case = 4; /* ldmdb */
-+ else if (const_ok_for_arm (unsorted_offsets[order[0]])
-+ || const_ok_for_arm (-unsorted_offsets[order[0]]))
-+ ldm_case = 5;
-+ else
-+ return 0;
-
-- strcat (buf, "}\t%@ phole ldm");
-+ if (!multiple_operation_profitable_p (false, nops,
-+ ldm_case == 5
-+ ? unsorted_offsets[order[0]] : 0))
-+ return 0;
-
-- output_asm_insn (buf, operands);
-- return "";
-+ return ldm_case;
- }
-
--int
--store_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
-- HOST_WIDE_INT * load_offset)
--{
-- int unsorted_regs[4];
-- HOST_WIDE_INT unsorted_offsets[4];
-- int order[4];
-+/* Used to determine in a peephole whether a sequence of store instructions can
-+ be changed into a store-multiple instruction.
-+ NOPS is the number of separate store instructions we are examining.
-+ NOPS_TOTAL is the total number of instructions recognized by the peephole
-+ pattern.
-+ The first NOPS entries in OPERANDS are the source registers, the next
-+ NOPS entries are memory operands. If this function is successful, *BASE is
-+ set to the common base register of the memory accesses; *LOAD_OFFSET is set
-+ to the first memory location's offset from that base register. REGS is an
-+ array filled in with the source register numbers, REG_RTXS (if nonnull) is
-+ likewise filled with the corresponding rtx's.
-+ SAVED_ORDER (if nonnull), is an array filled in with an order that maps insn
-+ numbers to to an ascending order of stores.
-+ If CHECK_REGS is true, the sequence of registers in *REGS matches the stores
-+ from ascending memory locations, and the function verifies that the register
-+ numbers are themselves ascending. If CHECK_REGS is false, the register
-+ numbers are stored in the order they are found in the operands. */
-+static int
-+store_multiple_sequence (rtx *operands, int nops, int nops_total,
-+ int *regs, rtx *reg_rtxs, int *saved_order, int *base,
-+ HOST_WIDE_INT *load_offset, bool check_regs)
-+{
-+ int unsorted_regs[MAX_LDM_STM_OPS];
-+ rtx unsorted_reg_rtxs[MAX_LDM_STM_OPS];
-+ HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
-+ int order[MAX_LDM_STM_OPS];
- int base_reg = -1;
-- int i;
-+ rtx base_reg_rtx = NULL;
-+ int i, stm_case;
-
- if (low_irq_latency)
- return 0;
-
-- /* Can only handle 2, 3, or 4 insns at present, though could be easily
-- extended if required. */
-- gcc_assert (nops >= 2 && nops <= 4);
-+ /* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
-+ easily extended if required. */
-+ gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
-
-- memset (order, 0, 4 * sizeof (int));
-+ memset (order, 0, MAX_LDM_STM_OPS * sizeof (int));
-
- /* Loop over the operands and check that the memory references are
- suitable (i.e. immediate offsets from the same base register). At
-@@ -9931,32 +9959,32 @@
- && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
- == CONST_INT)))
- {
-+ unsorted_reg_rtxs[i] = (GET_CODE (operands[i]) == REG
-+ ? operands[i] : SUBREG_REG (operands[i]));
-+ unsorted_regs[i] = REGNO (unsorted_reg_rtxs[i]);
-+
- if (i == 0)
- {
- base_reg = REGNO (reg);
-- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
-- ? REGNO (operands[i])
-- : REGNO (SUBREG_REG (operands[i])));
-- order[0] = 0;
-- }
-- else
-- {
-- if (base_reg != (int) REGNO (reg))
-- /* Not addressed from the same base register. */
-+ base_reg_rtx = reg;
-+ if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
- return 0;
--
-- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
-- ? REGNO (operands[i])
-- : REGNO (SUBREG_REG (operands[i])));
-- if (unsorted_regs[i] < unsorted_regs[order[0]])
-- order[0] = i;
- }
-+ else if (base_reg != (int) REGNO (reg))
-+ /* Not addressed from the same base register. */
-+ return 0;
-
- /* If it isn't an integer register, then we can't do this. */
-- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
-+ if (unsorted_regs[i] < 0
-+ || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
-+ || (TARGET_THUMB2 && unsorted_regs[i] == base_reg)
-+ || (TARGET_THUMB2 && unsorted_regs[i] == SP_REGNUM)
-+ || unsorted_regs[i] > 14)
- return 0;
-
- unsorted_offsets[i] = INTVAL (offset);
-+ if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]])
-+ order[0] = i;
- }
- else
- /* Not a suitable memory address. */
-@@ -9965,111 +9993,65 @@
-
- /* All the useful information has now been extracted from the
- operands into unsorted_regs and unsorted_offsets; additionally,
-- order[0] has been set to the lowest numbered register in the
-- list. Sort the registers into order, and check that the memory
-- offsets are ascending and adjacent. */
--
-- for (i = 1; i < nops; i++)
-- {
-- int j;
--
-- order[i] = order[i - 1];
-- for (j = 0; j < nops; j++)
-- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
-- && (order[i] == order[i - 1]
-- || unsorted_regs[j] < unsorted_regs[order[i]]))
-- order[i] = j;
--
-- /* Have we found a suitable register? if not, one must be used more
-- than once. */
-- if (order[i] == order[i - 1])
-- return 0;
-+ order[0] has been set to the lowest offset in the list. Sort
-+ the offsets into order, verifying that they are adjacent, and
-+ check that the register numbers are ascending. */
-+ if (!compute_offset_order (nops, unsorted_offsets, order,
-+ check_regs ? unsorted_regs : NULL))
-+ return 0;
-
-- /* Is the memory address adjacent and ascending? */
-- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
-- return 0;
-- }
-+ if (saved_order)
-+ memcpy (saved_order, order, sizeof order);
-
- if (base)
- {
- *base = base_reg;
-
- for (i = 0; i < nops; i++)
-- regs[i] = unsorted_regs[order[i]];
-+ {
-+ regs[i] = unsorted_regs[check_regs ? order[i] : i];
-+ if (reg_rtxs)
-+ reg_rtxs[i] = unsorted_reg_rtxs[check_regs ? order[i] : i];
-+ }
-
- *load_offset = unsorted_offsets[order[0]];
- }
-
-- if (unsorted_offsets[order[0]] == 0)
-- return 1; /* stmia */
--
-- if (unsorted_offsets[order[0]] == 4)
-- return 2; /* stmib */
--
-- if (unsorted_offsets[order[nops - 1]] == 0)
-- return 3; /* stmda */
--
-- if (unsorted_offsets[order[nops - 1]] == -4)
-- return 4; /* stmdb */
--
-- return 0;
--}
--
--const char *
--emit_stm_seq (rtx *operands, int nops)
--{
-- int regs[4];
-- int base_reg;
-- HOST_WIDE_INT offset;
-- char buf[100];
-- int i;
--
-- switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
-- {
-- case 1:
-- strcpy (buf, "stm%(ia%)\t");
-- break;
--
-- case 2:
-- strcpy (buf, "stm%(ib%)\t");
-- break;
--
-- case 3:
-- strcpy (buf, "stm%(da%)\t");
-- break;
--
-- case 4:
-- strcpy (buf, "stm%(db%)\t");
-- break;
--
-- default:
-- gcc_unreachable ();
-- }
--
-- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
-- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
-+ if (TARGET_THUMB1
-+ && !peep2_reg_dead_p (nops_total, base_reg_rtx))
-+ return 0;
-
-- for (i = 1; i < nops; i++)
-- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
-- reg_names[regs[i]]);
-+ if (unsorted_offsets[order[0]] == 0)
-+ stm_case = 1; /* stmia */
-+ else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
-+ stm_case = 2; /* stmib */
-+ else if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
-+ stm_case = 3; /* stmda */
-+ else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
-+ stm_case = 4; /* stmdb */
-+ else
-+ return 0;
-
-- strcat (buf, "}\t%@ phole stm");
-+ if (!multiple_operation_profitable_p (false, nops, 0))
-+ return 0;
-
-- output_asm_insn (buf, operands);
-- return "";
-+ return stm_case;
- }
-
- /* Routines for use in generating RTL. */
-
--rtx
--arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
-- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
-+/* Generate a load-multiple instruction. COUNT is the number of loads in
-+ the instruction; REGS and MEMS are arrays containing the operands.
-+ BASEREG is the base register to be used in addressing the memory operands.
-+ WBACK_OFFSET is nonzero if the instruction should update the base
-+ register. */
-+
-+static rtx
-+arm_gen_load_multiple_1 (int count, int *regs, rtx *mems, rtx basereg,
-+ HOST_WIDE_INT wback_offset)
- {
-- HOST_WIDE_INT offset = *offsetp;
- int i = 0, j;
- rtx result;
-- int sign = up ? 1 : -1;
-- rtx mem, addr;
-
- /* XScale has load-store double instructions, but they have stricter
- alignment requirements than load-store multiple, so we cannot
-@@ -10106,18 +10088,10 @@
- start_sequence ();
-
- for (i = 0; i < count; i++)
-- {
-- addr = plus_constant (from, i * 4 * sign);
-- mem = adjust_automodify_address (basemem, SImode, addr, offset);
-- emit_move_insn (gen_rtx_REG (SImode, base_regno + i), mem);
-- offset += 4 * sign;
-- }
-+ emit_move_insn (gen_rtx_REG (SImode, regs[i]), mems[i]);
-
-- if (write_back)
-- {
-- emit_move_insn (from, plus_constant (from, count * 4 * sign));
-- *offsetp = offset;
-- }
-+ if (wback_offset != 0)
-+ emit_move_insn (basereg, plus_constant (basereg, wback_offset));
-
- seq = get_insns ();
- end_sequence ();
-@@ -10126,41 +10100,40 @@
- }
-
- result = gen_rtx_PARALLEL (VOIDmode,
-- rtvec_alloc (count + (write_back ? 1 : 0)));
-- if (write_back)
-+ rtvec_alloc (count + (wback_offset != 0 ? 1 : 0)));
-+ if (wback_offset != 0)
- {
- XVECEXP (result, 0, 0)
-- = gen_rtx_SET (VOIDmode, from, plus_constant (from, count * 4 * sign));
-+ = gen_rtx_SET (VOIDmode, basereg,
-+ plus_constant (basereg, wback_offset));
- i = 1;
- count++;
- }
-
- for (j = 0; i < count; i++, j++)
-- {
-- addr = plus_constant (from, j * 4 * sign);
-- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
-- XVECEXP (result, 0, i)
-- = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, base_regno + j), mem);
-- offset += 4 * sign;
-- }
--
-- if (write_back)
-- *offsetp = offset;
-+ XVECEXP (result, 0, i)
-+ = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, regs[j]), mems[j]);
-
- return result;
- }
-
--rtx
--arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
-- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
-+/* Generate a store-multiple instruction. COUNT is the number of stores in
-+ the instruction; REGS and MEMS are arrays containing the operands.
-+ BASEREG is the base register to be used in addressing the memory operands.
-+ WBACK_OFFSET is nonzero if the instruction should update the base
-+ register. */
-+
-+static rtx
-+arm_gen_store_multiple_1 (int count, int *regs, rtx *mems, rtx basereg,
-+ HOST_WIDE_INT wback_offset)
- {
-- HOST_WIDE_INT offset = *offsetp;
- int i = 0, j;
- rtx result;
-- int sign = up ? 1 : -1;
-- rtx mem, addr;
-
-- /* See arm_gen_load_multiple for discussion of
-+ if (GET_CODE (basereg) == PLUS)
-+ basereg = XEXP (basereg, 0);
-+
-+ /* See arm_gen_load_multiple_1 for discussion of
- the pros/cons of ldm/stm usage for XScale. */
- if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size))
- {
-@@ -10169,18 +10142,10 @@
- start_sequence ();
-
- for (i = 0; i < count; i++)
-- {
-- addr = plus_constant (to, i * 4 * sign);
-- mem = adjust_automodify_address (basemem, SImode, addr, offset);
-- emit_move_insn (mem, gen_rtx_REG (SImode, base_regno + i));
-- offset += 4 * sign;
-- }
-+ emit_move_insn (mems[i], gen_rtx_REG (SImode, regs[i]));
-
-- if (write_back)
-- {
-- emit_move_insn (to, plus_constant (to, count * 4 * sign));
-- *offsetp = offset;
-- }
-+ if (wback_offset != 0)
-+ emit_move_insn (basereg, plus_constant (basereg, wback_offset));
-
- seq = get_insns ();
- end_sequence ();
-@@ -10189,29 +10154,319 @@
- }
-
- result = gen_rtx_PARALLEL (VOIDmode,
-- rtvec_alloc (count + (write_back ? 1 : 0)));
-- if (write_back)
-+ rtvec_alloc (count + (wback_offset != 0 ? 1 : 0)));
-+ if (wback_offset != 0)
- {
- XVECEXP (result, 0, 0)
-- = gen_rtx_SET (VOIDmode, to,
-- plus_constant (to, count * 4 * sign));
-+ = gen_rtx_SET (VOIDmode, basereg,
-+ plus_constant (basereg, wback_offset));
- i = 1;
- count++;
- }
-
- for (j = 0; i < count; i++, j++)
-+ XVECEXP (result, 0, i)
-+ = gen_rtx_SET (VOIDmode, mems[j], gen_rtx_REG (SImode, regs[j]));
-+
-+ return result;
-+}
-+
-+/* Generate either a load-multiple or a store-multiple instruction. This
-+ function can be used in situations where we can start with a single MEM
-+ rtx and adjust its address upwards.
-+ COUNT is the number of operations in the instruction, not counting a
-+ possible update of the base register. REGS is an array containing the
-+ register operands.
-+ BASEREG is the base register to be used in addressing the memory operands,
-+ which are constructed from BASEMEM.
-+ WRITE_BACK specifies whether the generated instruction should include an
-+ update of the base register.
-+ OFFSETP is used to pass an offset to and from this function; this offset
-+ is not used when constructing the address (instead BASEMEM should have an
-+ appropriate offset in its address), it is used only for setting
-+ MEM_OFFSET. It is updated only if WRITE_BACK is true.*/
-+
-+static rtx
-+arm_gen_multiple_op (bool is_load, int *regs, int count, rtx basereg,
-+ bool write_back, rtx basemem, HOST_WIDE_INT *offsetp)
-+{
-+ rtx mems[MAX_LDM_STM_OPS];
-+ HOST_WIDE_INT offset = *offsetp;
-+ int i;
-+
-+ gcc_assert (count <= MAX_LDM_STM_OPS);
-+
-+ if (GET_CODE (basereg) == PLUS)
-+ basereg = XEXP (basereg, 0);
-+
-+ for (i = 0; i < count; i++)
- {
-- addr = plus_constant (to, j * 4 * sign);
-- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
-- XVECEXP (result, 0, i)
-- = gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (SImode, base_regno + j));
-- offset += 4 * sign;
-+ rtx addr = plus_constant (basereg, i * 4);
-+ mems[i] = adjust_automodify_address_nv (basemem, SImode, addr, offset);
-+ offset += 4;
- }
-
- if (write_back)
- *offsetp = offset;
-
-- return result;
-+ if (is_load)
-+ return arm_gen_load_multiple_1 (count, regs, mems, basereg,
-+ write_back ? 4 * count : 0);
-+ else
-+ return arm_gen_store_multiple_1 (count, regs, mems, basereg,
-+ write_back ? 4 * count : 0);
-+}
-+
-+rtx
-+arm_gen_load_multiple (int *regs, int count, rtx basereg, int write_back,
-+ rtx basemem, HOST_WIDE_INT *offsetp)
-+{
-+ return arm_gen_multiple_op (TRUE, regs, count, basereg, write_back, basemem,
-+ offsetp);
-+}
-+
-+rtx
-+arm_gen_store_multiple (int *regs, int count, rtx basereg, int write_back,
-+ rtx basemem, HOST_WIDE_INT *offsetp)
-+{
-+ return arm_gen_multiple_op (FALSE, regs, count, basereg, write_back, basemem,
-+ offsetp);
-+}
-+
-+/* Called from a peephole2 expander to turn a sequence of loads into an
-+ LDM instruction. OPERANDS are the operands found by the peephole matcher;
-+ NOPS indicates how many separate loads we are trying to combine. SORT_REGS
-+ is true if we can reorder the registers because they are used commutatively
-+ subsequently.
-+ Returns true iff we could generate a new instruction. */
-+
-+bool
-+gen_ldm_seq (rtx *operands, int nops, bool sort_regs)
-+{
-+ int regs[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
-+ rtx mems[MAX_LDM_STM_OPS];
-+ int i, j, base_reg;
-+ rtx base_reg_rtx;
-+ HOST_WIDE_INT offset;
-+ int write_back = FALSE;
-+ int ldm_case;
-+ rtx addr;
-+
-+ ldm_case = load_multiple_sequence (operands, nops, regs, mem_order,
-+ &base_reg, &offset, !sort_regs);
-+
-+ if (ldm_case == 0)
-+ return false;
-+
-+ if (sort_regs)
-+ for (i = 0; i < nops - 1; i++)
-+ for (j = i + 1; j < nops; j++)
-+ if (regs[i] > regs[j])
-+ {
-+ int t = regs[i];
-+ regs[i] = regs[j];
-+ regs[j] = t;
-+ }
-+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
-+
-+ if (TARGET_THUMB1)
-+ {
-+ gcc_assert (peep2_reg_dead_p (nops, base_reg_rtx));
-+ gcc_assert (ldm_case == 1 || ldm_case == 5);
-+ write_back = TRUE;
-+ }
-+
-+ if (ldm_case == 5)
-+ {
-+ rtx newbase = TARGET_THUMB1 ? base_reg_rtx : gen_rtx_REG (SImode, regs[0]);
-+ emit_insn (gen_addsi3 (newbase, base_reg_rtx, GEN_INT (offset)));
-+ offset = 0;
-+ if (!TARGET_THUMB1)
-+ {
-+ base_reg = regs[0];
-+ base_reg_rtx = newbase;
-+ }
-+ }
-+
-+ for (i = 0; i < nops; i++)
-+ {
-+ addr = plus_constant (base_reg_rtx, offset + i * 4);
-+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
-+ SImode, addr, 0);
-+ }
-+ emit_insn (arm_gen_load_multiple_1 (nops, regs, mems, base_reg_rtx,
-+ write_back ? offset + i * 4 : 0));
-+ return true;
-+}
-+
-+/* Called from a peephole2 expander to turn a sequence of stores into an
-+ STM instruction. OPERANDS are the operands found by the peephole matcher;
-+ NOPS indicates how many separate stores we are trying to combine.
-+ Returns true iff we could generate a new instruction. */
-+
-+bool
-+gen_stm_seq (rtx *operands, int nops)
-+{
-+ int i;
-+ int regs[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
-+ rtx mems[MAX_LDM_STM_OPS];
-+ int base_reg;
-+ rtx base_reg_rtx;
-+ HOST_WIDE_INT offset;
-+ int write_back = FALSE;
-+ int stm_case;
-+ rtx addr;
-+ bool base_reg_dies;
-+
-+ stm_case = store_multiple_sequence (operands, nops, nops, regs, NULL,
-+ mem_order, &base_reg, &offset, true);
-+
-+ if (stm_case == 0)
-+ return false;
-+
-+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
-+
-+ base_reg_dies = peep2_reg_dead_p (nops, base_reg_rtx);
-+ if (TARGET_THUMB1)
-+ {
-+ gcc_assert (base_reg_dies);
-+ write_back = TRUE;
-+ }
-+
-+ if (stm_case == 5)
-+ {
-+ gcc_assert (base_reg_dies);
-+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, GEN_INT (offset)));
-+ offset = 0;
-+ }
-+
-+ addr = plus_constant (base_reg_rtx, offset);
-+
-+ for (i = 0; i < nops; i++)
-+ {
-+ addr = plus_constant (base_reg_rtx, offset + i * 4);
-+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
-+ SImode, addr, 0);
-+ }
-+ emit_insn (arm_gen_store_multiple_1 (nops, regs, mems, base_reg_rtx,
-+ write_back ? offset + i * 4 : 0));
-+ return true;
-+}
-+
-+/* Called from a peephole2 expander to turn a sequence of stores that are
-+ preceded by constant loads into an STM instruction. OPERANDS are the
-+ operands found by the peephole matcher; NOPS indicates how many
-+ separate stores we are trying to combine; there are 2 * NOPS
-+ instructions in the peephole.
-+ Returns true iff we could generate a new instruction. */
-+
-+bool
-+gen_const_stm_seq (rtx *operands, int nops)
-+{
-+ int regs[MAX_LDM_STM_OPS], sorted_regs[MAX_LDM_STM_OPS];
-+ int reg_order[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
-+ rtx reg_rtxs[MAX_LDM_STM_OPS], orig_reg_rtxs[MAX_LDM_STM_OPS];
-+ rtx mems[MAX_LDM_STM_OPS];
-+ int base_reg;
-+ rtx base_reg_rtx;
-+ HOST_WIDE_INT offset;
-+ int write_back = FALSE;
-+ int stm_case;
-+ rtx addr;
-+ bool base_reg_dies;
-+ int i, j;
-+ HARD_REG_SET allocated;
-+
-+ stm_case = store_multiple_sequence (operands, nops, 2 * nops, regs, reg_rtxs,
-+ mem_order, &base_reg, &offset, false);
-+
-+ if (stm_case == 0)
-+ return false;
-+
-+ memcpy (orig_reg_rtxs, reg_rtxs, sizeof orig_reg_rtxs);
-+
-+ /* If the same register is used more than once, try to find a free
-+ register. */
-+ CLEAR_HARD_REG_SET (allocated);
-+ for (i = 0; i < nops; i++)
-+ {
-+ for (j = i + 1; j < nops; j++)
-+ if (regs[i] == regs[j])
-+ {
-+ rtx t = peep2_find_free_register (0, nops * 2,
-+ TARGET_THUMB1 ? "l" : "r",
-+ SImode, &allocated);
-+ if (t == NULL_RTX)
-+ return false;
-+ reg_rtxs[i] = t;
-+ regs[i] = REGNO (t);
-+ }
-+ }
-+
-+ /* Compute an ordering that maps the register numbers to an ascending
-+ sequence. */
-+ reg_order[0] = 0;
-+ for (i = 0; i < nops; i++)
-+ if (regs[i] < regs[reg_order[0]])
-+ reg_order[0] = i;
-+
-+ for (i = 1; i < nops; i++)
-+ {
-+ int this_order = reg_order[i - 1];
-+ for (j = 0; j < nops; j++)
-+ if (regs[j] > regs[reg_order[i - 1]]
-+ && (this_order == reg_order[i - 1]
-+ || regs[j] < regs[this_order]))
-+ this_order = j;
-+ reg_order[i] = this_order;
-+ }
-+
-+ /* Ensure that registers that must be live after the instruction end
-+ up with the correct value. */
-+ for (i = 0; i < nops; i++)
-+ {
-+ int this_order = reg_order[i];
-+ if ((this_order != mem_order[i]
-+ || orig_reg_rtxs[this_order] != reg_rtxs[this_order])
-+ && !peep2_reg_dead_p (nops * 2, orig_reg_rtxs[this_order]))
-+ return false;
-+ }
-+
-+ /* Load the constants. */
-+ for (i = 0; i < nops; i++)
-+ {
-+ rtx op = operands[2 * nops + mem_order[i]];
-+ sorted_regs[i] = regs[reg_order[i]];
-+ emit_move_insn (reg_rtxs[reg_order[i]], op);
-+ }
-+
-+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
-+
-+ base_reg_dies = peep2_reg_dead_p (nops * 2, base_reg_rtx);
-+ if (TARGET_THUMB1)
-+ {
-+ gcc_assert (base_reg_dies);
-+ write_back = TRUE;
-+ }
-+
-+ if (stm_case == 5)
-+ {
-+ gcc_assert (base_reg_dies);
-+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, GEN_INT (offset)));
-+ offset = 0;
-+ }
-+
-+ addr = plus_constant (base_reg_rtx, offset);
-+
-+ for (i = 0; i < nops; i++)
-+ {
-+ addr = plus_constant (base_reg_rtx, offset + i * 4);
-+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
-+ SImode, addr, 0);
-+ }
-+ emit_insn (arm_gen_store_multiple_1 (nops, sorted_regs, mems, base_reg_rtx,
-+ write_back ? offset + i * 4 : 0));
-+ return true;
- }
-
- int
-@@ -10247,20 +10502,21 @@
- for (i = 0; in_words_to_go >= 2; i+=4)
- {
- if (in_words_to_go > 4)
-- emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
-- srcbase, &srcoffset));
-+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, src,
-+ TRUE, srcbase, &srcoffset));
- else
-- emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
-- FALSE, srcbase, &srcoffset));
-+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, in_words_to_go,
-+ src, FALSE, srcbase,
-+ &srcoffset));
-
- if (out_words_to_go)
- {
- if (out_words_to_go > 4)
-- emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
-- dstbase, &dstoffset));
-+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, dst,
-+ TRUE, dstbase, &dstoffset));
- else if (out_words_to_go != 1)
-- emit_insn (arm_gen_store_multiple (0, out_words_to_go,
-- dst, TRUE,
-+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence,
-+ out_words_to_go, dst,
- (last_bytes == 0
- ? FALSE : TRUE),
- dstbase, &dstoffset));
-Index: gcc-4_5-branch/gcc/config/arm/arm.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/arm.h 2012-03-06 12:47:55.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/arm.h 2012-03-06 12:51:19.988547639 -0800
-@@ -1143,6 +1143,9 @@
- ((MODE) == TImode || (MODE) == EImode || (MODE) == OImode \
- || (MODE) == CImode || (MODE) == XImode)
-
-+/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
-+extern int arm_regs_in_sequence[];
-+
- /* The order in which register should be allocated. It is good to use ip
- since no saving is required (though calls clobber it) and it never contains
- function parameters. It is quite good to use lr since other calls may
-@@ -2821,4 +2824,8 @@
- #define NEED_INDICATE_EXEC_STACK 0
- #endif
-
-+/* The maximum number of parallel loads or stores we support in an ldm/stm
-+ instruction. */
-+#define MAX_LDM_STM_OPS 4
-+
- #endif /* ! GCC_ARM_H */
-Index: gcc-4_5-branch/gcc/config/arm/arm.md
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/arm.md 2012-03-06 12:47:56.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/arm.md 2012-03-06 12:51:19.992547622 -0800
-@@ -6282,7 +6282,7 @@
-
- ;; load- and store-multiple insns
- ;; The arm can load/store any set of registers, provided that they are in
--;; ascending order; but that is beyond GCC so stick with what it knows.
-+;; ascending order, but these expanders assume a contiguous set.
-
- (define_expand "load_multiple"
- [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
-@@ -6303,126 +6303,12 @@
- FAIL;
-
- operands[3]
-- = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
-+ = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
-+ INTVAL (operands[2]),
- force_reg (SImode, XEXP (operands[1], 0)),
-- TRUE, FALSE, operands[1], &offset);
-+ FALSE, operands[1], &offset);
- })
-
--;; Load multiple with write-back
--
--(define_insn "*ldmsi_postinc4"
-- [(match_parallel 0 "load_multiple_operation"
-- [(set (match_operand:SI 1 "s_register_operand" "=r")
-- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
-- (const_int 16)))
-- (set (match_operand:SI 3 "arm_hard_register_operand" "")
-- (mem:SI (match_dup 2)))
-- (set (match_operand:SI 4 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
-- (set (match_operand:SI 5 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
-- (set (match_operand:SI 6 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
-- "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
-- [(set_attr "type" "load4")
-- (set_attr "predicable" "yes")]
--)
--
--(define_insn "*ldmsi_postinc4_thumb1"
-- [(match_parallel 0 "load_multiple_operation"
-- [(set (match_operand:SI 1 "s_register_operand" "=l")
-- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
-- (const_int 16)))
-- (set (match_operand:SI 3 "arm_hard_register_operand" "")
-- (mem:SI (match_dup 2)))
-- (set (match_operand:SI 4 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
-- (set (match_operand:SI 5 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
-- (set (match_operand:SI 6 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
-- "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
-- "ldmia\\t%1!, {%3, %4, %5, %6}"
-- [(set_attr "type" "load4")]
--)
--
--(define_insn "*ldmsi_postinc3"
-- [(match_parallel 0 "load_multiple_operation"
-- [(set (match_operand:SI 1 "s_register_operand" "=r")
-- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
-- (const_int 12)))
-- (set (match_operand:SI 3 "arm_hard_register_operand" "")
-- (mem:SI (match_dup 2)))
-- (set (match_operand:SI 4 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
-- (set (match_operand:SI 5 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-- "ldm%(ia%)\\t%1!, {%3, %4, %5}"
-- [(set_attr "type" "load3")
-- (set_attr "predicable" "yes")]
--)
--
--(define_insn "*ldmsi_postinc2"
-- [(match_parallel 0 "load_multiple_operation"
-- [(set (match_operand:SI 1 "s_register_operand" "=r")
-- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
-- (const_int 8)))
-- (set (match_operand:SI 3 "arm_hard_register_operand" "")
-- (mem:SI (match_dup 2)))
-- (set (match_operand:SI 4 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-- "ldm%(ia%)\\t%1!, {%3, %4}"
-- [(set_attr "type" "load2")
-- (set_attr "predicable" "yes")]
--)
--
--;; Ordinary load multiple
--
--(define_insn "*ldmsi4"
-- [(match_parallel 0 "load_multiple_operation"
-- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
-- (set (match_operand:SI 3 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
-- (set (match_operand:SI 4 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
-- (set (match_operand:SI 5 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-- "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
-- [(set_attr "type" "load4")
-- (set_attr "predicable" "yes")]
--)
--
--(define_insn "*ldmsi3"
-- [(match_parallel 0 "load_multiple_operation"
-- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
-- (set (match_operand:SI 3 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
-- (set (match_operand:SI 4 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-- "ldm%(ia%)\\t%1, {%2, %3, %4}"
-- [(set_attr "type" "load3")
-- (set_attr "predicable" "yes")]
--)
--
--(define_insn "*ldmsi2"
-- [(match_parallel 0 "load_multiple_operation"
-- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
-- (set (match_operand:SI 3 "arm_hard_register_operand" "")
-- (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
-- "ldm%(ia%)\\t%1, {%2, %3}"
-- [(set_attr "type" "load2")
-- (set_attr "predicable" "yes")]
--)
--
- (define_expand "store_multiple"
- [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
- (match_operand:SI 1 "" ""))
-@@ -6442,125 +6328,12 @@
- FAIL;
-
- operands[3]
-- = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
-+ = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
-+ INTVAL (operands[2]),
- force_reg (SImode, XEXP (operands[0], 0)),
-- TRUE, FALSE, operands[0], &offset);
-+ FALSE, operands[0], &offset);
- })
-
--;; Store multiple with write-back
--
--(define_insn "*stmsi_postinc4"
-- [(match_parallel 0 "store_multiple_operation"
-- [(set (match_operand:SI 1 "s_register_operand" "=r")
-- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
-- (const_int 16)))
-- (set (mem:SI (match_dup 2))
-- (match_operand:SI 3 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-- (match_operand:SI 4 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-- (match_operand:SI 5 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
-- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
-- "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
-- [(set_attr "predicable" "yes")
-- (set_attr "type" "store4")]
--)
--
--(define_insn "*stmsi_postinc4_thumb1"
-- [(match_parallel 0 "store_multiple_operation"
-- [(set (match_operand:SI 1 "s_register_operand" "=l")
-- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
-- (const_int 16)))
-- (set (mem:SI (match_dup 2))
-- (match_operand:SI 3 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-- (match_operand:SI 4 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-- (match_operand:SI 5 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
-- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
-- "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
-- "stmia\\t%1!, {%3, %4, %5, %6}"
-- [(set_attr "type" "store4")]
--)
--
--(define_insn "*stmsi_postinc3"
-- [(match_parallel 0 "store_multiple_operation"
-- [(set (match_operand:SI 1 "s_register_operand" "=r")
-- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
-- (const_int 12)))
-- (set (mem:SI (match_dup 2))
-- (match_operand:SI 3 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-- (match_operand:SI 4 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-- "stm%(ia%)\\t%1!, {%3, %4, %5}"
-- [(set_attr "predicable" "yes")
-- (set_attr "type" "store3")]
--)
--
--(define_insn "*stmsi_postinc2"
-- [(match_parallel 0 "store_multiple_operation"
-- [(set (match_operand:SI 1 "s_register_operand" "=r")
-- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
-- (const_int 8)))
-- (set (mem:SI (match_dup 2))
-- (match_operand:SI 3 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-- "stm%(ia%)\\t%1!, {%3, %4}"
-- [(set_attr "predicable" "yes")
-- (set_attr "type" "store2")]
--)
--
--;; Ordinary store multiple
--
--(define_insn "*stmsi4"
-- [(match_parallel 0 "store_multiple_operation"
-- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
-- (match_operand:SI 2 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
-- (match_operand:SI 3 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
-- (match_operand:SI 4 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
-- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-- "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
-- [(set_attr "predicable" "yes")
-- (set_attr "type" "store4")]
--)
--
--(define_insn "*stmsi3"
-- [(match_parallel 0 "store_multiple_operation"
-- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
-- (match_operand:SI 2 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
-- (match_operand:SI 3 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
-- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-- "stm%(ia%)\\t%1, {%2, %3, %4}"
-- [(set_attr "predicable" "yes")
-- (set_attr "type" "store3")]
--)
--
--(define_insn "*stmsi2"
-- [(match_parallel 0 "store_multiple_operation"
-- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
-- (match_operand:SI 2 "arm_hard_register_operand" ""))
-- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
-- (match_operand:SI 3 "arm_hard_register_operand" ""))])]
-- "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
-- "stm%(ia%)\\t%1, {%2, %3}"
-- [(set_attr "predicable" "yes")
-- (set_attr "type" "store2")]
--)
-
- ;; Move a block of memory if it is word aligned and MORE than 2 words long.
- ;; We could let this apply for blocks of less than this, but it clobbers so
-@@ -9025,8 +8798,8 @@
- if (REGNO (reg) == R0_REGNUM)
- {
- /* On thumb we have to use a write-back instruction. */
-- emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
-- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
-+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
-+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
- size = TARGET_ARM ? 16 : 0;
- }
- else
-@@ -9072,8 +8845,8 @@
- if (REGNO (reg) == R0_REGNUM)
- {
- /* On thumb we have to use a write-back instruction. */
-- emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
-- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
-+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
-+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
- size = TARGET_ARM ? 16 : 0;
- }
- else
-@@ -10666,87 +10439,6 @@
- ""
- )
-
--; Peepholes to spot possible load- and store-multiples, if the ordering is
--; reversed, check that the memory references aren't volatile.
--
--(define_peephole
-- [(set (match_operand:SI 0 "s_register_operand" "=rk")
-- (match_operand:SI 4 "memory_operand" "m"))
-- (set (match_operand:SI 1 "s_register_operand" "=rk")
-- (match_operand:SI 5 "memory_operand" "m"))
-- (set (match_operand:SI 2 "s_register_operand" "=rk")
-- (match_operand:SI 6 "memory_operand" "m"))
-- (set (match_operand:SI 3 "s_register_operand" "=rk")
-- (match_operand:SI 7 "memory_operand" "m"))]
-- "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
-- "*
-- return emit_ldm_seq (operands, 4);
-- "
--)
--
--(define_peephole
-- [(set (match_operand:SI 0 "s_register_operand" "=rk")
-- (match_operand:SI 3 "memory_operand" "m"))
-- (set (match_operand:SI 1 "s_register_operand" "=rk")
-- (match_operand:SI 4 "memory_operand" "m"))
-- (set (match_operand:SI 2 "s_register_operand" "=rk")
-- (match_operand:SI 5 "memory_operand" "m"))]
-- "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
-- "*
-- return emit_ldm_seq (operands, 3);
-- "
--)
--
--(define_peephole
-- [(set (match_operand:SI 0 "s_register_operand" "=rk")
-- (match_operand:SI 2 "memory_operand" "m"))
-- (set (match_operand:SI 1 "s_register_operand" "=rk")
-- (match_operand:SI 3 "memory_operand" "m"))]
-- "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
-- "*
-- return emit_ldm_seq (operands, 2);
-- "
--)
--
--(define_peephole
-- [(set (match_operand:SI 4 "memory_operand" "=m")
-- (match_operand:SI 0 "s_register_operand" "rk"))
-- (set (match_operand:SI 5 "memory_operand" "=m")
-- (match_operand:SI 1 "s_register_operand" "rk"))
-- (set (match_operand:SI 6 "memory_operand" "=m")
-- (match_operand:SI 2 "s_register_operand" "rk"))
-- (set (match_operand:SI 7 "memory_operand" "=m")
-- (match_operand:SI 3 "s_register_operand" "rk"))]
-- "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
-- "*
-- return emit_stm_seq (operands, 4);
-- "
--)
--
--(define_peephole
-- [(set (match_operand:SI 3 "memory_operand" "=m")
-- (match_operand:SI 0 "s_register_operand" "rk"))
-- (set (match_operand:SI 4 "memory_operand" "=m")
-- (match_operand:SI 1 "s_register_operand" "rk"))
-- (set (match_operand:SI 5 "memory_operand" "=m")
-- (match_operand:SI 2 "s_register_operand" "rk"))]
-- "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
-- "*
-- return emit_stm_seq (operands, 3);
-- "
--)
--
--(define_peephole
-- [(set (match_operand:SI 2 "memory_operand" "=m")
-- (match_operand:SI 0 "s_register_operand" "rk"))
-- (set (match_operand:SI 3 "memory_operand" "=m")
-- (match_operand:SI 1 "s_register_operand" "rk"))]
-- "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
-- "*
-- return emit_stm_seq (operands, 2);
-- "
--)
--
- (define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
-@@ -11549,6 +11241,8 @@
- "
- )
-
-+;; Load the load/store multiple patterns
-+(include "ldmstm.md")
- ;; Load the FPA co-processor patterns
- (include "fpa.md")
- ;; Load the Maverick co-processor patterns
-Index: gcc-4_5-branch/gcc/config/arm/ldmstm.md
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-4_5-branch/gcc/config/arm/ldmstm.md 2012-03-06 12:51:19.992547622 -0800
-@@ -0,0 +1,1191 @@
-+/* ARM ldm/stm instruction patterns. This file was automatically generated
-+ using arm-ldmstm.ml. Please do not edit manually.
-+
-+ Copyright (C) 2010 Free Software Foundation, Inc.
-+ Contributed by CodeSourcery.
-+
-+ This file is part of GCC.
-+
-+ GCC is free software; you can redistribute it and/or modify it
-+ under the terms of the GNU General Public License as published
-+ by the Free Software Foundation; either version 3, or (at your
-+ option) any later version.
-+
-+ GCC is distributed in the hope that it will be useful, but WITHOUT
-+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-+ License for more details.
-+
-+ You should have received a copy of the GNU General Public License and
-+ a copy of the GCC Runtime Library Exception along with this program;
-+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+(define_insn "*ldm4_ia"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 8))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 12))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(ia%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "load4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_ldm4_ia"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 8))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 12))))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(ia%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "load4")])
-+
-+(define_insn "*ldm4_ia_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 8))))
-+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 12))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
-+ "ldm%(ia%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "load4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_ldm4_ia_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=l")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 8))))
-+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 12))))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
-+ "ldm%(ia%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "load4")])
-+
-+(define_insn "*stm4_ia"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-+ "stm%(ia%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "store4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm4_ia_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
-+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
-+ "stm%(ia%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "store4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_stm4_ia_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=l")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
-+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
-+ "stm%(ia%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "store4")])
-+
-+(define_insn "*ldm4_ib"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int 4))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 8))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 12))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 16))))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(ib%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "load4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm4_ib_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 8))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 12))))
-+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 16))))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
-+ "ldm%(ib%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "load4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm4_ib"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
-+ "stm%(ib%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "store4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm4_ib_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16)))
-+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
-+ "stm%(ib%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "store4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm4_da"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int -12))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -8))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -4))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 1)))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(da%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "load4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm4_da_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -12))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -8))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -4))))
-+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
-+ "ldm%(da%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "load4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm4_da"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -12)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (match_dup 1))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
-+ "stm%(da%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "store4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm4_da_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
-+ "stm%(da%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "store4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm4_db"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int -16))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -12))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -8))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -4))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(db%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "load4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm4_db_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -16))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -12))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -8))))
-+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -4))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
-+ "ldm%(db%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "load4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm4_db"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -16)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -12)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-+ "stm%(db%)\t%1, {%2, %3, %4, %5}"
-+ [(set_attr "type" "store4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm4_db_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -16)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
-+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
-+ "stm%(db%)\t%1!, {%3, %4, %5, %6}"
-+ [(set_attr "type" "store4")
-+ (set_attr "predicable" "yes")])
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 4 "memory_operand" ""))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 5 "memory_operand" ""))
-+ (set (match_operand:SI 2 "s_register_operand" "")
-+ (match_operand:SI 6 "memory_operand" ""))
-+ (set (match_operand:SI 3 "s_register_operand" "")
-+ (match_operand:SI 7 "memory_operand" ""))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_ldm_seq (operands, 4, false))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 4 "memory_operand" ""))
-+ (parallel
-+ [(set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 5 "memory_operand" ""))
-+ (set (match_operand:SI 2 "s_register_operand" "")
-+ (match_operand:SI 6 "memory_operand" ""))
-+ (set (match_operand:SI 3 "s_register_operand" "")
-+ (match_operand:SI 7 "memory_operand" ""))])]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_ldm_seq (operands, 4, false))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 8 "const_int_operand" ""))
-+ (set (match_operand:SI 4 "memory_operand" "")
-+ (match_dup 0))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 9 "const_int_operand" ""))
-+ (set (match_operand:SI 5 "memory_operand" "")
-+ (match_dup 1))
-+ (set (match_operand:SI 2 "s_register_operand" "")
-+ (match_operand:SI 10 "const_int_operand" ""))
-+ (set (match_operand:SI 6 "memory_operand" "")
-+ (match_dup 2))
-+ (set (match_operand:SI 3 "s_register_operand" "")
-+ (match_operand:SI 11 "const_int_operand" ""))
-+ (set (match_operand:SI 7 "memory_operand" "")
-+ (match_dup 3))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_const_stm_seq (operands, 4))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 8 "const_int_operand" ""))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 9 "const_int_operand" ""))
-+ (set (match_operand:SI 2 "s_register_operand" "")
-+ (match_operand:SI 10 "const_int_operand" ""))
-+ (set (match_operand:SI 3 "s_register_operand" "")
-+ (match_operand:SI 11 "const_int_operand" ""))
-+ (set (match_operand:SI 4 "memory_operand" "")
-+ (match_dup 0))
-+ (set (match_operand:SI 5 "memory_operand" "")
-+ (match_dup 1))
-+ (set (match_operand:SI 6 "memory_operand" "")
-+ (match_dup 2))
-+ (set (match_operand:SI 7 "memory_operand" "")
-+ (match_dup 3))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_const_stm_seq (operands, 4))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 4 "memory_operand" "")
-+ (match_operand:SI 0 "s_register_operand" ""))
-+ (set (match_operand:SI 5 "memory_operand" "")
-+ (match_operand:SI 1 "s_register_operand" ""))
-+ (set (match_operand:SI 6 "memory_operand" "")
-+ (match_operand:SI 2 "s_register_operand" ""))
-+ (set (match_operand:SI 7 "memory_operand" "")
-+ (match_operand:SI 3 "s_register_operand" ""))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_stm_seq (operands, 4))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_insn "*ldm3_ia"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 8))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(ia%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "load3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_ldm3_ia"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 8))))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(ia%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "load3")])
-+
-+(define_insn "*ldm3_ia_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 8))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(ia%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "load3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_ldm3_ia_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=l")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 8))))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(ia%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "load3")])
-+
-+(define_insn "*stm3_ia"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-+ "stm%(ia%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "store3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm3_ia_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-+ "stm%(ia%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "store3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_stm3_ia_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=l")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
-+ "stm%(ia%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "store3")])
-+
-+(define_insn "*ldm3_ib"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int 4))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 8))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 12))))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(ib%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "load3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm3_ib_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 8))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 12))))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(ib%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "load3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm3_ib"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
-+ "stm%(ib%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "store3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm3_ib_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
-+ "stm%(ib%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "store3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm3_da"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int -8))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 1)))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(da%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "load3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm3_da_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -8))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -4))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(da%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "load3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm3_da"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -8)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (match_dup 1))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
-+ "stm%(da%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "store3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm3_da_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
-+ "stm%(da%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "store3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm3_db"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int -12))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -8))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -4))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(db%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "load3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm3_db_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -12))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -8))))
-+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -4))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-+ "ldm%(db%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "load3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm3_db"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -12)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-+ "stm%(db%)\t%1, {%2, %3, %4}"
-+ [(set_attr "type" "store3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm3_db_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
-+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
-+ "stm%(db%)\t%1!, {%3, %4, %5}"
-+ [(set_attr "type" "store3")
-+ (set_attr "predicable" "yes")])
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 3 "memory_operand" ""))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 4 "memory_operand" ""))
-+ (set (match_operand:SI 2 "s_register_operand" "")
-+ (match_operand:SI 5 "memory_operand" ""))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_ldm_seq (operands, 3, false))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 3 "memory_operand" ""))
-+ (parallel
-+ [(set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 4 "memory_operand" ""))
-+ (set (match_operand:SI 2 "s_register_operand" "")
-+ (match_operand:SI 5 "memory_operand" ""))])]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_ldm_seq (operands, 3, false))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 6 "const_int_operand" ""))
-+ (set (match_operand:SI 3 "memory_operand" "")
-+ (match_dup 0))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 7 "const_int_operand" ""))
-+ (set (match_operand:SI 4 "memory_operand" "")
-+ (match_dup 1))
-+ (set (match_operand:SI 2 "s_register_operand" "")
-+ (match_operand:SI 8 "const_int_operand" ""))
-+ (set (match_operand:SI 5 "memory_operand" "")
-+ (match_dup 2))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_const_stm_seq (operands, 3))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 6 "const_int_operand" ""))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 7 "const_int_operand" ""))
-+ (set (match_operand:SI 2 "s_register_operand" "")
-+ (match_operand:SI 8 "const_int_operand" ""))
-+ (set (match_operand:SI 3 "memory_operand" "")
-+ (match_dup 0))
-+ (set (match_operand:SI 4 "memory_operand" "")
-+ (match_dup 1))
-+ (set (match_operand:SI 5 "memory_operand" "")
-+ (match_dup 2))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_const_stm_seq (operands, 3))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 3 "memory_operand" "")
-+ (match_operand:SI 0 "s_register_operand" ""))
-+ (set (match_operand:SI 4 "memory_operand" "")
-+ (match_operand:SI 1 "s_register_operand" ""))
-+ (set (match_operand:SI 5 "memory_operand" "")
-+ (match_operand:SI 2 "s_register_operand" ""))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_stm_seq (operands, 3))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_insn "*ldm2_ia"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 4))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
-+ "ldm%(ia%)\t%1, {%2, %3}"
-+ [(set_attr "type" "load2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_ldm2_ia"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 4))))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 2"
-+ "ldm%(ia%)\t%1, {%2, %3}"
-+ [(set_attr "type" "load2")])
-+
-+(define_insn "*ldm2_ia_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(ia%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "load2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_ldm2_ia_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=l")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(ia%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "load2")])
-+
-+(define_insn "*stm2_ia"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
-+ "stm%(ia%)\t%1, {%2, %3}"
-+ [(set_attr "type" "store2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm2_ia_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-+ "stm%(ia%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "store2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*thumb_stm2_ia_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=l")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
-+ "stm%(ia%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "store2")])
-+
-+(define_insn "*ldm2_ib"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int 4))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int 8))))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
-+ "ldm%(ib%)\t%1, {%2, %3}"
-+ [(set_attr "type" "load2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm2_ib_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int 8))))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(ib%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "load2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm2_ib"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
-+ "stm%(ib%)\t%1, {%2, %3}"
-+ [(set_attr "type" "store2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm2_ib_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
-+ "stm%(ib%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "store2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm2_da"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int -4))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 1)))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
-+ "ldm%(da%)\t%1, {%2, %3}"
-+ [(set_attr "type" "load2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm2_da_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -4))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (match_dup 2)))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(da%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "load2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm2_da"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -4)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (match_dup 1))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
-+ "stm%(da%)\t%1, {%2, %3}"
-+ [(set_attr "type" "store2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm2_da_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (match_dup 2))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
-+ "stm%(da%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "store2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm2_db"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
-+ (const_int -8))))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 1)
-+ (const_int -4))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
-+ "ldm%(db%)\t%1, {%2, %3}"
-+ [(set_attr "type" "load2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*ldm2_db_update"
-+ [(match_parallel 0 "load_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
-+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -8))))
-+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
-+ (mem:SI (plus:SI (match_dup 2)
-+ (const_int -4))))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-+ "ldm%(db%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "load2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm2_db"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -8)))
-+ (match_operand:SI 2 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
-+ "stm%(db%)\t%1, {%2, %3}"
-+ [(set_attr "type" "store2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_insn "*stm2_db_update"
-+ [(match_parallel 0 "store_multiple_operation"
-+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
-+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
-+ (match_operand:SI 3 "arm_hard_register_operand" ""))
-+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
-+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
-+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
-+ "stm%(db%)\t%1!, {%3, %4}"
-+ [(set_attr "type" "store2")
-+ (set_attr "predicable" "yes")])
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 2 "memory_operand" ""))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 3 "memory_operand" ""))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_ldm_seq (operands, 2, false))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 4 "const_int_operand" ""))
-+ (set (match_operand:SI 2 "memory_operand" "")
-+ (match_dup 0))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 5 "const_int_operand" ""))
-+ (set (match_operand:SI 3 "memory_operand" "")
-+ (match_dup 1))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_const_stm_seq (operands, 2))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 4 "const_int_operand" ""))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 5 "const_int_operand" ""))
-+ (set (match_operand:SI 2 "memory_operand" "")
-+ (match_dup 0))
-+ (set (match_operand:SI 3 "memory_operand" "")
-+ (match_dup 1))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_const_stm_seq (operands, 2))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 2 "memory_operand" "")
-+ (match_operand:SI 0 "s_register_operand" ""))
-+ (set (match_operand:SI 3 "memory_operand" "")
-+ (match_operand:SI 1 "s_register_operand" ""))]
-+ ""
-+ [(const_int 0)]
-+{
-+ if (gen_stm_seq (operands, 2))
-+ DONE;
-+ else
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 2 "memory_operand" ""))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 3 "memory_operand" ""))
-+ (parallel
-+ [(set (match_operand:SI 4 "s_register_operand" "")
-+ (match_operator:SI 5 "commutative_binary_operator"
-+ [(match_operand:SI 6 "s_register_operand" "")
-+ (match_operand:SI 7 "s_register_operand" "")]))
-+ (clobber (reg:CC CC_REGNUM))])]
-+ "(((operands[6] == operands[0] && operands[7] == operands[1])
-+ || (operands[7] == operands[0] && operands[6] == operands[1]))
-+ && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[1]))"
-+ [(parallel
-+ [(set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))
-+ (clobber (reg:CC CC_REGNUM))])]
-+{
-+ if (!gen_ldm_seq (operands, 2, true))
-+ FAIL;
-+})
-+
-+(define_peephole2
-+ [(set (match_operand:SI 0 "s_register_operand" "")
-+ (match_operand:SI 2 "memory_operand" ""))
-+ (set (match_operand:SI 1 "s_register_operand" "")
-+ (match_operand:SI 3 "memory_operand" ""))
-+ (set (match_operand:SI 4 "s_register_operand" "")
-+ (match_operator:SI 5 "commutative_binary_operator"
-+ [(match_operand:SI 6 "s_register_operand" "")
-+ (match_operand:SI 7 "s_register_operand" "")]))]
-+ "(((operands[6] == operands[0] && operands[7] == operands[1])
-+ || (operands[7] == operands[0] && operands[6] == operands[1]))
-+ && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[1]))"
-+ [(set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))]
-+{
-+ if (!gen_ldm_seq (operands, 2, true))
-+ FAIL;
-+})
-+
-Index: gcc-4_5-branch/gcc/config/arm/predicates.md
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/arm/predicates.md 2012-03-06 12:47:54.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/arm/predicates.md 2012-03-06 12:51:19.992547622 -0800
-@@ -211,6 +211,11 @@
- (and (match_code "ior,xor,and")
- (match_test "mode == GET_MODE (op)")))
-
-+;; True for commutative operators
-+(define_special_predicate "commutative_binary_operator"
-+ (and (match_code "ior,xor,and,plus")
-+ (match_test "mode == GET_MODE (op)")))
-+
- ;; True for shift operators.
- (define_special_predicate "shift_operator"
- (and (ior (ior (and (match_code "mult")
-@@ -334,16 +339,20 @@
- (match_code "parallel")
- {
- HOST_WIDE_INT count = XVECLEN (op, 0);
-- int dest_regno;
-+ unsigned dest_regno;
- rtx src_addr;
- HOST_WIDE_INT i = 1, base = 0;
-+ HOST_WIDE_INT offset = 0;
- rtx elt;
-+ bool addr_reg_loaded = false;
-+ bool update = false;
-
- if (low_irq_latency)
- return false;
-
- if (count <= 1
-- || GET_CODE (XVECEXP (op, 0, 0)) != SET)
-+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
-+ || !REG_P (SET_DEST (XVECEXP (op, 0, 0))))
- return false;
-
- /* Check to see if this might be a write-back. */
-@@ -351,6 +360,7 @@
- {
- i++;
- base = 1;
-+ update = true;
-
- /* Now check it more carefully. */
- if (GET_CODE (SET_DEST (elt)) != REG
-@@ -369,6 +379,15 @@
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
- src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
-+ if (GET_CODE (src_addr) == PLUS)
-+ {
-+ if (GET_CODE (XEXP (src_addr, 1)) != CONST_INT)
-+ return false;
-+ offset = INTVAL (XEXP (src_addr, 1));
-+ src_addr = XEXP (src_addr, 0);
-+ }
-+ if (!REG_P (src_addr))
-+ return false;
-
- for (; i < count; i++)
- {
-@@ -377,16 +396,28 @@
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != SImode
-- || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
-+ || REGNO (SET_DEST (elt)) <= dest_regno
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != SImode
-- || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
-- || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
-- || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
-- || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4)
-+ || ((GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
-+ || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
-+ || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
-+ || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != offset + (i - base) * 4)
-+ && (!REG_P (XEXP (SET_SRC (elt), 0))
-+ || offset + (i - base) * 4 != 0)))
- return false;
-+ dest_regno = REGNO (SET_DEST (elt));
-+ if (dest_regno == REGNO (src_addr))
-+ addr_reg_loaded = true;
- }
--
-+ /* For Thumb, we only have updating instructions. If the pattern does
-+ not describe an update, it must be because the address register is
-+ in the list of loaded registers - on the hardware, this has the effect
-+ of overriding the update. */
-+ if (update && addr_reg_loaded)
-+ return false;
-+ if (TARGET_THUMB1)
-+ return update || addr_reg_loaded;
- return true;
- })
-
-@@ -394,9 +425,9 @@
- (match_code "parallel")
- {
- HOST_WIDE_INT count = XVECLEN (op, 0);
-- int src_regno;
-+ unsigned src_regno;
- rtx dest_addr;
-- HOST_WIDE_INT i = 1, base = 0;
-+ HOST_WIDE_INT i = 1, base = 0, offset = 0;
- rtx elt;
-
- if (low_irq_latency)
-@@ -430,6 +461,16 @@
- src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
- dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
-
-+ if (GET_CODE (dest_addr) == PLUS)
-+ {
-+ if (GET_CODE (XEXP (dest_addr, 1)) != CONST_INT)
-+ return false;
-+ offset = INTVAL (XEXP (dest_addr, 1));
-+ dest_addr = XEXP (dest_addr, 0);
-+ }
-+ if (!REG_P (dest_addr))
-+ return false;
-+
- for (; i < count; i++)
- {
- elt = XVECEXP (op, 0, i);
-@@ -437,14 +478,17 @@
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != SImode
-- || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
-+ || REGNO (SET_SRC (elt)) <= src_regno
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != SImode
-- || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
-- || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
-- || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
-- || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
-+ || ((GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
-+ || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
-+ || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
-+ || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != offset + (i - base) * 4)
-+ && (!REG_P (XEXP (SET_DEST (elt), 0))
-+ || offset + (i - base) * 4 != 0)))
- return false;
-+ src_regno = REGNO (SET_SRC (elt));
- }
-
- return true;
-Index: gcc-4_5-branch/gcc/config/i386/i386.md
-===================================================================
---- gcc-4_5-branch.orig/gcc/config/i386/i386.md 2012-03-06 12:47:55.000000000 -0800
-+++ gcc-4_5-branch/gcc/config/i386/i386.md 2012-03-06 12:51:19.996547605 -0800
-@@ -4960,6 +4960,7 @@
- (set (match_operand:SSEMODEI24 2 "register_operand" "")
- (fix:SSEMODEI24 (match_dup 0)))]
- "TARGET_SHORTEN_X87_SSE
-+ && !(TARGET_AVOID_VECTOR_DECODE && optimize_insn_for_speed_p ())
- && peep2_reg_dead_p (2, operands[0])"
- [(set (match_dup 2) (fix:SSEMODEI24 (match_dup 1)))]
- "")
-@@ -20089,15 +20090,14 @@
- ;; leal (%edx,%eax,4), %eax
-
- (define_peephole2
-- [(parallel [(set (match_operand 0 "register_operand" "")
-+ [(match_scratch:P 5 "r")
-+ (parallel [(set (match_operand 0 "register_operand" "")
- (ashift (match_operand 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")))
- (clobber (reg:CC FLAGS_REG))])
-- (set (match_operand 3 "register_operand")
-- (match_operand 4 "x86_64_general_operand" ""))
-- (parallel [(set (match_operand 5 "register_operand" "")
-- (plus (match_operand 6 "register_operand" "")
-- (match_operand 7 "register_operand" "")))
-+ (parallel [(set (match_operand 3 "register_operand" "")
-+ (plus (match_dup 0)
-+ (match_operand 4 "x86_64_general_operand" "")))
- (clobber (reg:CC FLAGS_REG))])]
- "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
- /* Validate MODE for lea. */
-@@ -20106,31 +20106,27 @@
- || GET_MODE (operands[0]) == HImode))
- || GET_MODE (operands[0]) == SImode
- || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
-+ && (rtx_equal_p (operands[0], operands[3])
-+ || peep2_reg_dead_p (2, operands[0]))
- /* We reorder load and the shift. */
-- && !rtx_equal_p (operands[1], operands[3])
-- && !reg_overlap_mentioned_p (operands[0], operands[4])
-- /* Last PLUS must consist of operand 0 and 3. */
-- && !rtx_equal_p (operands[0], operands[3])
-- && (rtx_equal_p (operands[3], operands[6])
-- || rtx_equal_p (operands[3], operands[7]))
-- && (rtx_equal_p (operands[0], operands[6])
-- || rtx_equal_p (operands[0], operands[7]))
-- /* The intermediate operand 0 must die or be same as output. */
-- && (rtx_equal_p (operands[0], operands[5])
-- || peep2_reg_dead_p (3, operands[0]))"
-- [(set (match_dup 3) (match_dup 4))
-+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
-+ [(set (match_dup 5) (match_dup 4))
- (set (match_dup 0) (match_dup 1))]
- {
-- enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
-+ enum machine_mode mode = GET_MODE (operands[1]) == DImode ? DImode : SImode;
- int scale = 1 << INTVAL (operands[2]);
- rtx index = gen_lowpart (Pmode, operands[1]);
-- rtx base = gen_lowpart (Pmode, operands[3]);
-- rtx dest = gen_lowpart (mode, operands[5]);
-+ rtx base = gen_lowpart (Pmode, operands[5]);
-+ rtx dest = gen_lowpart (mode, operands[3]);
-
- operands[1] = gen_rtx_PLUS (Pmode, base,
- gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
-+ operands[5] = base;
- if (mode != Pmode)
-- operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
-+ {
-+ operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
-+ operands[5] = gen_rtx_SUBREG (mode, operands[5], 0);
-+ }
- operands[0] = dest;
- })
-
-Index: gcc-4_5-branch/gcc/genoutput.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/genoutput.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/genoutput.c 2012-03-06 12:51:20.000547582 -0800
-@@ -266,6 +266,8 @@
-
- printf (" %d,\n", d->strict_low);
-
-+ printf (" %d,\n", d->constraint == NULL ? 1 : 0);
-+
- printf (" %d\n", d->eliminable);
-
- printf(" },\n");
-Index: gcc-4_5-branch/gcc/genrecog.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/genrecog.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/genrecog.c 2012-03-06 12:51:20.000547582 -0800
-@@ -1782,20 +1782,11 @@
- int odepth = strlen (oldpos);
- int ndepth = strlen (newpos);
- int depth;
-- int old_has_insn, new_has_insn;
-
- /* Pop up as many levels as necessary. */
- for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
- continue;
-
-- /* Hunt for the last [A-Z] in both strings. */
-- for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
-- if (ISUPPER (oldpos[old_has_insn]))
-- break;
-- for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
-- if (ISUPPER (newpos[new_has_insn]))
-- break;
--
- /* Go down to desired level. */
- while (depth < ndepth)
- {
-Index: gcc-4_5-branch/gcc/recog.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/recog.c 2012-03-06 12:47:48.000000000 -0800
-+++ gcc-4_5-branch/gcc/recog.c 2012-03-06 13:04:05.780584592 -0800
-@@ -2082,6 +2082,7 @@
- recog_data.operand_loc,
- recog_data.constraints,
- recog_data.operand_mode, NULL);
-+ memset (recog_data.is_operator, 0, sizeof recog_data.is_operator);
- if (noperands > 0)
- {
- const char *p = recog_data.constraints[0];
-@@ -2111,6 +2112,7 @@
- for (i = 0; i < noperands; i++)
- {
- recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
-+ recog_data.is_operator[i] = insn_data[icode].operand[i].is_operator;
- recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
- /* VOIDmode match_operands gets mode from their real operand. */
- if (recog_data.operand_mode[i] == VOIDmode)
-@@ -2909,6 +2911,10 @@
-
- static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
- static int peep2_current;
-+
-+static bool peep2_do_rebuild_jump_labels;
-+static bool peep2_do_cleanup_cfg;
-+
- /* The number of instructions available to match a peep2. */
- int peep2_current_count;
-
-@@ -2917,6 +2923,16 @@
- DF_LIVE_OUT for the block. */
- #define PEEP2_EOB pc_rtx
-
-+/* Wrap N to fit into the peep2_insn_data buffer. */
-+
-+static int
-+peep2_buf_position (int n)
-+{
-+ if (n >= MAX_INSNS_PER_PEEP2 + 1)
-+ n -= MAX_INSNS_PER_PEEP2 + 1;
-+ return n;
-+}
-+
- /* Return the Nth non-note insn after `current', or return NULL_RTX if it
- does not exist. Used by the recognizer to find the next insn to match
- in a multi-insn pattern. */
-@@ -2926,9 +2942,7 @@
- {
- gcc_assert (n <= peep2_current_count);
-
-- n += peep2_current;
-- if (n >= MAX_INSNS_PER_PEEP2 + 1)
-- n -= MAX_INSNS_PER_PEEP2 + 1;
-+ n = peep2_buf_position (peep2_current + n);
-
- return peep2_insn_data[n].insn;
- }
-@@ -2941,9 +2955,7 @@
- {
- gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
-
-- ofs += peep2_current;
-- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
-- ofs -= MAX_INSNS_PER_PEEP2 + 1;
-+ ofs = peep2_buf_position (peep2_current + ofs);
-
- gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
-
-@@ -2959,9 +2971,7 @@
-
- gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
-
-- ofs += peep2_current;
-- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
-- ofs -= MAX_INSNS_PER_PEEP2 + 1;
-+ ofs = peep2_buf_position (peep2_current + ofs);
-
- gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
-
-@@ -2997,12 +3007,8 @@
- gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
- gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
-
-- from += peep2_current;
-- if (from >= MAX_INSNS_PER_PEEP2 + 1)
-- from -= MAX_INSNS_PER_PEEP2 + 1;
-- to += peep2_current;
-- if (to >= MAX_INSNS_PER_PEEP2 + 1)
-- to -= MAX_INSNS_PER_PEEP2 + 1;
-+ from = peep2_buf_position (peep2_current + from);
-+ to = peep2_buf_position (peep2_current + to);
-
- gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
- REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
-@@ -3016,8 +3022,7 @@
- *def_rec; def_rec++)
- SET_HARD_REG_BIT (live, DF_REF_REGNO (*def_rec));
-
-- if (++from >= MAX_INSNS_PER_PEEP2 + 1)
-- from = 0;
-+ from = peep2_buf_position (from + 1);
- }
-
- cl = (class_str[0] == 'r' ? GENERAL_REGS
-@@ -3107,19 +3112,234 @@
- COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
- }
-
-+/* While scanning basic block BB, we found a match of length MATCH_LEN,
-+ starting at INSN. Perform the replacement, removing the old insns and
-+ replacing them with ATTEMPT. Returns the last insn emitted. */
-+
-+static rtx
-+peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt)
-+{
-+ int i;
-+ rtx last, note, before_try, x;
-+ bool was_call = false;
-+
-+ /* If we are splitting a CALL_INSN, look for the CALL_INSN
-+ in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
-+ cfg-related call notes. */
-+ for (i = 0; i <= match_len; ++i)
-+ {
-+ int j;
-+ rtx old_insn, new_insn, note;
-+
-+ j = peep2_buf_position (peep2_current + i);
-+ old_insn = peep2_insn_data[j].insn;
-+ if (!CALL_P (old_insn))
-+ continue;
-+ was_call = true;
-+
-+ new_insn = attempt;
-+ while (new_insn != NULL_RTX)
-+ {
-+ if (CALL_P (new_insn))
-+ break;
-+ new_insn = NEXT_INSN (new_insn);
-+ }
-+
-+ gcc_assert (new_insn != NULL_RTX);
-+
-+ CALL_INSN_FUNCTION_USAGE (new_insn)
-+ = CALL_INSN_FUNCTION_USAGE (old_insn);
-+
-+ for (note = REG_NOTES (old_insn);
-+ note;
-+ note = XEXP (note, 1))
-+ switch (REG_NOTE_KIND (note))
-+ {
-+ case REG_NORETURN:
-+ case REG_SETJMP:
-+ add_reg_note (new_insn, REG_NOTE_KIND (note),
-+ XEXP (note, 0));
-+ break;
-+ default:
-+ /* Discard all other reg notes. */
-+ break;
-+ }
-+
-+ /* Croak if there is another call in the sequence. */
-+ while (++i <= match_len)
-+ {
-+ j = peep2_buf_position (peep2_current + i);
-+ old_insn = peep2_insn_data[j].insn;
-+ gcc_assert (!CALL_P (old_insn));
-+ }
-+ break;
-+ }
-+
-+ i = peep2_buf_position (peep2_current + match_len);
-+
-+ note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX);
-+
-+ /* Replace the old sequence with the new. */
-+ last = emit_insn_after_setloc (attempt,
-+ peep2_insn_data[i].insn,
-+ INSN_LOCATOR (peep2_insn_data[i].insn));
-+ before_try = PREV_INSN (insn);
-+ delete_insn_chain (insn, peep2_insn_data[i].insn, false);
-+
-+ /* Re-insert the EH_REGION notes. */
-+ if (note || (was_call && nonlocal_goto_handler_labels))
-+ {
-+ edge eh_edge;
-+ edge_iterator ei;
-+
-+ FOR_EACH_EDGE (eh_edge, ei, bb->succs)
-+ if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
-+ break;
-+
-+ if (note)
-+ copy_reg_eh_region_note_backward (note, last, before_try);
-+
-+ if (eh_edge)
-+ for (x = last; x != before_try; x = PREV_INSN (x))
-+ if (x != BB_END (bb)
-+ && (can_throw_internal (x)
-+ || can_nonlocal_goto (x)))
-+ {
-+ edge nfte, nehe;
-+ int flags;
-+
-+ nfte = split_block (bb, x);
-+ flags = (eh_edge->flags
-+ & (EDGE_EH | EDGE_ABNORMAL));
-+ if (CALL_P (x))
-+ flags |= EDGE_ABNORMAL_CALL;
-+ nehe = make_edge (nfte->src, eh_edge->dest,
-+ flags);
-+
-+ nehe->probability = eh_edge->probability;
-+ nfte->probability
-+ = REG_BR_PROB_BASE - nehe->probability;
-+
-+ peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
-+ bb = nfte->src;
-+ eh_edge = nehe;
-+ }
-+
-+ /* Converting possibly trapping insn to non-trapping is
-+ possible. Zap dummy outgoing edges. */
-+ peep2_do_cleanup_cfg |= purge_dead_edges (bb);
-+ }
-+
-+ /* If we generated a jump instruction, it won't have
-+ JUMP_LABEL set. Recompute after we're done. */
-+ for (x = last; x != before_try; x = PREV_INSN (x))
-+ if (JUMP_P (x))
-+ {
-+ peep2_do_rebuild_jump_labels = true;
-+ break;
-+ }
-+
-+ return last;
-+}
-+
-+/* After performing a replacement in basic block BB, fix up the life
-+ information in our buffer. LAST is the last of the insns that we
-+ emitted as a replacement. PREV is the insn before the start of
-+ the replacement. MATCH_LEN is the number of instructions that were
-+ matched, and which now need to be replaced in the buffer. */
-+
-+static void
-+peep2_update_life (basic_block bb, int match_len, rtx last, rtx prev)
-+{
-+ int i = peep2_buf_position (peep2_current + match_len + 1);
-+ rtx x;
-+ regset_head live;
-+
-+ INIT_REG_SET (&live);
-+ COPY_REG_SET (&live, peep2_insn_data[i].live_before);
-+
-+ gcc_assert (peep2_current_count >= match_len + 1);
-+ peep2_current_count -= match_len + 1;
-+
-+ x = last;
-+ do
-+ {
-+ if (INSN_P (x))
-+ {
-+ df_insn_rescan (x);
-+ if (peep2_current_count < MAX_INSNS_PER_PEEP2)
-+ {
-+ peep2_current_count++;
-+ if (--i < 0)
-+ i = MAX_INSNS_PER_PEEP2;
-+ peep2_insn_data[i].insn = x;
-+ df_simulate_one_insn_backwards (bb, x, &live);
-+ COPY_REG_SET (peep2_insn_data[i].live_before, &live);
-+ }
-+ }
-+ x = PREV_INSN (x);
-+ }
-+ while (x != prev);
-+ CLEAR_REG_SET (&live);
-+
-+ peep2_current = i;
-+}
-+
-+/* Add INSN, which is in BB, at the end of the peep2 insn buffer if possible.
-+ Return true if we added it, false otherwise. The caller will try to match
-+ peepholes against the buffer if we return false; otherwise it will try to
-+ add more instructions to the buffer. */
-+
-+static bool
-+peep2_fill_buffer (basic_block bb, rtx insn, regset live)
-+{
-+ int pos;
-+
-+ /* Once we have filled the maximum number of insns the buffer can hold,
-+ allow the caller to match the insns against peepholes. We wait until
-+ the buffer is full in case the target has similar peepholes of different
-+ length; we always want to match the longest if possible. */
-+ if (peep2_current_count == MAX_INSNS_PER_PEEP2)
-+ return false;
-+
-+ /* If an insn has RTX_FRAME_RELATED_P set, peephole substitution would lose
-+ the REG_FRAME_RELATED_EXPR that is attached. */
-+ if (RTX_FRAME_RELATED_P (insn))
-+ {
-+ /* Let the buffer drain first. */
-+ if (peep2_current_count > 0)
-+ return false;
-+ /* Step over the insn then return true without adding the insn
-+ to the buffer; this will cause us to process the next
-+ insn. */
-+ df_simulate_one_insn_forwards (bb, insn, live);
-+ return true;
-+ }
-+
-+ pos = peep2_buf_position (peep2_current + peep2_current_count);
-+ peep2_insn_data[pos].insn = insn;
-+ COPY_REG_SET (peep2_insn_data[pos].live_before, live);
-+ peep2_current_count++;
-+
-+ df_simulate_one_insn_forwards (bb, insn, live);
-+ return true;
-+}
-+
- /* Perform the peephole2 optimization pass. */
-
- static void
- peephole2_optimize (void)
- {
-- rtx insn, prev;
-+ rtx insn;
- bitmap live;
- int i;
- basic_block bb;
-- bool do_cleanup_cfg = false;
-- bool do_rebuild_jump_labels = false;
-+
-+ peep2_do_cleanup_cfg = false;
-+ peep2_do_rebuild_jump_labels = false;
-
- df_set_flags (DF_LR_RUN_DCE);
-+ df_note_add_problem ();
- df_analyze ();
-
- /* Initialize the regsets we're going to use. */
-@@ -3129,214 +3349,59 @@
-
- FOR_EACH_BB_REVERSE (bb)
- {
-+ bool past_end = false;
-+ int pos;
-+
- rtl_profile_for_bb (bb);
-
- /* Start up propagation. */
-- bitmap_copy (live, DF_LR_OUT (bb));
-- df_simulate_initialize_backwards (bb, live);
-+ bitmap_copy (live, DF_LR_IN (bb));
-+ df_simulate_initialize_forwards (bb, live);
- peep2_reinit_state (live);
-
-- for (insn = BB_END (bb); ; insn = prev)
-+ insn = BB_HEAD (bb);
-+ for (;;)
- {
-- prev = PREV_INSN (insn);
-- if (NONDEBUG_INSN_P (insn))
-- {
-- rtx attempt, before_try, x;
-- int match_len;
-- rtx note;
-- bool was_call = false;
--
-- /* Record this insn. */
-- if (--peep2_current < 0)
-- peep2_current = MAX_INSNS_PER_PEEP2;
-- if (peep2_current_count < MAX_INSNS_PER_PEEP2
-- && peep2_insn_data[peep2_current].insn == NULL_RTX)
-- peep2_current_count++;
-- peep2_insn_data[peep2_current].insn = insn;
-- df_simulate_one_insn_backwards (bb, insn, live);
-- COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
-+ rtx attempt, head;
-+ int match_len;
-
-- if (RTX_FRAME_RELATED_P (insn))
-- {
-- /* If an insn has RTX_FRAME_RELATED_P set, peephole
-- substitution would lose the
-- REG_FRAME_RELATED_EXPR that is attached. */
-- peep2_reinit_state (live);
-- attempt = NULL;
-- }
-- else
-- /* Match the peephole. */
-- attempt = peephole2_insns (PATTERN (insn), insn, &match_len);
--
-- if (attempt != NULL)
-- {
-- /* If we are splitting a CALL_INSN, look for the CALL_INSN
-- in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
-- cfg-related call notes. */
-- for (i = 0; i <= match_len; ++i)
-- {
-- int j;
-- rtx old_insn, new_insn, note;
--
-- j = i + peep2_current;
-- if (j >= MAX_INSNS_PER_PEEP2 + 1)
-- j -= MAX_INSNS_PER_PEEP2 + 1;
-- old_insn = peep2_insn_data[j].insn;
-- if (!CALL_P (old_insn))
-- continue;
-- was_call = true;
--
-- new_insn = attempt;
-- while (new_insn != NULL_RTX)
-- {
-- if (CALL_P (new_insn))
-- break;
-- new_insn = NEXT_INSN (new_insn);
-- }
--
-- gcc_assert (new_insn != NULL_RTX);
--
-- CALL_INSN_FUNCTION_USAGE (new_insn)
-- = CALL_INSN_FUNCTION_USAGE (old_insn);
--
-- for (note = REG_NOTES (old_insn);
-- note;
-- note = XEXP (note, 1))
-- switch (REG_NOTE_KIND (note))
-- {
-- case REG_NORETURN:
-- case REG_SETJMP:
-- add_reg_note (new_insn, REG_NOTE_KIND (note),
-- XEXP (note, 0));
-- break;
-- default:
-- /* Discard all other reg notes. */
-- break;
-- }
--
-- /* Croak if there is another call in the sequence. */
-- while (++i <= match_len)
-- {
-- j = i + peep2_current;
-- if (j >= MAX_INSNS_PER_PEEP2 + 1)
-- j -= MAX_INSNS_PER_PEEP2 + 1;
-- old_insn = peep2_insn_data[j].insn;
-- gcc_assert (!CALL_P (old_insn));
-- }
-- break;
-- }
--
-- i = match_len + peep2_current;
-- if (i >= MAX_INSNS_PER_PEEP2 + 1)
-- i -= MAX_INSNS_PER_PEEP2 + 1;
--
-- note = find_reg_note (peep2_insn_data[i].insn,
-- REG_EH_REGION, NULL_RTX);
--
-- /* Replace the old sequence with the new. */
-- attempt = emit_insn_after_setloc (attempt,
-- peep2_insn_data[i].insn,
-- INSN_LOCATOR (peep2_insn_data[i].insn));
-- before_try = PREV_INSN (insn);
-- delete_insn_chain (insn, peep2_insn_data[i].insn, false);
--
-- /* Re-insert the EH_REGION notes. */
-- if (note || (was_call && nonlocal_goto_handler_labels))
-- {
-- edge eh_edge;
-- edge_iterator ei;
--
-- FOR_EACH_EDGE (eh_edge, ei, bb->succs)
-- if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
-- break;
--
-- if (note)
-- copy_reg_eh_region_note_backward (note, attempt,
-- before_try);
--
-- if (eh_edge)
-- for (x = attempt ; x != before_try ; x = PREV_INSN (x))
-- if (x != BB_END (bb)
-- && (can_throw_internal (x)
-- || can_nonlocal_goto (x)))
-- {
-- edge nfte, nehe;
-- int flags;
--
-- nfte = split_block (bb, x);
-- flags = (eh_edge->flags
-- & (EDGE_EH | EDGE_ABNORMAL));
-- if (CALL_P (x))
-- flags |= EDGE_ABNORMAL_CALL;
-- nehe = make_edge (nfte->src, eh_edge->dest,
-- flags);
--
-- nehe->probability = eh_edge->probability;
-- nfte->probability
-- = REG_BR_PROB_BASE - nehe->probability;
--
-- do_cleanup_cfg |= purge_dead_edges (nfte->dest);
-- bb = nfte->src;
-- eh_edge = nehe;
-- }
--
-- /* Converting possibly trapping insn to non-trapping is
-- possible. Zap dummy outgoing edges. */
-- do_cleanup_cfg |= purge_dead_edges (bb);
-- }
-+ if (!past_end && !NONDEBUG_INSN_P (insn))
-+ {
-+ next_insn:
-+ insn = NEXT_INSN (insn);
-+ if (insn == NEXT_INSN (BB_END (bb)))
-+ past_end = true;
-+ continue;
-+ }
-+ if (!past_end && peep2_fill_buffer (bb, insn, live))
-+ goto next_insn;
-
-- if (targetm.have_conditional_execution ())
-- {
-- for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
-- peep2_insn_data[i].insn = NULL_RTX;
-- peep2_insn_data[peep2_current].insn = PEEP2_EOB;
-- peep2_current_count = 0;
-- }
-- else
-- {
-- /* Back up lifetime information past the end of the
-- newly created sequence. */
-- if (++i >= MAX_INSNS_PER_PEEP2 + 1)
-- i = 0;
-- bitmap_copy (live, peep2_insn_data[i].live_before);
--
-- /* Update life information for the new sequence. */
-- x = attempt;
-- do
-- {
-- if (INSN_P (x))
-- {
-- if (--i < 0)
-- i = MAX_INSNS_PER_PEEP2;
-- if (peep2_current_count < MAX_INSNS_PER_PEEP2
-- && peep2_insn_data[i].insn == NULL_RTX)
-- peep2_current_count++;
-- peep2_insn_data[i].insn = x;
-- df_insn_rescan (x);
-- df_simulate_one_insn_backwards (bb, x, live);
-- bitmap_copy (peep2_insn_data[i].live_before,
-- live);
-- }
-- x = PREV_INSN (x);
-- }
-- while (x != prev);
-+ /* If we did not fill an empty buffer, it signals the end of the
-+ block. */
-+ if (peep2_current_count == 0)
-+ break;
-
-- peep2_current = i;
-- }
-+ /* The buffer filled to the current maximum, so try to match. */
-
-- /* If we generated a jump instruction, it won't have
-- JUMP_LABEL set. Recompute after we're done. */
-- for (x = attempt; x != before_try; x = PREV_INSN (x))
-- if (JUMP_P (x))
-- {
-- do_rebuild_jump_labels = true;
-- break;
-- }
-- }
-+ pos = peep2_buf_position (peep2_current + peep2_current_count);
-+ peep2_insn_data[pos].insn = PEEP2_EOB;
-+ COPY_REG_SET (peep2_insn_data[pos].live_before, live);
-+
-+ /* Match the peephole. */
-+ head = peep2_insn_data[peep2_current].insn;
-+ attempt = peephole2_insns (PATTERN (head), head, &match_len);
-+ if (attempt != NULL)
-+ {
-+ rtx last;
-+ last = peep2_attempt (bb, head, match_len, attempt);
-+ peep2_update_life (bb, match_len, last, PREV_INSN (attempt));
-+ }
-+ else
-+ {
-+ /* If no match, advance the buffer by one insn. */
-+ peep2_current = peep2_buf_position (peep2_current + 1);
-+ peep2_current_count--;
- }
--
-- if (insn == BB_HEAD (bb))
-- break;
- }
- }
-
-@@ -3344,7 +3409,7 @@
- for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
- BITMAP_FREE (peep2_insn_data[i].live_before);
- BITMAP_FREE (live);
-- if (do_rebuild_jump_labels)
-+ if (peep2_do_rebuild_jump_labels)
- rebuild_jump_labels (get_insns ());
- }
- #endif /* HAVE_peephole2 */
-Index: gcc-4_5-branch/gcc/recog.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/recog.h 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/recog.h 2012-03-06 12:51:20.000547582 -0800
-@@ -194,6 +194,9 @@
- /* Gives the constraint string for operand N. */
- const char *constraints[MAX_RECOG_OPERANDS];
-
-+ /* Nonzero if operand N is a match_operator or a match_parallel. */
-+ char is_operator[MAX_RECOG_OPERANDS];
-+
- /* Gives the mode of operand N. */
- enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
-
-@@ -260,6 +263,8 @@
-
- const char strict_low;
-
-+ const char is_operator;
-+
- const char eliminable;
- };
-
-Index: gcc-4_5-branch/gcc/reload.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/reload.c 2012-03-06 11:53:32.000000000 -0800
-+++ gcc-4_5-branch/gcc/reload.c 2012-03-06 12:51:20.004547561 -0800
-@@ -3631,7 +3631,7 @@
- || modified[j] != RELOAD_WRITE)
- && j != i
- /* Ignore things like match_operator operands. */
-- && *recog_data.constraints[j] != 0
-+ && !recog_data.is_operator[j]
- /* Don't count an input operand that is constrained to match
- the early clobber operand. */
- && ! (this_alternative_matches[j] == i