summaryrefslogtreecommitdiffstats
path: root/recipes-devtools
diff options
context:
space:
mode:
authorKoen Kooi <koen@dominion.thruhere.net>2011-01-13 13:39:44 +0100
committerKoen Kooi <koen@dominion.thruhere.net>2011-01-13 13:39:44 +0100
commit94237e310fd27f9f66699c07311ff0ae17f8ee20 (patch)
tree173f6eb82befe60a06d34240e89a26f364f371b5 /recipes-devtools
parent9411e8a9e0428b6a1ec43ae086c1a5e6366a597e (diff)
downloadmeta-openembedded-94237e310fd27f9f66699c07311ff0ae17f8ee20.tar.gz
gcc 4.5: sync with OE
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
Diffstat (limited to 'recipes-devtools')
-rw-r--r--recipes-devtools/gcc/foo191
-rw-r--r--recipes-devtools/gcc/gcc-4.5.inc16
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99414.patch36
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99448.patch147
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99449.patch34
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99450.patch104
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99451.patch45
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99452.patch201
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99453.patch72
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99454.patch46
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99455.patch (renamed from recipes-devtools/gcc/gcc-4.5/gcc-arm-qihi-split-PR46883.patch)39
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99456.patch3163
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99457.patch4236
-rw-r--r--recipes-devtools/gcc/gcc-4.5/sh4-multilib.patch25
-rw-r--r--recipes-devtools/gcc/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch33
15 files changed, 8335 insertions, 53 deletions
diff --git a/recipes-devtools/gcc/foo b/recipes-devtools/gcc/foo
new file mode 100644
index 000000000..3fe24131e
--- /dev/null
+++ b/recipes-devtools/gcc/foo
@@ -0,0 +1,191 @@
1From f13cb20ed19c41b9ff85ef1c9ec0883a21d1d5bf Mon Sep 17 00:00:00 2001
2From: Kevin Tian <kevin.tian@intel.com>
3Date: Thu, 30 Dec 2010 04:36:50 +0000
4Subject: gcc-4.5.1: make c++ include path relative to "--sysroot"
5
6So far c++ include path is not relative to "--sysroot", which brings
7trouble if we want to use the toolchain in a new environment where
8the original build directory generating that toolchain is not
9available. It's firstly exposed in multiple SDK sysroots support, and
10then in the case when sstate packages are used, where c++ standard
11headers are missing because gcc tries to search original build dir.
12
13This patch makes c++ include path now relative to "--sysroot", and
14then once "--sysroot" is assigned correctly in new environment, c++
15include paths can be searched as expected.
16
17Signed-off-by: Kevin Tian <kevin.tian@intel.com>
18---
19diff --git a/meta/recipes-devtools/gcc/gcc-4.5.1.inc b/meta/recipes-devtools/gcc/gcc-4.5.1.inc
20index 3edc4d4..1786d8a 100644
21--- a/meta/recipes-devtools/gcc/gcc-4.5.1.inc
22+++ b/meta/recipes-devtools/gcc/gcc-4.5.1.inc
23@@ -54,6 +54,7 @@ SRC_URI = "${GNU_MIRROR}/gcc/gcc-${PV}/gcc-${PV}.tar.bz2 \
24 file://optional_libstdc.patch \
25 file://disable_relax_pic_calls_flag.patch \
26 file://gcc-poison-parameters.patch \
27+ file://GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch \
28 "
29
30 SRC_URI_append_sh3 = " file://sh3-installfix-fixheaders.patch;patch=1 "
31diff --git a/meta/recipes-devtools/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch b/meta/recipes-devtools/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch
32new file mode 100644
33index 0000000..9ae01c3
34--- a/dev/null
35+++ b/meta/recipes-devtools/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch
36@@ -0,0 +1,33 @@
37+# by default c++ include directories are not relative to "--sysroot"
38+# which brings one trouble when using the toolchain in an environment
39+# where the build directory generating that toolchain doesn't exist,
40+# e.g. in sstate, machine specific sysroot and relocatable SDK
41+# toolchain. This patch now enables c++ include paths under sysroot.
42+# This way it's enough as long as "--sysroot" is correctly enabled
43+# in the new environment.
44+#
45+# Signed-off-by Kevin Tian <kevin.tian@intel.com>, 2010-12-30
46+
47+diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c
48+index 5024f48..9b47d1c 100644
49+--- a/gcc/cppdefault.c
50++++ b/gcc/cppdefault.c
51+@@ -48,15 +48,15 @@ const struct default_include cpp_include_defaults[]
52+ = {
53+ #ifdef GPLUSPLUS_INCLUDE_DIR
54+ /* Pick up GNU C++ generic include files. */
55+- { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0, 0 },
56++ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 1, 0 },
57+ #endif
58+ #ifdef GPLUSPLUS_TOOL_INCLUDE_DIR
59+ /* Pick up GNU C++ target-dependent include files. */
60+- { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, 0, 1 },
61++ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, 1, 1 },
62+ #endif
63+ #ifdef GPLUSPLUS_BACKWARD_INCLUDE_DIR
64+ /* Pick up GNU C++ backward and deprecated include files. */
65+- { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, 0, 0 },
66++ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, 1, 0 },
67+ #endif
68+ #ifdef LOCAL_INCLUDE_DIR
69+ /* /usr/local/include comes before the fixincluded header files. */
70diff --git a/meta/recipes-devtools/gcc/gcc-configure-cross.inc b/meta/recipes-devtools/gcc/gcc-configure-cross.inc
71index 3da92e2..04a8685 100644
72--- a/meta/recipes-devtools/gcc/gcc-configure-cross.inc
73+++ b/meta/recipes-devtools/gcc/gcc-configure-cross.inc
74@@ -5,7 +5,7 @@ USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibc", "no", "", d )}'
75 EXTRA_OECONF += " --enable-poison-system-directories "
76
77 EXTRA_OECONF_PATHS = "--with-local-prefix=${STAGING_DIR_TARGET}${target_exec_prefix} \
78- --with-gxx-include-dir=${STAGING_DIR_TARGET}/${target_includedir}/c++ \
79+ --with-gxx-include-dir=${target_includedir}/c++ \
80 --with-sysroot=${STAGING_DIR_TARGET} \
81 --with-build-sysroot=${STAGING_DIR_TARGET}"
82
83diff --git a/meta/recipes-devtools/gcc/gcc-configure-sdk.inc b/meta/recipes-devtools/gcc/gcc-configure-sdk.inc
84index 0eb33ad..756e74e 100644
85--- a/meta/recipes-devtools/gcc/gcc-configure-sdk.inc
86+++ b/meta/recipes-devtools/gcc/gcc-configure-sdk.inc
87@@ -5,7 +5,7 @@ USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibc", "no", "", d )}'
88 USE_NLS = '${@base_conditional( "TARGET_OS", "linux-uclibcgnueabi", "no", "", d )}'
89
90 EXTRA_OECONF_PATHS = "--with-local-prefix=${SDKPATH}/sysroots/${TARGET_SYS}${target_exec_prefix} \
91- --with-gxx-include-dir=${SDKPATH}/sysroots/${TARGET_SYS}${target_includedir}/c++ \
92+ --with-gxx-include-dir=${target_includedir}/c++ \
93 --with-build-time-tools=${STAGING_DIR_NATIVE}${prefix_native}/${TARGET_SYS}/bin \
94 --with-sysroot=${SDKPATH}/sysroots/${TARGET_SYS} \
95 --with-build-sysroot=${STAGING_DIR_TARGET}"
96diff --git a/meta/recipes-devtools/gcc/gcc-cross-canadian_4.5.1.bb b/meta/recipes-devtools/gcc/gcc-cross-canadian_4.5.1.bb
97index 98e239d..37c64fb 100644
98--- a/meta/recipes-devtools/gcc/gcc-cross-canadian_4.5.1.bb
99+++ b/meta/recipes-devtools/gcc/gcc-cross-canadian_4.5.1.bb
100@@ -5,7 +5,7 @@ require gcc-cross-canadian.inc
101 require gcc-configure-sdk.inc
102 require gcc-package-sdk.inc
103
104-PR = "r1"
105+PR = "r2"
106
107 DEPENDS += "gmp-nativesdk mpfr-nativesdk libmpc-nativesdk elfutils-nativesdk"
108 RDEPENDS_${PN} += "mpfr-nativesdk libmpc-nativesdk elfutils-nativesdk"
109diff --git a/meta/recipes-devtools/gcc/gcc-cross-initial_4.5.1.bb b/meta/recipes-devtools/gcc/gcc-cross-initial_4.5.1.bb
110index e3aea8b..a121782 100644
111--- a/meta/recipes-devtools/gcc/gcc-cross-initial_4.5.1.bb
112+++ b/meta/recipes-devtools/gcc/gcc-cross-initial_4.5.1.bb
113@@ -1,5 +1,5 @@
114 require gcc-cross_${PV}.bb
115 require gcc-cross-initial.inc
116
117-PR = "r0"
118+PR = "r1"
119
120diff --git a/meta/recipes-devtools/gcc/gcc-cross-intermediate_4.5.1.bb b/meta/recipes-devtools/gcc/gcc-cross-intermediate_4.5.1.bb
121index 4cabe0e..7aaa5b0 100644
122--- a/meta/recipes-devtools/gcc/gcc-cross-intermediate_4.5.1.bb
123+++ b/meta/recipes-devtools/gcc/gcc-cross-intermediate_4.5.1.bb
124@@ -1,4 +1,4 @@
125 require gcc-cross_${PV}.bb
126 require gcc-cross-intermediate.inc
127-PR = "r0"
128+PR = "r1"
129
130diff --git a/meta/recipes-devtools/gcc/gcc-cross_4.5.1.bb b/meta/recipes-devtools/gcc/gcc-cross_4.5.1.bb
131index 445869d..b7e4328 100644
132--- a/meta/recipes-devtools/gcc/gcc-cross_4.5.1.bb
133+++ b/meta/recipes-devtools/gcc/gcc-cross_4.5.1.bb
134@@ -1,4 +1,4 @@
135-PR = "r0"
136+PR = "r1"
137
138 require gcc-${PV}.inc
139 require gcc-cross4.inc
140diff --git a/meta/recipes-devtools/gcc/gcc-crosssdk-initial_4.5.1.bb b/meta/recipes-devtools/gcc/gcc-crosssdk-initial_4.5.1.bb
141index 22cb490..0fc5faa 100644
142--- a/meta/recipes-devtools/gcc/gcc-crosssdk-initial_4.5.1.bb
143+++ b/meta/recipes-devtools/gcc/gcc-crosssdk-initial_4.5.1.bb
144@@ -1,4 +1,4 @@
145 require gcc-cross-initial_${PV}.bb
146 require gcc-crosssdk-initial.inc
147
148-PR = "r0"
149+PR = "r1"
150diff --git a/meta/recipes-devtools/gcc/gcc-crosssdk-intermediate_4.5.1.bb b/meta/recipes-devtools/gcc/gcc-crosssdk-intermediate_4.5.1.bb
151index ba42ca0..4260c35 100644
152--- a/meta/recipes-devtools/gcc/gcc-crosssdk-intermediate_4.5.1.bb
153+++ b/meta/recipes-devtools/gcc/gcc-crosssdk-intermediate_4.5.1.bb
154@@ -1,4 +1,4 @@
155 require gcc-cross-intermediate_${PV}.bb
156 require gcc-crosssdk-intermediate.inc
157
158-PR = "r0"
159+PR = "r1"
160diff --git a/meta/recipes-devtools/gcc/gcc-crosssdk_4.5.1.bb b/meta/recipes-devtools/gcc/gcc-crosssdk_4.5.1.bb
161index 6f0a540..a23a662 100644
162--- a/meta/recipes-devtools/gcc/gcc-crosssdk_4.5.1.bb
163+++ b/meta/recipes-devtools/gcc/gcc-crosssdk_4.5.1.bb
164@@ -1,4 +1,4 @@
165 require gcc-cross_${PV}.bb
166 require gcc-crosssdk.inc
167
168-PR = "r0"
169+PR = "r1"
170diff --git a/meta/recipes-devtools/gcc/gcc-runtime_4.5.1.bb b/meta/recipes-devtools/gcc/gcc-runtime_4.5.1.bb
171index 4d2302d..ca22e8b 100644
172--- a/meta/recipes-devtools/gcc/gcc-runtime_4.5.1.bb
173+++ b/meta/recipes-devtools/gcc/gcc-runtime_4.5.1.bb
174@@ -1,4 +1,4 @@
175-PR = "r0"
176+PR = "r1"
177
178 require gcc-${PV}.inc
179 require gcc-configure-runtime.inc
180diff --git a/meta/recipes-devtools/gcc/gcc_4.5.1.bb b/meta/recipes-devtools/gcc/gcc_4.5.1.bb
181index 81c1fa9..a21772f 100644
182--- a/meta/recipes-devtools/gcc/gcc_4.5.1.bb
183+++ b/meta/recipes-devtools/gcc/gcc_4.5.1.bb
184@@ -1,4 +1,4 @@
185-PR = "r0"
186+PR = "r1"
187 require gcc-${PV}.inc
188 require gcc-configure-target.inc
189 require gcc-package-target.inc
190--
191cgit v0.8.3.3-89-gbf82
diff --git a/recipes-devtools/gcc/gcc-4.5.inc b/recipes-devtools/gcc/gcc-4.5.inc
index ddd9f9839..5dcb5acc5 100644
--- a/recipes-devtools/gcc/gcc-4.5.inc
+++ b/recipes-devtools/gcc/gcc-4.5.inc
@@ -12,9 +12,9 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=59530bdf33659b29e73d4adb9f9f6552 \
12 file://COPYING.RUNTIME;md5=fe60d87048567d4fe8c8a0ed2448bcc8" 12 file://COPYING.RUNTIME;md5=fe60d87048567d4fe8c8a0ed2448bcc8"
13 13
14 14
15SRCREV = "167948" 15SRCREV = "168622"
16PV = "4.5" 16PV = "4.5"
17INC_PR = "r11" 17INC_PR = "r29"
18 18
19# BINV should be incremented after updating to a revision 19# BINV should be incremented after updating to a revision
20# after a minor gcc release (e.g. 4.5.1 or 4.5.2) has been made 20# after a minor gcc release (e.g. 4.5.1 or 4.5.2) has been made
@@ -133,7 +133,6 @@ SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \
133 file://linaro/gcc-4.5-linaro-r99411.patch \ 133 file://linaro/gcc-4.5-linaro-r99411.patch \
134 file://linaro/gcc-4.5-linaro-r99412.patch \ 134 file://linaro/gcc-4.5-linaro-r99412.patch \
135 file://linaro/gcc-4.5-linaro-r99413.patch \ 135 file://linaro/gcc-4.5-linaro-r99413.patch \
136 file://linaro/gcc-4.5-linaro-r99414.patch \
137 file://linaro/gcc-4.5-linaro-r99415.patch \ 136 file://linaro/gcc-4.5-linaro-r99415.patch \
138 file://linaro/gcc-4.5-linaro-r99416.patch \ 137 file://linaro/gcc-4.5-linaro-r99416.patch \
139 file://linaro/gcc-4.5-linaro-r99417.patch \ 138 file://linaro/gcc-4.5-linaro-r99417.patch \
@@ -158,8 +157,17 @@ SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \
158 file://linaro/gcc-4.5-linaro-r99442.patch \ 157 file://linaro/gcc-4.5-linaro-r99442.patch \
159 file://linaro/gcc-4.5-linaro-r99443.patch \ 158 file://linaro/gcc-4.5-linaro-r99443.patch \
160 file://linaro/gcc-4.5-linaro-r99444.patch \ 159 file://linaro/gcc-4.5-linaro-r99444.patch \
160 file://linaro/gcc-4.5-linaro-r99448.patch \
161 file://linaro/gcc-4.5-linaro-r99449.patch \
162 file://linaro/gcc-4.5-linaro-r99450.patch \
163 file://linaro/gcc-4.5-linaro-r99451.patch \
164 file://linaro/gcc-4.5-linaro-r99452.patch \
165 file://linaro/gcc-4.5-linaro-r99453.patch \
166 file://linaro/gcc-4.5-linaro-r99454.patch \
167 file://linaro/gcc-4.5-linaro-r99455.patch \
168 file://linaro/gcc-4.5-linaro-r99456.patch \
169# file://linaro/gcc-4.5-linaro-r99457.patch \
161 file://gcc-scalar-widening-pr45847.patch \ 170 file://gcc-scalar-widening-pr45847.patch \
162 file://gcc-arm-qihi-split-PR46883.patch \
163 file://gcc-arm-volatile-bitfield-fix.patch \ 171 file://gcc-arm-volatile-bitfield-fix.patch \
164 \ 172 \
165 file://optional_libstdc.patch \ 173 file://optional_libstdc.patch \
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99414.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99414.patch
deleted file mode 100644
index 648ea5fa5..000000000
--- a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99414.patch
+++ /dev/null
@@ -1,36 +0,0 @@
12010-10-15 Yao Qi <yao@codesourcery.com>
2
3 Backport from mainline:
4
5 2010-10-14 Yao Qi <yao@codesourcery.com>
6
7 gcc/
8 PR target/45447
9 * config/arm/arm.c (arm_build_builtin_va_list): Assign
10 va_list_name to TYPE_STUB_DECL (va_list_type).
11
12 gcc/testsuite/
13 PR target/45447
14 * gcc.target/arm/pr45447.c: New test.
15
16=== modified file 'gcc/config/arm/arm.c'
17Index: gcc-4.5/gcc/config/arm/arm.c
18===================================================================
19--- gcc-4.5.orig/gcc/config/arm/arm.c
20+++ gcc-4.5/gcc/config/arm/arm.c
21@@ -1166,6 +1166,7 @@ arm_build_builtin_va_list (void)
22 va_list_type);
23 DECL_ARTIFICIAL (va_list_name) = 1;
24 TYPE_NAME (va_list_type) = va_list_name;
25+ TYPE_STUB_DECL (va_list_type) = va_list_name;
26 /* Create the __ap field. */
27 ap_field = build_decl (BUILTINS_LOCATION,
28 FIELD_DECL,
29Index: gcc-4.5/gcc/testsuite/gcc.target/arm/pr45447.c
30===================================================================
31--- /dev/null
32+++ gcc-4.5/gcc/testsuite/gcc.target/arm/pr45447.c
33@@ -0,0 +1,3 @@
34+/* { dg-do compile } */
35+/* { dg-options "-g -femit-struct-debug-baseonly" } */
36+typedef __builtin_va_list x;
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99448.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99448.patch
new file mode 100644
index 000000000..9f3d47f38
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99448.patch
@@ -0,0 +1,147 @@
12010-12-13 Chung-Lin Tang <cltang@codesourcery.com>
2
3 Backport from mainline:
4
5 2010-12-10 Jakub Jelinek <jakub@redhat.com>
6
7 PR rtl-optimization/46865
8
9 * rtl.c (rtx_equal_p_cb, rtx_equal_p): For last operand of
10 ASM_OPERANDS and ASM_INPUT if integers are different,
11 call locator_eq.
12 * jump.c (rtx_renumbered_equal_p): Likewise.
13
14 gcc/testsuite/
15 * gcc.target/i386/pr46865-1.c: New test.
16 * gcc.target/i386/pr46865-2.c: New test.
17
18=== modified file 'gcc/jump.c'
19--- old/gcc/jump.c 2009-11-25 10:55:54 +0000
20+++ new/gcc/jump.c 2010-12-13 10:05:52 +0000
21@@ -1728,7 +1728,13 @@
22
23 case 'i':
24 if (XINT (x, i) != XINT (y, i))
25- return 0;
26+ {
27+ if (((code == ASM_OPERANDS && i == 6)
28+ || (code == ASM_INPUT && i == 1))
29+ && locator_eq (XINT (x, i), XINT (y, i)))
30+ break;
31+ return 0;
32+ }
33 break;
34
35 case 't':
36
37=== modified file 'gcc/rtl.c'
38--- old/gcc/rtl.c 2009-11-25 10:55:54 +0000
39+++ new/gcc/rtl.c 2010-12-13 10:05:52 +0000
40@@ -429,7 +429,15 @@
41 case 'n':
42 case 'i':
43 if (XINT (x, i) != XINT (y, i))
44- return 0;
45+ {
46+#ifndef GENERATOR_FILE
47+ if (((code == ASM_OPERANDS && i == 6)
48+ || (code == ASM_INPUT && i == 1))
49+ && locator_eq (XINT (x, i), XINT (y, i)))
50+ break;
51+#endif
52+ return 0;
53+ }
54 break;
55
56 case 'V':
57@@ -549,7 +557,15 @@
58 case 'n':
59 case 'i':
60 if (XINT (x, i) != XINT (y, i))
61- return 0;
62+ {
63+#ifndef GENERATOR_FILE
64+ if (((code == ASM_OPERANDS && i == 6)
65+ || (code == ASM_INPUT && i == 1))
66+ && locator_eq (XINT (x, i), XINT (y, i)))
67+ break;
68+#endif
69+ return 0;
70+ }
71 break;
72
73 case 'V':
74
75=== added file 'gcc/testsuite/gcc.target/i386/pr46865-1.c'
76--- old/gcc/testsuite/gcc.target/i386/pr46865-1.c 1970-01-01 00:00:00 +0000
77+++ new/gcc/testsuite/gcc.target/i386/pr46865-1.c 2010-12-13 10:05:52 +0000
78@@ -0,0 +1,31 @@
79+/* PR rtl-optimization/46865 */
80+/* { dg-do compile } */
81+/* { dg-options "-O2" } */
82+
83+extern unsigned long f;
84+
85+#define m1(f) \
86+ if (f & 1) \
87+ asm volatile ("nop /* asmnop */\n"); \
88+ else \
89+ asm volatile ("nop /* asmnop */\n");
90+
91+#define m2(f) \
92+ if (f & 1) \
93+ asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx"); \
94+ else \
95+ asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");
96+
97+void
98+foo (void)
99+{
100+ m1 (f);
101+}
102+
103+void
104+bar (void)
105+{
106+ m2 (f);
107+}
108+
109+/* { dg-final { scan-assembler-times "asmnop" 2 } } */
110
111=== added file 'gcc/testsuite/gcc.target/i386/pr46865-2.c'
112--- old/gcc/testsuite/gcc.target/i386/pr46865-2.c 1970-01-01 00:00:00 +0000
113+++ new/gcc/testsuite/gcc.target/i386/pr46865-2.c 2010-12-13 10:05:52 +0000
114@@ -0,0 +1,32 @@
115+/* PR rtl-optimization/46865 */
116+/* { dg-do compile } */
117+/* { dg-options "-O2 -save-temps" } */
118+
119+extern unsigned long f;
120+
121+#define m1(f) \
122+ if (f & 1) \
123+ asm volatile ("nop /* asmnop */\n"); \
124+ else \
125+ asm volatile ("nop /* asmnop */\n");
126+
127+#define m2(f) \
128+ if (f & 1) \
129+ asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx"); \
130+ else \
131+ asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");
132+
133+void
134+foo (void)
135+{
136+ m1 (f);
137+}
138+
139+void
140+bar (void)
141+{
142+ m2 (f);
143+}
144+
145+/* { dg-final { scan-assembler-times "asmnop" 2 } } */
146+/* { dg-final { cleanup-saved-temps } } */
147
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99449.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99449.patch
new file mode 100644
index 000000000..e6b0fad08
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99449.patch
@@ -0,0 +1,34 @@
12010-12-21 Ulrich Weigand <uweigand@de.ibm.com>
2
3 LP: #617384
4 Backport from mainline:
5
6 gcc/
7 * config/arm/arm.c (require_pic_register): Set INSN_LOCATOR for all
8 instructions injected into the prologue to prologue_locator.
9
10=== modified file 'gcc/config/arm/arm.c'
11--- old/gcc/config/arm/arm.c 2010-12-10 15:34:19 +0000
12+++ new/gcc/config/arm/arm.c 2010-12-21 14:13:38 +0000
13@@ -5080,7 +5080,7 @@
14 }
15 else
16 {
17- rtx seq;
18+ rtx seq, insn;
19
20 if (!cfun->machine->pic_reg)
21 cfun->machine->pic_reg = gen_reg_rtx (Pmode);
22@@ -5097,6 +5097,11 @@
23
24 seq = get_insns ();
25 end_sequence ();
26+
27+ for (insn = seq; insn; insn = NEXT_INSN (insn))
28+ if (INSN_P (insn))
29+ INSN_LOCATOR (insn) = prologue_locator;
30+
31 /* We can be called during expansion of PHI nodes, where
32 we can't yet emit instructions directly in the final
33 insn stream. Queue the insns on the entry edge, they will
34
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99450.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99450.patch
new file mode 100644
index 000000000..49fa07fca
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99450.patch
@@ -0,0 +1,104 @@
1 2010-12-21 Ulrich Weigand <uweigand@de.ibm.com>
2
3 LP: #662324
4 Backport from mainline:
5
6 2010-12-17 Dodji Seketeli <dodji@redhat.com>
7
8 gcc/
9 * dwarf2out.c (gen_type_die_with_usage): Do not try to emit debug
10 info for a redundant typedef that has DECL_ORIGINAL_TYPE set. Use
11 that underlying type instead.
12
13 gcc/testsuite/
14 * g++.dg/debug/dwarf2/self-ref-1.C: New test.
15 * g++.dg/debug/dwarf2/self-ref-2.C: Likewise.
16
17=== modified file 'gcc/dwarf2out.c'
18--- old/gcc/dwarf2out.c 2010-10-04 00:50:43 +0000
19+++ new/gcc/dwarf2out.c 2010-12-21 18:46:10 +0000
20@@ -18993,6 +18993,16 @@
21 if (type == NULL_TREE || type == error_mark_node)
22 return;
23
24+ if (TYPE_NAME (type) != NULL_TREE
25+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
26+ && is_redundant_typedef (TYPE_NAME (type))
27+ && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
28+ /* The DECL of this type is a typedef we don't want to emit debug
29+ info for but we want debug info for its underlying typedef.
30+ This can happen for e.g, the injected-class-name of a C++
31+ type. */
32+ type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
33+
34 /* If TYPE is a typedef type variant, let's generate debug info
35 for the parent typedef which TYPE is a type of. */
36 if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
37
38=== added file 'gcc/testsuite/g++.dg/debug/dwarf2/self-ref-1.C'
39--- old/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-1.C 1970-01-01 00:00:00 +0000
40+++ new/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-1.C 2010-12-21 18:46:10 +0000
41@@ -0,0 +1,28 @@
42+// Origin: PR debug/45088
43+// { dg-do compile }
44+// { dg-options "-g -dA" }
45+// { dg-final { scan-assembler-times "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_pointer_type\\)\[\n\r\]{1,2}\[^\n\r\]*DW_AT_byte_size\[\n\r\]{1,2}\[^\n\r\]*DW_AT_type" 4 } }
46+
47+struct A
48+{
49+ virtual ~A();
50+};
51+
52+struct B : public A
53+{
54+ virtual ~B(){}
55+};
56+
57+struct C : public B
58+{
59+ A* a1;
60+};
61+
62+int
63+main()
64+{
65+ C c;
66+ c.a1 = 0;
67+ return 0;
68+}
69+
70
71=== added file 'gcc/testsuite/g++.dg/debug/dwarf2/self-ref-2.C'
72--- old/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-2.C 1970-01-01 00:00:00 +0000
73+++ new/gcc/testsuite/g++.dg/debug/dwarf2/self-ref-2.C 2010-12-21 18:46:10 +0000
74@@ -0,0 +1,29 @@
75+// Origin: PR debug/45088
76+// { dg-do compile }
77+// { dg-options "-g -dA" }
78+// { dg-final { scan-assembler-times "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_pointer_type\\)\[\n\r\]{1,2}\[^\n\r\]*DW_AT_byte_size\[\n\r\]{1,2}\[^\n\r\]*DW_AT_type" 4 } }
79+
80+template<class T>
81+struct A
82+{
83+ virtual ~A();
84+};
85+
86+struct B : public A<int>
87+{
88+ virtual ~B(){}
89+};
90+
91+struct C : public B
92+{
93+ A<int>* a1;
94+};
95+
96+int
97+main()
98+{
99+ C c;
100+ c.a1 = 0;
101+ return 0;
102+}
103+
104
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99451.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99451.patch
new file mode 100644
index 000000000..d87c312d0
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99451.patch
@@ -0,0 +1,45 @@
12010-12-22 Ulrich Weigand <uweigand@de.ibm.com>
2
3 LP: #693425
4 Backport from mainline:
5
6 gcc/
7 * config/spu/spu.md ("mov<mode>"): Use nonimmediate_operand
8 predicate for destination operand.
9 * config/spu/spu.c (spu_expand_mov): If move destination is an
10 invalid subreg, perform move in the subreg's inner mode instead.
11
12=== modified file 'gcc/config/spu/spu.c'
13--- old/gcc/config/spu/spu.c 2010-08-04 09:53:04 +0000
14+++ new/gcc/config/spu/spu.c 2010-12-22 15:20:44 +0000
15@@ -4572,7 +4572,13 @@
16 spu_expand_mov (rtx * ops, enum machine_mode mode)
17 {
18 if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0]))
19- abort ();
20+ {
21+ /* Perform the move in the destination SUBREG's inner mode. */
22+ ops[0] = SUBREG_REG (ops[0]);
23+ mode = GET_MODE (ops[0]);
24+ ops[1] = gen_lowpart_common (mode, ops[1]);
25+ gcc_assert (ops[1]);
26+ }
27
28 if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1]))
29 {
30
31=== modified file 'gcc/config/spu/spu.md'
32--- old/gcc/config/spu/spu.md 2009-05-23 01:28:14 +0000
33+++ new/gcc/config/spu/spu.md 2010-12-22 15:20:44 +0000
34@@ -269,8 +269,8 @@
35 ;; mov
36
37 (define_expand "mov<mode>"
38- [(set (match_operand:ALL 0 "spu_nonimm_operand" "=r,r,r,m")
39- (match_operand:ALL 1 "general_operand" "r,i,m,r"))]
40+ [(set (match_operand:ALL 0 "nonimmediate_operand" "")
41+ (match_operand:ALL 1 "general_operand" ""))]
42 ""
43 {
44 if (spu_expand_mov(operands, <MODE>mode))
45
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99452.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99452.patch
new file mode 100644
index 000000000..6cfc01fef
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99452.patch
@@ -0,0 +1,201 @@
12010-12-14 Sandra Loosemore <sandra@codesourcery.com>
2
3 Backport from mainline:
4
5 2010-12-14 Jakub Jelinek <jakub@redhat.com>
6
7 PR tree-optimization/46909
8
9 gcc/
10 * tree-ssa-ccp.c (and_var_with_comparison_1): Save partial
11 result even in the is_and case, if both partial results
12 are the same, return it.
13 (or_var_with_comparison_1): Use is_or predicate instead of
14 innercode == TRUTH_OR_EXPR test. Save partial result
15 even in the is_or case, if both partial results are the
16 same, return it. In the !is_or case when both partial
17 results are the same, return the partial result instead
18 of boolean_true_node.
19
20 gcc/testsuite/
21 * gcc.c-torture/execute/pr46909-1.c: New test.
22 * gcc.c-torture/execute/pr46909-2.c: New test.
23 * gcc.dg/pr46909.c: New test.
24
25=== added file 'gcc/testsuite/gcc.c-torture/execute/pr46909-1.c'
26--- old/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c 1970-01-01 00:00:00 +0000
27+++ new/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c 2011-01-05 11:27:00 +0000
28@@ -0,0 +1,22 @@
29+/* PR tree-optimization/46909 */
30+
31+extern void abort ();
32+
33+int
34+__attribute__ ((__noinline__))
35+foo (unsigned int x)
36+{
37+ if (! (x == 4 || x == 6) || (x == 2 || x == 6))
38+ return 1;
39+ return -1;
40+}
41+
42+int
43+main ()
44+{
45+ int i;
46+ for (i = -10; i < 10; i++)
47+ if (foo (i) != 1 - 2 * (i == 4))
48+ abort ();
49+ return 0;
50+}
51
52=== added file 'gcc/testsuite/gcc.c-torture/execute/pr46909-2.c'
53--- old/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c 1970-01-01 00:00:00 +0000
54+++ new/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c 2011-01-05 11:27:00 +0000
55@@ -0,0 +1,22 @@
56+/* PR tree-optimization/46909 */
57+
58+extern void abort (void);
59+
60+int
61+__attribute__((noinline))
62+foo (int x)
63+{
64+ if ((x != 0 && x != 13) || x == 5 || x == 20)
65+ return 1;
66+ return -1;
67+}
68+
69+int
70+main (void)
71+{
72+ int i;
73+ for (i = -10; i < 30; i++)
74+ if (foo (i) != 1 - 2 * (i == 0) - 2 * (i == 13))
75+ abort ();
76+ return 0;
77+}
78
79=== added file 'gcc/testsuite/gcc.dg/pr46909.c'
80--- old/gcc/testsuite/gcc.dg/pr46909.c 1970-01-01 00:00:00 +0000
81+++ new/gcc/testsuite/gcc.dg/pr46909.c 2011-01-05 11:27:00 +0000
82@@ -0,0 +1,17 @@
83+/* PR tree-optimization/46909 */
84+/* { dg-do compile } */
85+/* { dg-options "-O2 -fdump-tree-ifcombine" } */
86+
87+extern void abort ();
88+
89+int
90+__attribute__ ((__noinline__))
91+foo (unsigned int x)
92+{
93+ if (! (x == 4 || x == 6) || (x == 2 || x == 6))
94+ return 1;
95+ return -1;
96+}
97+
98+/* { dg-final { scan-tree-dump "optimizing two comparisons to x_\[0-9\]+\\(D\\) != 4" "ifcombine" } } */
99+/* { dg-final { cleanup-tree-dump "ifcombine" } } */
100
101=== modified file 'gcc/tree-ssa-ccp.c'
102--- old/gcc/tree-ssa-ccp.c 2010-09-16 09:15:46 +0000
103+++ new/gcc/tree-ssa-ccp.c 2011-01-05 11:27:00 +0000
104@@ -3508,14 +3508,11 @@
105 /* Handle the OR case, where we are redistributing:
106 (inner1 OR inner2) AND (op2a code2 op2b)
107 => (t OR (inner2 AND (op2a code2 op2b))) */
108- else
109- {
110- if (integer_onep (t))
111- return boolean_true_node;
112- else
113- /* Save partial result for later. */
114- partial = t;
115- }
116+ else if (integer_onep (t))
117+ return boolean_true_node;
118+
119+ /* Save partial result for later. */
120+ partial = t;
121 }
122
123 /* Compute the second partial result, (inner2 AND (op2a code op2b)) */
124@@ -3536,6 +3533,10 @@
125 return inner1;
126 else if (integer_zerop (t))
127 return boolean_false_node;
128+ /* If both are the same, we can apply the identity
129+ (x AND x) == x. */
130+ else if (partial && same_bool_result_p (t, partial))
131+ return t;
132 }
133
134 /* Handle the OR case. where we are redistributing:
135@@ -3945,7 +3946,7 @@
136 => (t OR inner2)
137 If the partial result t is a constant, we win. Otherwise
138 continue on to try reassociating with the other inner test. */
139- if (innercode == TRUTH_OR_EXPR)
140+ if (is_or)
141 {
142 if (integer_onep (t))
143 return boolean_true_node;
144@@ -3956,14 +3957,11 @@
145 /* Handle the AND case, where we are redistributing:
146 (inner1 AND inner2) OR (op2a code2 op2b)
147 => (t AND (inner2 OR (op2a code op2b))) */
148- else
149- {
150- if (integer_zerop (t))
151- return boolean_false_node;
152- else
153- /* Save partial result for later. */
154- partial = t;
155- }
156+ else if (integer_zerop (t))
157+ return boolean_false_node;
158+
159+ /* Save partial result for later. */
160+ partial = t;
161 }
162
163 /* Compute the second partial result, (inner2 OR (op2a code op2b)) */
164@@ -3977,13 +3975,18 @@
165 {
166 /* Handle the OR case, where we are reassociating:
167 (inner1 OR inner2) OR (op2a code2 op2b)
168- => (inner1 OR t) */
169- if (innercode == TRUTH_OR_EXPR)
170+ => (inner1 OR t)
171+ => (t OR partial) */
172+ if (is_or)
173 {
174 if (integer_zerop (t))
175 return inner1;
176 else if (integer_onep (t))
177 return boolean_true_node;
178+ /* If both are the same, we can apply the identity
179+ (x OR x) == x. */
180+ else if (partial && same_bool_result_p (t, partial))
181+ return t;
182 }
183
184 /* Handle the AND case, where we are redistributing:
185@@ -4000,13 +4003,13 @@
186 operand to the redistributed AND expression. The
187 interesting case is when at least one is true.
188 Or, if both are the same, we can apply the identity
189- (x AND x) == true. */
190+ (x AND x) == x. */
191 if (integer_onep (partial))
192 return t;
193 else if (integer_onep (t))
194 return partial;
195 else if (same_bool_result_p (t, partial))
196- return boolean_true_node;
197+ return t;
198 }
199 }
200 }
201
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99453.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99453.patch
new file mode 100644
index 000000000..8eb35325e
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99453.patch
@@ -0,0 +1,72 @@
12010-12-17 Bernd Schmidt <bernds@codesourcery.com>
2
3 Issue #10208
4
5 gcc/
6 * config/arm/arm.c (arm_select_cc_mode): Before calling
7 arm_select_dominance_cc_mode for AND or IOR operations, ensure
8 that op is NE or EQ.
9
10 gcc/testsuite/
11 * gcc.c-torture/compile/20101217-1.c: New test.
12
13=== modified file 'gcc/config/arm/arm.c'
14--- old/gcc/config/arm/arm.c 2010-12-21 14:13:38 +0000
15+++ new/gcc/config/arm/arm.c 2011-01-05 11:32:50 +0000
16@@ -10609,12 +10609,14 @@
17
18 /* Alternate canonicalizations of the above. These are somewhat cleaner. */
19 if (GET_CODE (x) == AND
20+ && (op == EQ || op == NE)
21 && COMPARISON_P (XEXP (x, 0))
22 && COMPARISON_P (XEXP (x, 1)))
23 return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
24 DOM_CC_X_AND_Y);
25
26 if (GET_CODE (x) == IOR
27+ && (op == EQ || op == NE)
28 && COMPARISON_P (XEXP (x, 0))
29 && COMPARISON_P (XEXP (x, 1)))
30 return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
31
32=== added file 'gcc/testsuite/gcc.c-torture/compile/20101217-1.c'
33--- old/gcc/testsuite/gcc.c-torture/compile/20101217-1.c 1970-01-01 00:00:00 +0000
34+++ new/gcc/testsuite/gcc.c-torture/compile/20101217-1.c 2011-01-05 11:32:50 +0000
35@@ -0,0 +1,36 @@
36+/* Testcase provided by HUAWEI. */
37+#include <stdio.h>
38+int main()
39+{
40+ int cur_k;
41+ int cur_j=0;
42+ int cur_i=28;
43+ unsigned char temp_data[8];
44+ unsigned int Data_Size=20;
45+
46+ for (cur_k=0;cur_j<7;cur_j++,cur_i++) {
47+ if (cur_j%2==0) {
48+ temp_data[cur_k++]=0;
49+ }
50+ if (cur_k==7) {
51+ for (;cur_k>0;cur_k--) {
52+ if (cur_k>2) {
53+ if ((temp_data[7-cur_k]=='n' || temp_data[7-cur_k]=='N' ) && (temp_data[7-cur_k+1]=='a' || temp_data[7-cur_k+1]=='A' )) {
54+ break;
55+ }
56+ }
57+ if (cur_k==1) {
58+ if (temp_data[7-cur_k]=='n' || temp_data[7-cur_k]=='N' ) {
59+ break;
60+ }
61+ }
62+ }
63+ if (cur_k==7) {
64+ } else {
65+ if (cur_k>0)
66+ printf("dfjk");
67+ }
68+ }
69+ }
70+return 0;
71+}
72
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99454.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99454.patch
new file mode 100644
index 000000000..8aa06cc51
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99454.patch
@@ -0,0 +1,46 @@
12010-12-18 Andrew Stubbs <ams@codesourcery.com>
2
3 Backport from mainline:
4
5 gcc/
6 2010-12-17 Andrew Stubbs <ams@codesourcery.com>
7
8 * config/arm/arm.md (maddhisi4, *maddhidi4): Use the canonical
9 operand order for plus.
10 Drop redundant % from constraints.
11
12=== modified file 'gcc/config/arm/arm.md'
13--- old/gcc/config/arm/arm.md 2010-11-11 11:12:14 +0000
14+++ new/gcc/config/arm/arm.md 2011-01-05 11:42:19 +0000
15@@ -1791,11 +1791,11 @@
16
17 (define_insn "maddhisi4"
18 [(set (match_operand:SI 0 "s_register_operand" "=r")
19- (plus:SI (match_operand:SI 3 "s_register_operand" "r")
20- (mult:SI (sign_extend:SI
21- (match_operand:HI 1 "s_register_operand" "%r"))
22+ (plus:SI (mult:SI (sign_extend:SI
23+ (match_operand:HI 1 "s_register_operand" "r"))
24 (sign_extend:SI
25- (match_operand:HI 2 "s_register_operand" "r")))))]
26+ (match_operand:HI 2 "s_register_operand" "r")))
27+ (match_operand:SI 3 "s_register_operand" "r")))]
28 "TARGET_DSP_MULTIPLY"
29 "smlabb%?\\t%0, %1, %2, %3"
30 [(set_attr "insn" "smlaxy")
31@@ -1805,11 +1805,11 @@
32 (define_insn "*maddhidi4"
33 [(set (match_operand:DI 0 "s_register_operand" "=r")
34 (plus:DI
35- (match_operand:DI 3 "s_register_operand" "0")
36 (mult:DI (sign_extend:DI
37- (match_operand:HI 1 "s_register_operand" "%r"))
38+ (match_operand:HI 1 "s_register_operand" "r"))
39 (sign_extend:DI
40- (match_operand:HI 2 "s_register_operand" "r")))))]
41+ (match_operand:HI 2 "s_register_operand" "r")))
42+ (match_operand:DI 3 "s_register_operand" "0")))]
43 "TARGET_DSP_MULTIPLY"
44 "smlalbb%?\\t%Q0, %R0, %1, %2"
45 [(set_attr "insn" "smlalxy")
46
diff --git a/recipes-devtools/gcc/gcc-4.5/gcc-arm-qihi-split-PR46883.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99455.patch
index 2cb5635da..5e8383a7d 100644
--- a/recipes-devtools/gcc/gcc-4.5/gcc-arm-qihi-split-PR46883.patch
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99455.patch
@@ -1,13 +1,25 @@
1Backport of http://gcc.gnu.org/ml/gcc-patches/2010-12/msg01096.html 12010-12-21 Chung-Lin Tang <cltang@codesourcery.com>
2This should fix the ICE found in samba
3 2
4-Khem 3 Issue #10201
5 4
6Index: a/gcc/config/arm/arm.md 5 Backport from mainline:
7=================================================================== 6
8--- a/gcc/config/arm/arm.md (revision 167797) 7 2010-12-16 Chung-Lin Tang <cltang@codesourcery.com>
9+++ b/gcc/config/arm/arm.md (working copy) 8
10@@ -4137,8 +4137,8 @@ 9 PR target/46883
10 gcc/
11 * config/arm/arm.md
12 (zero_extendhisi2 for register input splitter): Change
13 "register_operand" to "s_register_operand".
14 (zero_extendqisi2 for register input splitter): Same.
15
16 gcc/testsuite/
17 * gcc.target/arm/pr46883.c: New testcase.
18
19=== modified file 'gcc/config/arm/arm.md'
20--- old/gcc/config/arm/arm.md 2011-01-05 11:42:19 +0000
21+++ new/gcc/config/arm/arm.md 2011-01-05 11:52:16 +0000
22@@ -4114,8 +4114,8 @@
11 }) 23 })
12 24
13 (define_split 25 (define_split
@@ -18,7 +30,7 @@ Index: a/gcc/config/arm/arm.md
18 "!TARGET_THUMB2 && !arm_arch6" 30 "!TARGET_THUMB2 && !arm_arch6"
19 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) 31 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
20 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] 32 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
21@@ -4244,8 +4244,8 @@ 33@@ -4234,8 +4234,8 @@
22 }) 34 })
23 35
24 (define_split 36 (define_split
@@ -29,10 +41,10 @@ Index: a/gcc/config/arm/arm.md
29 "!arm_arch6" 41 "!arm_arch6"
30 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) 42 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
31 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))] 43 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
32Index: a/gcc/testsuite/gcc.target/arm/pr46883.c 44
33=================================================================== 45=== added file 'gcc/testsuite/gcc.target/arm/pr46883.c'
34--- a/gcc/testsuite/gcc.target/arm/pr46883.c (revision 0) 46--- old/gcc/testsuite/gcc.target/arm/pr46883.c 1970-01-01 00:00:00 +0000
35+++ b/gcc/testsuite/gcc.target/arm/pr46883.c (revision 0) 47+++ new/gcc/testsuite/gcc.target/arm/pr46883.c 2011-01-05 11:52:16 +0000
36@@ -0,0 +1,16 @@ 48@@ -0,0 +1,16 @@
37+/* { dg-do compile } */ 49+/* { dg-do compile } */
38+/* { dg-options "-O1 -march=armv5te" } */ 50+/* { dg-options "-O1 -march=armv5te" } */
@@ -50,3 +62,4 @@ Index: a/gcc/testsuite/gcc.target/arm/pr46883.c
50+ (((data16s[i] & 0xFF) << 8) | ((data16s[i] >> 8) & 0xFF))) >> 8; 62+ (((data16s[i] & 0xFF) << 8) | ((data16s[i] >> 8) & 0xFF))) >> 8;
51+ } 63+ }
52+} 64+}
65
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99456.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99456.patch
new file mode 100644
index 000000000..35f98d24a
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99456.patch
@@ -0,0 +1,3163 @@
12011-01-03 Bernd Schmidt <bernds@codesourcery.com>
2
3 gcc/
4 * doc/tm.texi (RETURN_ADDR_REGNUM): Document.
5 * doc/md.texi (simple_return): Document pattern.
6 (return): Add a sentence to clarify.
7 * doc/rtl.texi (simple_return): Document.
8 * doc/invoke.texi (Optimize Options): Document -fshrink-wrap.
9 * common.opt (fshrink-wrap): New.
10 * opts.c (decode_options): Set it for -O2 and above.
11 * gengenrtl.c (special_rtx): PC, CC0, RETURN and SIMPLE_RETURN
12 are special.
13 * rtl.h (ANY_RETURN_P): New macro.
14 (global_rtl_index): Add GR_RETURN and GR_SIMPLE_RETURN.
15 (ret_rtx, simple_return_rtx): New macros.
16 * genemit.c (gen_exp): RETURN and SIMPLE_RETURN have unique rtxs.
17 (gen_expand, gen_split): Use ANY_RETURN_P.
18 * rtl.c (copy_rtx): RETURN and SIMPLE_RETURN are shared.
19 * emit-rtl.c (verify_rtx_sharing): Likewise.
20 (skip_consecutive_labels): Return the argument if it is a return rtx.
21 (classify_insn): Handle both kinds of return.
22 (init_emit_regs): Create global rtl for ret_rtx and simple_return_rtx.
23 * df-scan.c (df_uses_record): Handle SIMPLE_RETURN.
24 * rtl.def (SIMPLE_RETURN): New.
25 * rtlanal.c (tablejump_p): Check JUMP_LABEL for returns.
26 * final.c (final_scan_insn): Recognize both kinds of return.
27 * reorg.c (function_return_label, function_simple_return_label): New
28 static variables.
29 (end_of_function_label): Remove.
30 (simplejump_or_return_p): New static function.
31 (find_end_label): Add a new arg, KIND. All callers changed.
32 Depending on KIND, look for a label suitable for return or
33 simple_return.
34 (make_return_insns): Make corresponding changes.
35 (get_jump_flags): Check JUMP_LABELs for returns.
36 (follow_jumps): Likewise.
37 (get_branch_condition): Check target for return patterns rather
38 than NULL.
39 (own_thread_p): Likewise for thread.
40 (steal_delay_list_from_target): Check JUMP_LABELs for returns.
41 Use simplejump_or_return_p.
42 (fill_simple_delay_slots): Likewise.
43 (optimize_skip): Likewise.
44 (fill_slots_from_thread): Likewise.
45 (relax_delay_slots): Likewise.
46 (dbr_schedule): Adjust handling of end_of_function_label for the
47 two new variables.
48 * ifcvt.c (find_if_case_1): Take care when redirecting jumps to the
49 exit block.
50 (dead_or_predicable): Change NEW_DEST arg to DEST_EDGE. All callers
51 changed. Ensure that the right label is passed to redirect_jump.
52 * jump.c (condjump_p, condjump_in_parallel_p, any_condjump_p,
53 returnjump_p): Handle SIMPLE_RETURNs.
54 (delete_related_insns): Check JUMP_LABEL for returns.
55 (redirect_target): New static function.
56 (redirect_exp_1): Use it. Handle any kind of return rtx as a label
57 rather than interpreting NULL as a return.
58 (redirect_jump_1): Assert that nlabel is not NULL.
59 (redirect_jump): Likewise.
60 (redirect_jump_2): Handle any kind of return rtx as a label rather
61 than interpreting NULL as a return.
62 * dwarf2out.c (compute_barrier_args_size_1): Check JUMP_LABEL for
63 returns.
64 * function.c (emit_return_into_block): Remove useless declaration.
65 (record_hard_reg_sets, frame_required_for_rtx, gen_return_pattern,
66 requires_stack_frame_p): New static functions.
67 (emit_return_into_block): New arg SIMPLE_P. All callers changed.
68 Generate either kind of return pattern and update the JUMP_LABEL.
69 (thread_prologue_and_epilogue_insns): Implement a form of
70 shrink-wrapping. Ensure JUMP_LABELs for return insns are set.
71 * print-rtl.c (print_rtx): Handle returns in JUMP_LABELs.
72 * cfglayout.c (fixup_reorder_chain): Ensure JUMP_LABELs for returns
73 remain correct.
74 * resource.c (find_dead_or_set_registers): Check JUMP_LABELs for
75 returns.
76 (mark_target_live_regs): Don't pass a return rtx to next_active_insn.
77 * basic-block.h (force_nonfallthru_and_redirect): Declare.
78 * sched-vis.c (print_pattern): Add case for SIMPLE_RETURN.
79 * cfgrtl.c (force_nonfallthru_and_redirect): No longer static. New arg
80 JUMP_LABEL. All callers changed. Use the label when generating
81 return insns.
82
83 * config/i386/i386.md (returns, return_str, return_cond): New
84 code_iterator and corresponding code_attrs.
85 (<return_str>return): Renamed from return and adapted.
86 (<return_str>return_internal): Likewise for return_internal.
87 (<return_str>return_internal_long): Likewise for return_internal_long.
88 (<return_str>return_pop_internal): Likewise for return_pop_internal.
89 (<return_str>return_indirect_internal): Likewise for
90 return_indirect_internal.
91 * config/i386/i386.c (ix86_expand_epilogue): Expand a simple_return as
92 the last insn.
93 (ix86_pad_returns): Handle both kinds of return rtx.
94 * config/arm/arm.c (use_simple_return_p): new function.
95 (is_jump_table): Handle returns in JUMP_LABELs.
96 (output_return_instruction): New arg SIMPLE. All callers changed.
97 Use it to determine which kind of return to generate.
98 (arm_final_prescan_insn): Handle both kinds of return.
99 * config/arm/arm.md (returns, return_str, return_simple_p,
100 return_cond): New code_iterator and corresponding code_attrs.
101 (<return_str>return): Renamed from return and adapted.
102 (arm_<return_str>return): Renamed from arm_return and adapted.
103 (cond_<return_str>return): Renamed from cond_return and adapted.
104 (cond_<return_str>return_inverted): Renamed from cond_return_inverted
105 and adapted.
106 (epilogue): Use ret_rtx instead of gen_rtx_RETURN.
107 * config/arm/thumb2.md (thumb2_<return_str>return): Renamed from
108 thumb2_return and adapted.
109 * config/arm/arm.h (RETURN_ADDR_REGNUM): Define.
110 * config/arm/arm-protos.h (use_simple_return_p): Declare.
111 (output_return_instruction): Adjust declaration.
112 * config/mips/mips.c (mips_expand_epilogue): Generate a simple_return
113 as final insn.
114 * config/mips/mips.md (simple_return): New expander.
115 (*simple_return, simple_return_internal): New patterns.
116 * config/sh/sh.c (barrier_align): Handle return in a JUMP_LABEL.
117 (split_branches): Don't pass a null label to redirect_jump.
118
119 From mainline:
120 * vec.h (FOR_EACH_VEC_ELT, FOR_EACH_VEC_ELT_REVERSE): New macros.
121 * haifa-sched.c (find_fallthru_edge_from): Rename from
122 find_fallthru_edge. All callers changed.
123 * sched-int.h (find_fallthru_edge_from): Rename declaration as well.
124 * basic-block.h (find_fallthru_edge): New inline function.
125
126=== modified file 'gcc/basic-block.h'
127--- old/gcc/basic-block.h 2010-09-01 13:29:58 +0000
128+++ new/gcc/basic-block.h 2011-01-05 12:12:18 +0000
129@@ -884,6 +884,7 @@
130
131 /* In cfgrtl.c */
132 extern basic_block force_nonfallthru (edge);
133+extern basic_block force_nonfallthru_and_redirect (edge, basic_block, rtx);
134 extern rtx block_label (basic_block);
135 extern bool purge_all_dead_edges (void);
136 extern bool purge_dead_edges (basic_block);
137@@ -1004,6 +1005,20 @@
138 return false;
139 }
140
141+/* Return the fallthru edge in EDGES if it exists, NULL otherwise. */
142+static inline edge
143+find_fallthru_edge (VEC(edge,gc) *edges)
144+{
145+ edge e;
146+ edge_iterator ei;
147+
148+ FOR_EACH_EDGE (e, ei, edges)
149+ if (e->flags & EDGE_FALLTHRU)
150+ break;
151+
152+ return e;
153+}
154+
155 /* In cfgloopmanip.c. */
156 extern edge mfb_kj_edge;
157 extern bool mfb_keep_just (edge);
158
159=== modified file 'gcc/cfganal.c'
160--- old/gcc/cfganal.c 2009-11-25 10:55:54 +0000
161+++ new/gcc/cfganal.c 2011-01-05 12:12:18 +0000
162@@ -271,6 +271,37 @@
163 EDGE_SUCC (bb, 0)->flags |= EDGE_CAN_FALLTHRU;
164 EDGE_SUCC (bb, 1)->flags |= EDGE_CAN_FALLTHRU;
165 }
166+ /* dwarf2out expects that a NOTE_INSN_EPILOGUE_BEGIN is always paired
167+ with a return or a sibcall. Ensure that this remains the case if
168+ they are in different basic blocks. */
169+ FOR_EACH_BB (bb)
170+ {
171+ edge e;
172+ edge_iterator ei;
173+ rtx insn, end;
174+
175+ end = BB_END (bb);
176+ FOR_BB_INSNS (bb, insn)
177+ if (GET_CODE (insn) == NOTE
178+ && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG
179+ && !(CALL_P (end) && SIBLING_CALL_P (end))
180+ && !returnjump_p (end))
181+ {
182+ basic_block other_bb = NULL;
183+ FOR_EACH_EDGE (e, ei, bb->succs)
184+ {
185+ if (e->flags & EDGE_FALLTHRU)
186+ other_bb = e->dest;
187+ else
188+ e->flags &= ~EDGE_CAN_FALLTHRU;
189+ }
190+ FOR_EACH_EDGE (e, ei, other_bb->preds)
191+ {
192+ if (!(e->flags & EDGE_FALLTHRU))
193+ e->flags &= ~EDGE_CAN_FALLTHRU;
194+ }
195+ }
196+ }
197 }
198
199 /* Find unreachable blocks. An unreachable block will have 0 in
200
201=== modified file 'gcc/cfglayout.c'
202--- old/gcc/cfglayout.c 2010-05-17 16:30:54 +0000
203+++ new/gcc/cfglayout.c 2011-01-05 12:12:18 +0000
204@@ -766,6 +766,7 @@
205 {
206 edge e_fall, e_taken, e;
207 rtx bb_end_insn;
208+ rtx ret_label = NULL_RTX;
209 basic_block nb;
210 edge_iterator ei;
211
212@@ -785,6 +786,7 @@
213 bb_end_insn = BB_END (bb);
214 if (JUMP_P (bb_end_insn))
215 {
216+ ret_label = JUMP_LABEL (bb_end_insn);
217 if (any_condjump_p (bb_end_insn))
218 {
219 /* This might happen if the conditional jump has side
220@@ -899,7 +901,7 @@
221 }
222
223 /* We got here if we need to add a new jump insn. */
224- nb = force_nonfallthru (e_fall);
225+ nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
226 if (nb)
227 {
228 nb->il.rtl->visited = 1;
229@@ -1118,24 +1120,30 @@
230 bool
231 cfg_layout_can_duplicate_bb_p (const_basic_block bb)
232 {
233+ rtx insn;
234+
235 /* Do not attempt to duplicate tablejumps, as we need to unshare
236 the dispatch table. This is difficult to do, as the instructions
237 computing jump destination may be hoisted outside the basic block. */
238 if (tablejump_p (BB_END (bb), NULL, NULL))
239 return false;
240
241- /* Do not duplicate blocks containing insns that can't be copied. */
242- if (targetm.cannot_copy_insn_p)
243+ insn = BB_HEAD (bb);
244+ while (1)
245 {
246- rtx insn = BB_HEAD (bb);
247- while (1)
248- {
249- if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
250- return false;
251- if (insn == BB_END (bb))
252- break;
253- insn = NEXT_INSN (insn);
254- }
255+ /* Do not duplicate blocks containing insns that can't be copied. */
256+ if (INSN_P (insn) && targetm.cannot_copy_insn_p
257+ && targetm.cannot_copy_insn_p (insn))
258+ return false;
259+ /* dwarf2out expects that these notes are always paired with a
260+ returnjump or sibling call. */
261+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG
262+ && !returnjump_p (BB_END (bb))
263+ && (!CALL_P (BB_END (bb)) || !SIBLING_CALL_P (BB_END (bb))))
264+ return false;
265+ if (insn == BB_END (bb))
266+ break;
267+ insn = NEXT_INSN (insn);
268 }
269
270 return true;
271@@ -1167,6 +1175,9 @@
272 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
273 break;
274 copy = emit_copy_of_insn_after (insn, get_last_insn ());
275+ if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
276+ && ANY_RETURN_P (JUMP_LABEL (insn)))
277+ JUMP_LABEL (copy) = JUMP_LABEL (insn);
278 maybe_copy_epilogue_insn (insn, copy);
279 break;
280
281
282=== modified file 'gcc/cfgrtl.c'
283--- old/gcc/cfgrtl.c 2010-09-20 21:30:35 +0000
284+++ new/gcc/cfgrtl.c 2011-01-05 12:12:18 +0000
285@@ -1107,10 +1107,13 @@
286 }
287
288 /* Like force_nonfallthru below, but additionally performs redirection
289- Used by redirect_edge_and_branch_force. */
290+ Used by redirect_edge_and_branch_force. JUMP_LABEL is used only
291+ when redirecting to the EXIT_BLOCK, it is either a return or a
292+ simple_return rtx indicating which kind of returnjump to create.
293+ It should be NULL otherwise. */
294
295-static basic_block
296-force_nonfallthru_and_redirect (edge e, basic_block target)
297+basic_block
298+force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
299 {
300 basic_block jump_block, new_bb = NULL, src = e->src;
301 rtx note;
302@@ -1242,11 +1245,25 @@
303 e->flags &= ~EDGE_FALLTHRU;
304 if (target == EXIT_BLOCK_PTR)
305 {
306+ if (jump_label == ret_rtx)
307+ {
308 #ifdef HAVE_return
309- emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc);
310-#else
311- gcc_unreachable ();
312-#endif
313+ emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block),
314+ loc);
315+#else
316+ gcc_unreachable ();
317+#endif
318+ }
319+ else
320+ {
321+ gcc_assert (jump_label == simple_return_rtx);
322+#ifdef HAVE_simple_return
323+ emit_jump_insn_after_setloc (gen_simple_return (),
324+ BB_END (jump_block), loc);
325+#else
326+ gcc_unreachable ();
327+#endif
328+ }
329 }
330 else
331 {
332@@ -1273,7 +1290,7 @@
333 basic_block
334 force_nonfallthru (edge e)
335 {
336- return force_nonfallthru_and_redirect (e, e->dest);
337+ return force_nonfallthru_and_redirect (e, e->dest, NULL_RTX);
338 }
339
340 /* Redirect edge even at the expense of creating new jump insn or
341@@ -1290,7 +1307,7 @@
342 /* In case the edge redirection failed, try to force it to be non-fallthru
343 and redirect newly created simplejump. */
344 df_set_bb_dirty (e->src);
345- return force_nonfallthru_and_redirect (e, target);
346+ return force_nonfallthru_and_redirect (e, target, NULL_RTX);
347 }
348
349 /* The given edge should potentially be a fallthru edge. If that is in
350
351=== modified file 'gcc/common.opt'
352--- old/gcc/common.opt 2010-12-10 15:33:37 +0000
353+++ new/gcc/common.opt 2011-01-05 12:12:18 +0000
354@@ -1147,6 +1147,11 @@
355 Common C ObjC C++ ObjC++ Report Var(flag_show_column) Init(1)
356 Show column numbers in diagnostics, when available. Default on
357
358+fshrink-wrap
359+Common Report Var(flag_shrink_wrap) Optimization
360+Emit function prologues only before parts of the function that need it,
361+rather than at the top of the function.
362+
363 fsignaling-nans
364 Common Report Var(flag_signaling_nans) Optimization
365 Disable optimizations observable by IEEE signaling NaNs
366
367=== modified file 'gcc/config/arm/arm-protos.h'
368--- old/gcc/config/arm/arm-protos.h 2010-11-04 10:45:05 +0000
369+++ new/gcc/config/arm/arm-protos.h 2011-01-05 12:12:18 +0000
370@@ -26,6 +26,7 @@
371 extern void arm_override_options (void);
372 extern void arm_optimization_options (int, int);
373 extern int use_return_insn (int, rtx);
374+extern bool use_simple_return_p (void);
375 extern enum reg_class arm_regno_class (int);
376 extern void arm_load_pic_register (unsigned long);
377 extern int arm_volatile_func (void);
378@@ -137,7 +138,7 @@
379 extern const char *output_add_immediate (rtx *);
380 extern const char *arithmetic_instr (rtx, int);
381 extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
382-extern const char *output_return_instruction (rtx, int, int);
383+extern const char *output_return_instruction (rtx, bool, bool, bool);
384 extern void arm_poke_function_name (FILE *, const char *);
385 extern void arm_print_operand (FILE *, rtx, int);
386 extern void arm_print_operand_address (FILE *, rtx);
387
388=== modified file 'gcc/config/arm/arm.c'
389--- old/gcc/config/arm/arm.c 2011-01-05 11:32:50 +0000
390+++ new/gcc/config/arm/arm.c 2011-01-05 12:12:18 +0000
391@@ -2163,6 +2163,18 @@
392 return addr;
393 }
394
395+/* Return true if we should try to use a simple_return insn, i.e. perform
396+ shrink-wrapping if possible. This is the case if we need to emit a
397+ prologue, which we can test by looking at the offsets. */
398+bool
399+use_simple_return_p (void)
400+{
401+ arm_stack_offsets *offsets;
402+
403+ offsets = arm_get_frame_offsets ();
404+ return offsets->outgoing_args != 0;
405+}
406+
407 /* Return 1 if it is possible to return using a single instruction.
408 If SIBLING is non-null, this is a test for a return before a sibling
409 call. SIBLING is the call insn, so we can examine its register usage. */
410@@ -11284,6 +11296,7 @@
411
412 if (GET_CODE (insn) == JUMP_INSN
413 && JUMP_LABEL (insn) != NULL
414+ && !ANY_RETURN_P (JUMP_LABEL (insn))
415 && ((table = next_real_insn (JUMP_LABEL (insn)))
416 == next_real_insn (insn))
417 && table != NULL
418@@ -14168,7 +14181,7 @@
419 /* Generate a function exit sequence. If REALLY_RETURN is false, then do
420 everything bar the final return instruction. */
421 const char *
422-output_return_instruction (rtx operand, int really_return, int reverse)
423+output_return_instruction (rtx operand, bool really_return, bool reverse, bool simple)
424 {
425 char conditional[10];
426 char instr[100];
427@@ -14206,10 +14219,15 @@
428
429 sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd');
430
431- cfun->machine->return_used_this_function = 1;
432+ if (simple)
433+ live_regs_mask = 0;
434+ else
435+ {
436+ cfun->machine->return_used_this_function = 1;
437
438- offsets = arm_get_frame_offsets ();
439- live_regs_mask = offsets->saved_regs_mask;
440+ offsets = arm_get_frame_offsets ();
441+ live_regs_mask = offsets->saved_regs_mask;
442+ }
443
444 if (live_regs_mask)
445 {
446@@ -17108,6 +17126,7 @@
447
448 /* If we start with a return insn, we only succeed if we find another one. */
449 int seeking_return = 0;
450+ enum rtx_code return_code = UNKNOWN;
451
452 /* START_INSN will hold the insn from where we start looking. This is the
453 first insn after the following code_label if REVERSE is true. */
454@@ -17146,7 +17165,7 @@
455 else
456 return;
457 }
458- else if (GET_CODE (body) == RETURN)
459+ else if (ANY_RETURN_P (body))
460 {
461 start_insn = next_nonnote_insn (start_insn);
462 if (GET_CODE (start_insn) == BARRIER)
463@@ -17157,6 +17176,7 @@
464 {
465 reverse = TRUE;
466 seeking_return = 1;
467+ return_code = GET_CODE (body);
468 }
469 else
470 return;
471@@ -17197,11 +17217,15 @@
472 label = XEXP (XEXP (SET_SRC (body), 2), 0);
473 then_not_else = FALSE;
474 }
475- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN)
476- seeking_return = 1;
477- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
478+ else if (ANY_RETURN_P (XEXP (SET_SRC (body), 1)))
479+ {
480+ seeking_return = 1;
481+ return_code = GET_CODE (XEXP (SET_SRC (body), 1));
482+ }
483+ else if (ANY_RETURN_P (XEXP (SET_SRC (body), 2)))
484 {
485 seeking_return = 1;
486+ return_code = GET_CODE (XEXP (SET_SRC (body), 2));
487 then_not_else = FALSE;
488 }
489 else
490@@ -17302,8 +17326,7 @@
491 && !use_return_insn (TRUE, NULL)
492 && !optimize_size)
493 fail = TRUE;
494- else if (GET_CODE (scanbody) == RETURN
495- && seeking_return)
496+ else if (GET_CODE (scanbody) == return_code)
497 {
498 arm_ccfsm_state = 2;
499 succeed = TRUE;
500
501=== modified file 'gcc/config/arm/arm.h'
502--- old/gcc/config/arm/arm.h 2010-11-11 11:12:14 +0000
503+++ new/gcc/config/arm/arm.h 2011-01-05 12:12:18 +0000
504@@ -2622,6 +2622,8 @@
505 #define RETURN_ADDR_RTX(COUNT, FRAME) \
506 arm_return_addr (COUNT, FRAME)
507
508+#define RETURN_ADDR_REGNUM LR_REGNUM
509+
510 /* Mask of the bits in the PC that contain the real return address
511 when running in 26-bit mode. */
512 #define RETURN_ADDR_MASK26 (0x03fffffc)
513
514=== modified file 'gcc/config/arm/arm.md'
515--- old/gcc/config/arm/arm.md 2011-01-05 11:52:16 +0000
516+++ new/gcc/config/arm/arm.md 2011-01-05 12:12:18 +0000
517@@ -8882,66 +8882,72 @@
518 [(set_attr "type" "call")]
519 )
520
521-(define_expand "return"
522- [(return)]
523- "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
524+;; Both kinds of return insn.
525+(define_code_iterator returns [return simple_return])
526+(define_code_attr return_str [(return "") (simple_return "simple_")])
527+(define_code_attr return_simple_p [(return "false") (simple_return "true")])
528+(define_code_attr return_cond [(return " && USE_RETURN_INSN (FALSE)")
529+ (simple_return " && use_simple_return_p ()")])
530+
531+(define_expand "<return_str>return"
532+ [(returns)]
533+ "TARGET_32BIT<return_cond>"
534 "")
535
536-;; Often the return insn will be the same as loading from memory, so set attr
537-(define_insn "*arm_return"
538- [(return)]
539- "TARGET_ARM && USE_RETURN_INSN (FALSE)"
540- "*
541- {
542- if (arm_ccfsm_state == 2)
543- {
544- arm_ccfsm_state += 2;
545- return \"\";
546- }
547- return output_return_instruction (const_true_rtx, TRUE, FALSE);
548- }"
549+(define_insn "*arm_<return_str>return"
550+ [(returns)]
551+ "TARGET_ARM<return_cond>"
552+{
553+ if (arm_ccfsm_state == 2)
554+ {
555+ arm_ccfsm_state += 2;
556+ return "";
557+ }
558+ return output_return_instruction (const_true_rtx, true, false,
559+ <return_simple_p>);
560+}
561 [(set_attr "type" "load1")
562 (set_attr "length" "12")
563 (set_attr "predicable" "yes")]
564 )
565
566-(define_insn "*cond_return"
567+(define_insn "*cond_<return_str>return"
568 [(set (pc)
569 (if_then_else (match_operator 0 "arm_comparison_operator"
570 [(match_operand 1 "cc_register" "") (const_int 0)])
571- (return)
572+ (returns)
573 (pc)))]
574- "TARGET_ARM && USE_RETURN_INSN (TRUE)"
575- "*
576- {
577- if (arm_ccfsm_state == 2)
578- {
579- arm_ccfsm_state += 2;
580- return \"\";
581- }
582- return output_return_instruction (operands[0], TRUE, FALSE);
583- }"
584+ "TARGET_ARM<return_cond>"
585+{
586+ if (arm_ccfsm_state == 2)
587+ {
588+ arm_ccfsm_state += 2;
589+ return "";
590+ }
591+ return output_return_instruction (operands[0], true, false,
592+ <return_simple_p>);
593+}
594 [(set_attr "conds" "use")
595 (set_attr "length" "12")
596 (set_attr "type" "load1")]
597 )
598
599-(define_insn "*cond_return_inverted"
600+(define_insn "*cond_<return_str>return_inverted"
601 [(set (pc)
602 (if_then_else (match_operator 0 "arm_comparison_operator"
603 [(match_operand 1 "cc_register" "") (const_int 0)])
604 (pc)
605- (return)))]
606- "TARGET_ARM && USE_RETURN_INSN (TRUE)"
607- "*
608- {
609- if (arm_ccfsm_state == 2)
610- {
611- arm_ccfsm_state += 2;
612- return \"\";
613- }
614- return output_return_instruction (operands[0], TRUE, TRUE);
615- }"
616+ (returns)))]
617+ "TARGET_ARM<return_cond>"
618+{
619+ if (arm_ccfsm_state == 2)
620+ {
621+ arm_ccfsm_state += 2;
622+ return "";
623+ }
624+ return output_return_instruction (operands[0], true, true,
625+ <return_simple_p>);
626+}
627 [(set_attr "conds" "use")
628 (set_attr "length" "12")
629 (set_attr "type" "load1")]
630@@ -10809,8 +10815,7 @@
631 DONE;
632 }
633 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
634- gen_rtvec (1,
635- gen_rtx_RETURN (VOIDmode)),
636+ gen_rtvec (1, ret_rtx),
637 VUNSPEC_EPILOGUE));
638 DONE;
639 "
640@@ -10827,7 +10832,7 @@
641 "TARGET_32BIT"
642 "*
643 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
644- return output_return_instruction (const_true_rtx, FALSE, FALSE);
645+ return output_return_instruction (const_true_rtx, false, false, false);
646 return arm_output_epilogue (next_nonnote_insn (insn));
647 "
648 ;; Length is absolute worst case
649
650=== modified file 'gcc/config/arm/thumb2.md'
651--- old/gcc/config/arm/thumb2.md 2010-09-22 05:54:42 +0000
652+++ new/gcc/config/arm/thumb2.md 2011-01-05 12:12:18 +0000
653@@ -1020,16 +1020,15 @@
654
655 ;; Note: this is not predicable, to avoid issues with linker-generated
656 ;; interworking stubs.
657-(define_insn "*thumb2_return"
658- [(return)]
659- "TARGET_THUMB2 && USE_RETURN_INSN (FALSE)"
660- "*
661- {
662- return output_return_instruction (const_true_rtx, TRUE, FALSE);
663- }"
664+(define_insn "*thumb2_<return_str>return"
665+ [(returns)]
666+ "TARGET_THUMB2<return_cond>"
667+{
668+ return output_return_instruction (const_true_rtx, true, false,
669+ <return_simple_p>);
670+}
671 [(set_attr "type" "load1")
672- (set_attr "length" "12")]
673-)
674+ (set_attr "length" "12")])
675
676 (define_insn_and_split "thumb2_eh_return"
677 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
678
679=== modified file 'gcc/config/i386/i386.c'
680--- old/gcc/config/i386/i386.c 2010-11-16 18:05:53 +0000
681+++ new/gcc/config/i386/i386.c 2011-01-05 12:12:18 +0000
682@@ -9308,13 +9308,13 @@
683
684 pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
685 popc, -1, true);
686- emit_jump_insn (gen_return_indirect_internal (ecx));
687+ emit_jump_insn (gen_simple_return_indirect_internal (ecx));
688 }
689 else
690- emit_jump_insn (gen_return_pop_internal (popc));
691+ emit_jump_insn (gen_simple_return_pop_internal (popc));
692 }
693 else
694- emit_jump_insn (gen_return_internal ());
695+ emit_jump_insn (gen_simple_return_internal ());
696
697 /* Restore the state back to the state from the prologue,
698 so that it's correct for the next epilogue. */
699@@ -26596,7 +26596,7 @@
700 rtx prev;
701 bool replace = false;
702
703- if (!JUMP_P (ret) || GET_CODE (PATTERN (ret)) != RETURN
704+ if (!JUMP_P (ret) || !ANY_RETURN_P (PATTERN (ret))
705 || optimize_bb_for_size_p (bb))
706 continue;
707 for (prev = PREV_INSN (ret); prev; prev = PREV_INSN (prev))
708@@ -26626,7 +26626,10 @@
709 }
710 if (replace)
711 {
712- emit_jump_insn_before (gen_return_internal_long (), ret);
713+ if (PATTERN (ret) == ret_rtx)
714+ emit_jump_insn_before (gen_return_internal_long (), ret);
715+ else
716+ emit_jump_insn_before (gen_simple_return_internal_long (), ret);
717 delete_insn (ret);
718 }
719 }
720
721=== modified file 'gcc/config/i386/i386.md'
722--- old/gcc/config/i386/i386.md 2010-11-27 15:24:12 +0000
723+++ new/gcc/config/i386/i386.md 2011-01-05 12:12:18 +0000
724@@ -13797,24 +13797,29 @@
725 ""
726 [(set_attr "length" "0")])
727
728+(define_code_iterator returns [return simple_return])
729+(define_code_attr return_str [(return "") (simple_return "simple_")])
730+(define_code_attr return_cond [(return "ix86_can_use_return_insn_p ()")
731+ (simple_return "")])
732+
733 ;; Insn emitted into the body of a function to return from a function.
734 ;; This is only done if the function's epilogue is known to be simple.
735 ;; See comments for ix86_can_use_return_insn_p in i386.c.
736
737-(define_expand "return"
738- [(return)]
739- "ix86_can_use_return_insn_p ()"
740+(define_expand "<return_str>return"
741+ [(returns)]
742+ "<return_cond>"
743 {
744 if (crtl->args.pops_args)
745 {
746 rtx popc = GEN_INT (crtl->args.pops_args);
747- emit_jump_insn (gen_return_pop_internal (popc));
748+ emit_jump_insn (gen_<return_str>return_pop_internal (popc));
749 DONE;
750 }
751 })
752
753-(define_insn "return_internal"
754- [(return)]
755+(define_insn "<return_str>return_internal"
756+ [(returns)]
757 "reload_completed"
758 "ret"
759 [(set_attr "length" "1")
760@@ -13825,8 +13830,8 @@
761 ;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
762 ;; instruction Athlon and K8 have.
763
764-(define_insn "return_internal_long"
765- [(return)
766+(define_insn "<return_str>return_internal_long"
767+ [(returns)
768 (unspec [(const_int 0)] UNSPEC_REP)]
769 "reload_completed"
770 "rep\;ret"
771@@ -13836,8 +13841,8 @@
772 (set_attr "prefix_rep" "1")
773 (set_attr "modrm" "0")])
774
775-(define_insn "return_pop_internal"
776- [(return)
777+(define_insn "<return_str>return_pop_internal"
778+ [(returns)
779 (use (match_operand:SI 0 "const_int_operand" ""))]
780 "reload_completed"
781 "ret\t%0"
782@@ -13846,8 +13851,8 @@
783 (set_attr "length_immediate" "2")
784 (set_attr "modrm" "0")])
785
786-(define_insn "return_indirect_internal"
787- [(return)
788+(define_insn "<return_str>return_indirect_internal"
789+ [(returns)
790 (use (match_operand:SI 0 "register_operand" "r"))]
791 "reload_completed"
792 "jmp\t%A0"
793
794=== modified file 'gcc/config/mips/mips.c'
795--- old/gcc/config/mips/mips.c 2010-11-21 10:38:43 +0000
796+++ new/gcc/config/mips/mips.c 2011-01-05 12:12:18 +0000
797@@ -10497,7 +10497,8 @@
798 regno = GP_REG_FIRST + 7;
799 else
800 regno = RETURN_ADDR_REGNUM;
801- emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, regno)));
802+ emit_jump_insn (gen_simple_return_internal (gen_rtx_REG (Pmode,
803+ regno)));
804 }
805 }
806
807
808=== modified file 'gcc/config/mips/mips.md'
809--- old/gcc/config/mips/mips.md 2010-04-02 18:54:46 +0000
810+++ new/gcc/config/mips/mips.md 2011-01-05 12:12:18 +0000
811@@ -5815,6 +5815,18 @@
812 [(set_attr "type" "jump")
813 (set_attr "mode" "none")])
814
815+(define_expand "simple_return"
816+ [(simple_return)]
817+ "!mips_can_use_return_insn ()"
818+ { mips_expand_before_return (); })
819+
820+(define_insn "*simple_return"
821+ [(simple_return)]
822+ "!mips_can_use_return_insn ()"
823+ "%*j\t$31%/"
824+ [(set_attr "type" "jump")
825+ (set_attr "mode" "none")])
826+
827 ;; Normal return.
828
829 (define_insn "return_internal"
830@@ -5825,6 +5837,14 @@
831 [(set_attr "type" "jump")
832 (set_attr "mode" "none")])
833
834+(define_insn "simple_return_internal"
835+ [(simple_return)
836+ (use (match_operand 0 "pmode_register_operand" ""))]
837+ ""
838+ "%*j\t%0%/"
839+ [(set_attr "type" "jump")
840+ (set_attr "mode" "none")])
841+
842 ;; Exception return.
843 (define_insn "mips_eret"
844 [(return)
845
846=== modified file 'gcc/config/sh/sh.c'
847--- old/gcc/config/sh/sh.c 2010-12-10 15:34:19 +0000
848+++ new/gcc/config/sh/sh.c 2011-01-05 12:12:18 +0000
849@@ -5252,7 +5252,8 @@
850 }
851 if (prev
852 && JUMP_P (prev)
853- && JUMP_LABEL (prev))
854+ && JUMP_LABEL (prev)
855+ && !ANY_RETURN_P (JUMP_LABEL (prev)))
856 {
857 rtx x;
858 if (jump_to_next
859@@ -5951,7 +5952,7 @@
860 JUMP_LABEL (insn) = far_label;
861 LABEL_NUSES (far_label)++;
862 }
863- redirect_jump (insn, NULL_RTX, 1);
864+ redirect_jump (insn, ret_rtx, 1);
865 far_label = 0;
866 }
867 }
868
869=== modified file 'gcc/df-scan.c'
870--- old/gcc/df-scan.c 2010-11-16 22:17:17 +0000
871+++ new/gcc/df-scan.c 2011-01-05 12:12:18 +0000
872@@ -3296,6 +3296,7 @@
873 }
874
875 case RETURN:
876+ case SIMPLE_RETURN:
877 break;
878
879 case ASM_OPERANDS:
880
881=== modified file 'gcc/doc/invoke.texi'
882--- old/gcc/doc/invoke.texi 2010-11-04 14:29:09 +0000
883+++ new/gcc/doc/invoke.texi 2011-01-05 12:12:18 +0000
884@@ -5750,6 +5750,7 @@
885 -fipa-pure-const @gol
886 -fipa-reference @gol
887 -fmerge-constants
888+-fshrink-wrap @gol
889 -fsplit-wide-types @gol
890 -ftree-builtin-call-dce @gol
891 -ftree-ccp @gol
892@@ -6504,6 +6505,12 @@
893 When pipelining loops during selective scheduling, also pipeline outer loops.
894 This option has no effect until @option{-fsel-sched-pipelining} is turned on.
895
896+@item -fshrink-wrap
897+@opindex fshrink-wrap
898+Emit function prologues only before parts of the function that need it,
899+rather than at the top of the function. This flag is enabled by default at
900+@option{-O} and higher.
901+
902 @item -fcaller-saves
903 @opindex fcaller-saves
904 Enable values to be allocated in registers that will be clobbered by
905
906=== modified file 'gcc/doc/md.texi'
907--- old/gcc/doc/md.texi 2009-12-15 18:36:44 +0000
908+++ new/gcc/doc/md.texi 2011-01-05 12:12:18 +0000
909@@ -4801,7 +4801,19 @@
910 multiple instructions are usually needed to return from a function, but
911 some class of functions only requires one instruction to implement a
912 return. Normally, the applicable functions are those which do not need
913-to save any registers or allocate stack space.
914+to save any registers or allocate stack space, although some targets
915+have instructions that can perform both the epilogue and function return
916+in one instruction.
917+
918+@cindex @code{simple_return} instruction pattern
919+@item @samp{simple_return}
920+Subroutine return instruction. This instruction pattern name should be
921+defined only if a single instruction can do all the work of returning
922+from a function on a path where no epilogue is required. This pattern
923+is very similar to the @code{return} instruction pattern, but it is emitted
924+only by the shrink-wrapping optimization on paths where the function
925+prologue has not been executed, and a function return should occur without
926+any of the effects of the epilogue.
927
928 @findex reload_completed
929 @findex leaf_function_p
930
931=== modified file 'gcc/doc/rtl.texi'
932--- old/gcc/doc/rtl.texi 2010-07-06 19:23:53 +0000
933+++ new/gcc/doc/rtl.texi 2011-01-05 12:12:18 +0000
934@@ -2888,6 +2888,13 @@
935 Note that an insn pattern of @code{(return)} is logically equivalent to
936 @code{(set (pc) (return))}, but the latter form is never used.
937
938+@findex simple_return
939+@item (simple_return)
940+Like @code{(return)}, but truly represents only a function return, while
941+@code{(return)} may represent an insn that also performs other functions
942+of the function epilogue. Like @code{(return)}, this may also occur in
943+conditional jumps.
944+
945 @findex call
946 @item (call @var{function} @var{nargs})
947 Represents a function call. @var{function} is a @code{mem} expression
948@@ -3017,7 +3024,7 @@
949 brackets stand for a vector; the operand of @code{parallel} is a
950 vector of expressions. @var{x0}, @var{x1} and so on are individual
951 side effect expressions---expressions of code @code{set}, @code{call},
952-@code{return}, @code{clobber} or @code{use}.
953+@code{return}, @code{simple_return}, @code{clobber} or @code{use}.
954
955 ``In parallel'' means that first all the values used in the individual
956 side-effects are computed, and second all the actual side-effects are
957@@ -3656,14 +3663,16 @@
958 @table @code
959 @findex PATTERN
960 @item PATTERN (@var{i})
961-An expression for the side effect performed by this insn. This must be
962-one of the following codes: @code{set}, @code{call}, @code{use},
963-@code{clobber}, @code{return}, @code{asm_input}, @code{asm_output},
964-@code{addr_vec}, @code{addr_diff_vec}, @code{trap_if}, @code{unspec},
965-@code{unspec_volatile}, @code{parallel}, @code{cond_exec}, or @code{sequence}. If it is a @code{parallel},
966-each element of the @code{parallel} must be one these codes, except that
967-@code{parallel} expressions cannot be nested and @code{addr_vec} and
968-@code{addr_diff_vec} are not permitted inside a @code{parallel} expression.
969+An expression for the side effect performed by this insn. This must
970+be one of the following codes: @code{set}, @code{call}, @code{use},
971+@code{clobber}, @code{return}, @code{simple_return}, @code{asm_input},
972+@code{asm_output}, @code{addr_vec}, @code{addr_diff_vec},
973+@code{trap_if}, @code{unspec}, @code{unspec_volatile},
974+@code{parallel}, @code{cond_exec}, or @code{sequence}. If it is a
975+@code{parallel}, each element of the @code{parallel} must be one these
976+codes, except that @code{parallel} expressions cannot be nested and
977+@code{addr_vec} and @code{addr_diff_vec} are not permitted inside a
978+@code{parallel} expression.
979
980 @findex INSN_CODE
981 @item INSN_CODE (@var{i})
982
983=== modified file 'gcc/doc/tm.texi'
984--- old/gcc/doc/tm.texi 2010-09-01 13:29:58 +0000
985+++ new/gcc/doc/tm.texi 2011-01-05 12:12:18 +0000
986@@ -3287,6 +3287,12 @@
987 from the frame pointer of the previous stack frame.
988 @end defmac
989
990+@defmac RETURN_ADDR_REGNUM
991+If defined, a C expression whose value is the register number of the return
992+address for the current function. Targets that pass the return address on
993+the stack should not define this macro.
994+@end defmac
995+
996 @defmac INCOMING_RETURN_ADDR_RTX
997 A C expression whose value is RTL representing the location of the
998 incoming return address at the beginning of any function, before the
999
1000=== modified file 'gcc/dwarf2out.c'
1001--- old/gcc/dwarf2out.c 2010-12-21 18:46:10 +0000
1002+++ new/gcc/dwarf2out.c 2011-01-05 12:12:18 +0000
1003@@ -1396,7 +1396,7 @@
1004 {
1005 rtx dest = JUMP_LABEL (insn);
1006
1007- if (dest)
1008+ if (dest && !ANY_RETURN_P (dest))
1009 {
1010 if (barrier_args_size [INSN_UID (dest)] < 0)
1011 {
1012
1013=== modified file 'gcc/emit-rtl.c'
1014--- old/gcc/emit-rtl.c 2010-10-04 00:50:43 +0000
1015+++ new/gcc/emit-rtl.c 2011-01-05 12:12:18 +0000
1016@@ -2432,6 +2432,8 @@
1017 case CODE_LABEL:
1018 case PC:
1019 case CC0:
1020+ case RETURN:
1021+ case SIMPLE_RETURN:
1022 case SCRATCH:
1023 return;
1024 /* SCRATCH must be shared because they represent distinct values. */
1025@@ -3323,14 +3325,17 @@
1026 return insn;
1027 }
1028
1029-/* Return the last label to mark the same position as LABEL. Return null
1030- if LABEL itself is null. */
1031+/* Return the last label to mark the same position as LABEL. Return LABEL
1032+ itself if it is null or any return rtx. */
1033
1034 rtx
1035 skip_consecutive_labels (rtx label)
1036 {
1037 rtx insn;
1038
1039+ if (label && ANY_RETURN_P (label))
1040+ return label;
1041+
1042 for (insn = label; insn != 0 && !INSN_P (insn); insn = NEXT_INSN (insn))
1043 if (LABEL_P (insn))
1044 label = insn;
1045@@ -5209,7 +5214,7 @@
1046 return CODE_LABEL;
1047 if (GET_CODE (x) == CALL)
1048 return CALL_INSN;
1049- if (GET_CODE (x) == RETURN)
1050+ if (GET_CODE (x) == RETURN || GET_CODE (x) == SIMPLE_RETURN)
1051 return JUMP_INSN;
1052 if (GET_CODE (x) == SET)
1053 {
1054@@ -5715,8 +5720,10 @@
1055 init_reg_modes_target ();
1056
1057 /* Assign register numbers to the globally defined register rtx. */
1058- pc_rtx = gen_rtx_PC (VOIDmode);
1059- cc0_rtx = gen_rtx_CC0 (VOIDmode);
1060+ pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
1061+ ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
1062+ simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
1063+ cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
1064 stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
1065 frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
1066 hard_frame_pointer_rtx = gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
1067
1068=== modified file 'gcc/final.c'
1069--- old/gcc/final.c 2010-03-26 16:18:51 +0000
1070+++ new/gcc/final.c 2011-01-05 12:12:18 +0000
1071@@ -2428,7 +2428,7 @@
1072 delete_insn (insn);
1073 break;
1074 }
1075- else if (GET_CODE (SET_SRC (body)) == RETURN)
1076+ else if (ANY_RETURN_P (SET_SRC (body)))
1077 /* Replace (set (pc) (return)) with (return). */
1078 PATTERN (insn) = body = SET_SRC (body);
1079
1080
1081=== modified file 'gcc/function.c'
1082--- old/gcc/function.c 2010-08-16 19:18:08 +0000
1083+++ new/gcc/function.c 2011-01-05 12:12:18 +0000
1084@@ -147,9 +147,6 @@
1085 can always export `prologue_epilogue_contains'. */
1086 static void record_insns (rtx, rtx, htab_t *) ATTRIBUTE_UNUSED;
1087 static bool contains (const_rtx, htab_t);
1088-#ifdef HAVE_return
1089-static void emit_return_into_block (basic_block);
1090-#endif
1091 static void prepare_function_start (void);
1092 static void do_clobber_return_reg (rtx, void *);
1093 static void do_use_return_reg (rtx, void *);
1094@@ -4987,35 +4984,189 @@
1095 return 0;
1096 }
1097
1098+#ifdef HAVE_simple_return
1099+/* This collects sets and clobbers of hard registers in a HARD_REG_SET,
1100+ which is pointed to by DATA. */
1101+static void
1102+record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
1103+{
1104+ HARD_REG_SET *pset = (HARD_REG_SET *)data;
1105+ if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
1106+ {
1107+ int nregs = hard_regno_nregs[REGNO (x)][GET_MODE (x)];
1108+ while (nregs-- > 0)
1109+ SET_HARD_REG_BIT (*pset, REGNO (x) + nregs);
1110+ }
1111+}
1112+
1113+/* A subroutine of requires_stack_frame_p, called via for_each_rtx.
1114+ If any change is made, set CHANGED
1115+ to true. */
1116+
1117+static int
1118+frame_required_for_rtx (rtx *loc, void *data ATTRIBUTE_UNUSED)
1119+{
1120+ rtx x = *loc;
1121+ if (x == stack_pointer_rtx || x == hard_frame_pointer_rtx
1122+ || x == arg_pointer_rtx || x == pic_offset_table_rtx
1123+#ifdef RETURN_ADDR_REGNUM
1124+ || (REG_P (x) && REGNO (x) == RETURN_ADDR_REGNUM)
1125+#endif
1126+ )
1127+ return 1;
1128+ return 0;
1129+}
1130+
1131+static bool
1132+requires_stack_frame_p (rtx insn)
1133+{
1134+ HARD_REG_SET hardregs;
1135+ unsigned regno;
1136+
1137+ if (!INSN_P (insn) || DEBUG_INSN_P (insn))
1138+ return false;
1139+ if (CALL_P (insn))
1140+ return !SIBLING_CALL_P (insn);
1141+ if (for_each_rtx (&PATTERN (insn), frame_required_for_rtx, NULL))
1142+ return true;
1143+ CLEAR_HARD_REG_SET (hardregs);
1144+ note_stores (PATTERN (insn), record_hard_reg_sets, &hardregs);
1145+ AND_COMPL_HARD_REG_SET (hardregs, call_used_reg_set);
1146+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1147+ if (TEST_HARD_REG_BIT (hardregs, regno)
1148+ && df_regs_ever_live_p (regno))
1149+ return true;
1150+ return false;
1151+}
1152+#endif
1153+
1154 #ifdef HAVE_return
1155-/* Insert gen_return at the end of block BB. This also means updating
1156- block_for_insn appropriately. */
1157+
1158+static rtx
1159+gen_return_pattern (bool simple_p)
1160+{
1161+#ifdef HAVE_simple_return
1162+ return simple_p ? gen_simple_return () : gen_return ();
1163+#else
1164+ gcc_assert (!simple_p);
1165+ return gen_return ();
1166+#endif
1167+}
1168+
1169+/* Insert an appropriate return pattern at the end of block BB. This
1170+ also means updating block_for_insn appropriately. */
1171
1172 static void
1173-emit_return_into_block (basic_block bb)
1174+emit_return_into_block (bool simple_p, basic_block bb)
1175 {
1176- emit_jump_insn_after (gen_return (), BB_END (bb));
1177+ rtx jump;
1178+ jump = emit_jump_insn_after (gen_return_pattern (simple_p), BB_END (bb));
1179+ JUMP_LABEL (jump) = simple_p ? simple_return_rtx : ret_rtx;
1180 }
1181-#endif /* HAVE_return */
1182+#endif
1183
1184 /* Generate the prologue and epilogue RTL if the machine supports it. Thread
1185 this into place with notes indicating where the prologue ends and where
1186- the epilogue begins. Update the basic block information when possible. */
1187+ the epilogue begins. Update the basic block information when possible.
1188+
1189+ Notes on epilogue placement:
1190+ There are several kinds of edges to the exit block:
1191+ * a single fallthru edge from LAST_BB
1192+ * possibly, edges from blocks containing sibcalls
1193+ * possibly, fake edges from infinite loops
1194+
1195+ The epilogue is always emitted on the fallthru edge from the last basic
1196+ block in the function, LAST_BB, into the exit block.
1197+
1198+ If LAST_BB is empty except for a label, it is the target of every
1199+ other basic block in the function that ends in a return. If a
1200+ target has a return or simple_return pattern (possibly with
1201+ conditional variants), these basic blocks can be changed so that a
1202+ return insn is emitted into them, and their target is adjusted to
1203+ the real exit block.
1204+
1205+ Notes on shrink wrapping: We implement a fairly conservative
1206+ version of shrink-wrapping rather than the textbook one. We only
1207+ generate a single prologue and a single epilogue. This is
1208+ sufficient to catch a number of interesting cases involving early
1209+ exits.
1210+
1211+ First, we identify the blocks that require the prologue to occur before
1212+ them. These are the ones that modify a call-saved register, or reference
1213+ any of the stack or frame pointer registers. To simplify things, we then
1214+ mark everything reachable from these blocks as also requiring a prologue.
1215+ This takes care of loops automatically, and avoids the need to examine
1216+ whether MEMs reference the frame, since it is sufficient to check for
1217+ occurrences of the stack or frame pointer.
1218+
1219+ We then compute the set of blocks for which the need for a prologue
1220+ is anticipatable (borrowing terminology from the shrink-wrapping
1221+ description in Muchnick's book). These are the blocks which either
1222+ require a prologue themselves, or those that have only successors
1223+ where the prologue is anticipatable. The prologue needs to be
1224+ inserted on all edges from BB1->BB2 where BB2 is in ANTIC and BB1
1225+ is not. For the moment, we ensure that only one such edge exists.
1226+
1227+ The epilogue is placed as described above, but we make a
1228+ distinction between inserting return and simple_return patterns
1229+ when modifying other blocks that end in a return. Blocks that end
1230+ in a sibcall omit the sibcall_epilogue if the block is not in
1231+ ANTIC. */
1232
1233 static void
1234 thread_prologue_and_epilogue_insns (void)
1235 {
1236 int inserted = 0;
1237+ basic_block last_bb;
1238+ bool last_bb_active;
1239+#ifdef HAVE_simple_return
1240+ bool unconverted_simple_returns = false;
1241+ basic_block simple_return_block = NULL;
1242+#endif
1243+ rtx returnjump ATTRIBUTE_UNUSED;
1244+ rtx seq ATTRIBUTE_UNUSED, epilogue_end ATTRIBUTE_UNUSED;
1245+ rtx prologue_seq ATTRIBUTE_UNUSED, split_prologue_seq ATTRIBUTE_UNUSED;
1246+ edge entry_edge, orig_entry_edge, exit_fallthru_edge;
1247 edge e;
1248-#if defined (HAVE_sibcall_epilogue) || defined (HAVE_epilogue) || defined (HAVE_return) || defined (HAVE_prologue)
1249- rtx seq;
1250-#endif
1251-#if defined (HAVE_epilogue) || defined(HAVE_return)
1252- rtx epilogue_end = NULL_RTX;
1253-#endif
1254 edge_iterator ei;
1255+ bitmap_head bb_flags;
1256+
1257+ df_analyze ();
1258
1259 rtl_profile_for_bb (ENTRY_BLOCK_PTR);
1260+
1261+ epilogue_end = NULL_RTX;
1262+
1263+ /* Can't deal with multiple successors of the entry block at the
1264+ moment. Function should always have at least one entry
1265+ point. */
1266+ gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
1267+ entry_edge = single_succ_edge (ENTRY_BLOCK_PTR);
1268+ orig_entry_edge = entry_edge;
1269+
1270+ exit_fallthru_edge = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
1271+ if (exit_fallthru_edge != NULL)
1272+ {
1273+ rtx label;
1274+
1275+ last_bb = exit_fallthru_edge->src;
1276+ /* Test whether there are active instructions in the last block. */
1277+ label = BB_END (last_bb);
1278+ while (label && !LABEL_P (label))
1279+ {
1280+ if (active_insn_p (label))
1281+ break;
1282+ label = PREV_INSN (label);
1283+ }
1284+
1285+ last_bb_active = BB_HEAD (last_bb) != label || !LABEL_P (label);
1286+ }
1287+ else
1288+ {
1289+ last_bb = NULL;
1290+ last_bb_active = false;
1291+ }
1292+
1293 #ifdef HAVE_prologue
1294 if (HAVE_prologue)
1295 {
1296@@ -5040,19 +5191,168 @@
1297 emit_insn (gen_blockage ());
1298 #endif
1299
1300- seq = get_insns ();
1301+ prologue_seq = get_insns ();
1302 end_sequence ();
1303 set_insn_locators (seq, prologue_locator);
1304-
1305- /* Can't deal with multiple successors of the entry block
1306- at the moment. Function should always have at least one
1307- entry point. */
1308- gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
1309-
1310- insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
1311- inserted = 1;
1312- }
1313-#endif
1314+ }
1315+#endif
1316+
1317+ bitmap_initialize (&bb_flags, &bitmap_default_obstack);
1318+
1319+#ifdef HAVE_simple_return
1320+ /* Try to perform a kind of shrink-wrapping, making sure the
1321+ prologue/epilogue is emitted only around those parts of the
1322+ function that require it. */
1323+
1324+ if (flag_shrink_wrap && HAVE_simple_return && !flag_non_call_exceptions
1325+ && HAVE_prologue && !crtl->calls_eh_return)
1326+ {
1327+ HARD_REG_SET prologue_clobbered, live_on_edge;
1328+ rtx p_insn;
1329+ VEC(basic_block, heap) *vec;
1330+ basic_block bb;
1331+ bitmap_head bb_antic_flags;
1332+ bitmap_head bb_on_list;
1333+
1334+ bitmap_initialize (&bb_antic_flags, &bitmap_default_obstack);
1335+ bitmap_initialize (&bb_on_list, &bitmap_default_obstack);
1336+
1337+ vec = VEC_alloc (basic_block, heap, n_basic_blocks);
1338+
1339+ FOR_EACH_BB (bb)
1340+ {
1341+ rtx insn;
1342+ FOR_BB_INSNS (bb, insn)
1343+ {
1344+ if (requires_stack_frame_p (insn))
1345+ {
1346+ bitmap_set_bit (&bb_flags, bb->index);
1347+ VEC_quick_push (basic_block, vec, bb);
1348+ break;
1349+ }
1350+ }
1351+ }
1352+
1353+ /* For every basic block that needs a prologue, mark all blocks
1354+ reachable from it, so as to ensure they are also seen as
1355+ requiring a prologue. */
1356+ while (!VEC_empty (basic_block, vec))
1357+ {
1358+ basic_block tmp_bb = VEC_pop (basic_block, vec);
1359+ edge e;
1360+ edge_iterator ei;
1361+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
1362+ {
1363+ if (e->dest == EXIT_BLOCK_PTR
1364+ || bitmap_bit_p (&bb_flags, e->dest->index))
1365+ continue;
1366+ bitmap_set_bit (&bb_flags, e->dest->index);
1367+ VEC_quick_push (basic_block, vec, e->dest);
1368+ }
1369+ }
1370+ /* If the last basic block contains only a label, we'll be able
1371+ to convert jumps to it to (potentially conditional) return
1372+ insns later. This means we don't necessarily need a prologue
1373+ for paths reaching it. */
1374+ if (last_bb)
1375+ {
1376+ if (!last_bb_active)
1377+ bitmap_clear_bit (&bb_flags, last_bb->index);
1378+ else if (!bitmap_bit_p (&bb_flags, last_bb->index))
1379+ goto fail_shrinkwrap;
1380+ }
1381+
1382+ /* Now walk backwards from every block that is marked as needing
1383+ a prologue to compute the bb_antic_flags bitmap. */
1384+ bitmap_copy (&bb_antic_flags, &bb_flags);
1385+ FOR_EACH_BB (bb)
1386+ {
1387+ edge e;
1388+ edge_iterator ei;
1389+ if (!bitmap_bit_p (&bb_flags, bb->index))
1390+ continue;
1391+ FOR_EACH_EDGE (e, ei, bb->preds)
1392+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1393+ {
1394+ VEC_quick_push (basic_block, vec, e->src);
1395+ bitmap_set_bit (&bb_on_list, e->src->index);
1396+ }
1397+ }
1398+ while (!VEC_empty (basic_block, vec))
1399+ {
1400+ basic_block tmp_bb = VEC_pop (basic_block, vec);
1401+ edge e;
1402+ edge_iterator ei;
1403+ bool all_set = true;
1404+
1405+ bitmap_clear_bit (&bb_on_list, tmp_bb->index);
1406+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
1407+ {
1408+ if (!bitmap_bit_p (&bb_antic_flags, e->dest->index))
1409+ {
1410+ all_set = false;
1411+ break;
1412+ }
1413+ }
1414+ if (all_set)
1415+ {
1416+ bitmap_set_bit (&bb_antic_flags, tmp_bb->index);
1417+ FOR_EACH_EDGE (e, ei, tmp_bb->preds)
1418+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1419+ {
1420+ VEC_quick_push (basic_block, vec, e->src);
1421+ bitmap_set_bit (&bb_on_list, e->src->index);
1422+ }
1423+ }
1424+ }
1425+ /* Find exactly one edge that leads to a block in ANTIC from
1426+ a block that isn't. */
1427+ if (!bitmap_bit_p (&bb_antic_flags, entry_edge->dest->index))
1428+ FOR_EACH_BB (bb)
1429+ {
1430+ if (!bitmap_bit_p (&bb_antic_flags, bb->index))
1431+ continue;
1432+ FOR_EACH_EDGE (e, ei, bb->preds)
1433+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1434+ {
1435+ if (entry_edge != orig_entry_edge)
1436+ {
1437+ entry_edge = orig_entry_edge;
1438+ goto fail_shrinkwrap;
1439+ }
1440+ entry_edge = e;
1441+ }
1442+ }
1443+
1444+ /* Test whether the prologue is known to clobber any register
1445+ (other than FP or SP) which are live on the edge. */
1446+ CLEAR_HARD_REG_SET (prologue_clobbered);
1447+ for (p_insn = prologue_seq; p_insn; p_insn = NEXT_INSN (p_insn))
1448+ if (NONDEBUG_INSN_P (p_insn))
1449+ note_stores (PATTERN (p_insn), record_hard_reg_sets,
1450+ &prologue_clobbered);
1451+ CLEAR_HARD_REG_BIT (prologue_clobbered, STACK_POINTER_REGNUM);
1452+ if (frame_pointer_needed)
1453+ CLEAR_HARD_REG_BIT (prologue_clobbered, HARD_FRAME_POINTER_REGNUM);
1454+
1455+ CLEAR_HARD_REG_SET (live_on_edge);
1456+ reg_set_to_hard_reg_set (&live_on_edge,
1457+ df_get_live_in (entry_edge->dest));
1458+ if (hard_reg_set_intersect_p (live_on_edge, prologue_clobbered))
1459+ entry_edge = orig_entry_edge;
1460+
1461+ fail_shrinkwrap:
1462+ bitmap_clear (&bb_antic_flags);
1463+ bitmap_clear (&bb_on_list);
1464+ VEC_free (basic_block, heap, vec);
1465+ }
1466+#endif
1467+
1468+ if (prologue_seq != NULL_RTX)
1469+ {
1470+ insert_insn_on_edge (prologue_seq, entry_edge);
1471+ inserted = true;
1472+ }
1473
1474 /* If the exit block has no non-fake predecessors, we don't need
1475 an epilogue. */
1476@@ -5063,100 +5363,130 @@
1477 goto epilogue_done;
1478
1479 rtl_profile_for_bb (EXIT_BLOCK_PTR);
1480+
1481 #ifdef HAVE_return
1482- if (optimize && HAVE_return)
1483+ /* If we're allowed to generate a simple return instruction, then by
1484+ definition we don't need a full epilogue. If the last basic
1485+ block before the exit block does not contain active instructions,
1486+ examine its predecessors and try to emit (conditional) return
1487+ instructions. */
1488+ if (optimize && !last_bb_active
1489+ && (HAVE_return || entry_edge != orig_entry_edge))
1490 {
1491- /* If we're allowed to generate a simple return instruction,
1492- then by definition we don't need a full epilogue. Examine
1493- the block that falls through to EXIT. If it does not
1494- contain any code, examine its predecessors and try to
1495- emit (conditional) return instructions. */
1496-
1497- basic_block last;
1498+ edge_iterator ei2;
1499+ int i;
1500+ basic_block bb;
1501 rtx label;
1502+ VEC(basic_block,heap) *src_bbs;
1503
1504- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1505- if (e->flags & EDGE_FALLTHRU)
1506- break;
1507- if (e == NULL)
1508+ if (exit_fallthru_edge == NULL)
1509 goto epilogue_done;
1510- last = e->src;
1511-
1512- /* Verify that there are no active instructions in the last block. */
1513- label = BB_END (last);
1514- while (label && !LABEL_P (label))
1515+ label = BB_HEAD (last_bb);
1516+
1517+ src_bbs = VEC_alloc (basic_block, heap, EDGE_COUNT (last_bb->preds));
1518+ FOR_EACH_EDGE (e, ei2, last_bb->preds)
1519+ if (e->src != ENTRY_BLOCK_PTR)
1520+ VEC_quick_push (basic_block, src_bbs, e->src);
1521+
1522+ FOR_EACH_VEC_ELT (basic_block, src_bbs, i, bb)
1523 {
1524- if (active_insn_p (label))
1525- break;
1526- label = PREV_INSN (label);
1527+ bool simple_p;
1528+ rtx jump;
1529+ e = find_edge (bb, last_bb);
1530+
1531+ jump = BB_END (bb);
1532+
1533+#ifdef HAVE_simple_return
1534+ simple_p = (entry_edge != orig_entry_edge
1535+ ? !bitmap_bit_p (&bb_flags, bb->index) : false);
1536+#else
1537+ simple_p = false;
1538+#endif
1539+
1540+ if (!simple_p
1541+ && (!HAVE_return || !JUMP_P (jump)
1542+ || JUMP_LABEL (jump) != label))
1543+ continue;
1544+
1545+ /* If we have an unconditional jump, we can replace that
1546+ with a simple return instruction. */
1547+ if (!JUMP_P (jump))
1548+ {
1549+ emit_barrier_after (BB_END (bb));
1550+ emit_return_into_block (simple_p, bb);
1551+ }
1552+ else if (simplejump_p (jump))
1553+ {
1554+ emit_return_into_block (simple_p, bb);
1555+ delete_insn (jump);
1556+ }
1557+ else if (condjump_p (jump) && JUMP_LABEL (jump) != label)
1558+ {
1559+ basic_block new_bb;
1560+ edge new_e;
1561+
1562+ gcc_assert (simple_p);
1563+ new_bb = split_edge (e);
1564+ emit_barrier_after (BB_END (new_bb));
1565+ emit_return_into_block (simple_p, new_bb);
1566+#ifdef HAVE_simple_return
1567+ simple_return_block = new_bb;
1568+#endif
1569+ new_e = single_succ_edge (new_bb);
1570+ redirect_edge_succ (new_e, EXIT_BLOCK_PTR);
1571+
1572+ continue;
1573+ }
1574+ /* If we have a conditional jump branching to the last
1575+ block, we can try to replace that with a conditional
1576+ return instruction. */
1577+ else if (condjump_p (jump))
1578+ {
1579+ rtx dest;
1580+ if (simple_p)
1581+ dest = simple_return_rtx;
1582+ else
1583+ dest = ret_rtx;
1584+ if (! redirect_jump (jump, dest, 0))
1585+ {
1586+#ifdef HAVE_simple_return
1587+ if (simple_p)
1588+ unconverted_simple_returns = true;
1589+#endif
1590+ continue;
1591+ }
1592+
1593+ /* If this block has only one successor, it both jumps
1594+ and falls through to the fallthru block, so we can't
1595+ delete the edge. */
1596+ if (single_succ_p (bb))
1597+ continue;
1598+ }
1599+ else
1600+ {
1601+#ifdef HAVE_simple_return
1602+ if (simple_p)
1603+ unconverted_simple_returns = true;
1604+#endif
1605+ continue;
1606+ }
1607+
1608+ /* Fix up the CFG for the successful change we just made. */
1609+ redirect_edge_succ (e, EXIT_BLOCK_PTR);
1610 }
1611+ VEC_free (basic_block, heap, src_bbs);
1612
1613- if (BB_HEAD (last) == label && LABEL_P (label))
1614+ if (HAVE_return)
1615 {
1616- edge_iterator ei2;
1617-
1618- for (ei2 = ei_start (last->preds); (e = ei_safe_edge (ei2)); )
1619- {
1620- basic_block bb = e->src;
1621- rtx jump;
1622-
1623- if (bb == ENTRY_BLOCK_PTR)
1624- {
1625- ei_next (&ei2);
1626- continue;
1627- }
1628-
1629- jump = BB_END (bb);
1630- if (!JUMP_P (jump) || JUMP_LABEL (jump) != label)
1631- {
1632- ei_next (&ei2);
1633- continue;
1634- }
1635-
1636- /* If we have an unconditional jump, we can replace that
1637- with a simple return instruction. */
1638- if (simplejump_p (jump))
1639- {
1640- emit_return_into_block (bb);
1641- delete_insn (jump);
1642- }
1643-
1644- /* If we have a conditional jump, we can try to replace
1645- that with a conditional return instruction. */
1646- else if (condjump_p (jump))
1647- {
1648- if (! redirect_jump (jump, 0, 0))
1649- {
1650- ei_next (&ei2);
1651- continue;
1652- }
1653-
1654- /* If this block has only one successor, it both jumps
1655- and falls through to the fallthru block, so we can't
1656- delete the edge. */
1657- if (single_succ_p (bb))
1658- {
1659- ei_next (&ei2);
1660- continue;
1661- }
1662- }
1663- else
1664- {
1665- ei_next (&ei2);
1666- continue;
1667- }
1668-
1669- /* Fix up the CFG for the successful change we just made. */
1670- redirect_edge_succ (e, EXIT_BLOCK_PTR);
1671- }
1672-
1673 /* Emit a return insn for the exit fallthru block. Whether
1674 this is still reachable will be determined later. */
1675
1676- emit_barrier_after (BB_END (last));
1677- emit_return_into_block (last);
1678- epilogue_end = BB_END (last);
1679- single_succ_edge (last)->flags &= ~EDGE_FALLTHRU;
1680+ emit_barrier_after (BB_END (last_bb));
1681+ emit_return_into_block (false, last_bb);
1682+ epilogue_end = BB_END (last_bb);
1683+ if (JUMP_P (epilogue_end))
1684+ JUMP_LABEL (epilogue_end) = ret_rtx;
1685+ single_succ_edge (last_bb)->flags &= ~EDGE_FALLTHRU;
1686 goto epilogue_done;
1687 }
1688 }
1689@@ -5193,15 +5523,10 @@
1690 }
1691 #endif
1692
1693- /* Find the edge that falls through to EXIT. Other edges may exist
1694- due to RETURN instructions, but those don't need epilogues.
1695- There really shouldn't be a mixture -- either all should have
1696- been converted or none, however... */
1697+ /* If nothing falls through into the exit block, we don't need an
1698+ epilogue. */
1699
1700- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1701- if (e->flags & EDGE_FALLTHRU)
1702- break;
1703- if (e == NULL)
1704+ if (exit_fallthru_edge == NULL)
1705 goto epilogue_done;
1706
1707 #ifdef HAVE_epilogue
1708@@ -5217,25 +5542,38 @@
1709 set_insn_locators (seq, epilogue_locator);
1710
1711 seq = get_insns ();
1712+ returnjump = get_last_insn ();
1713 end_sequence ();
1714
1715- insert_insn_on_edge (seq, e);
1716+ insert_insn_on_edge (seq, exit_fallthru_edge);
1717 inserted = 1;
1718+ if (JUMP_P (returnjump))
1719+ {
1720+ rtx pat = PATTERN (returnjump);
1721+ if (GET_CODE (pat) == PARALLEL)
1722+ pat = XVECEXP (pat, 0, 0);
1723+ if (ANY_RETURN_P (pat))
1724+ JUMP_LABEL (returnjump) = pat;
1725+ else
1726+ JUMP_LABEL (returnjump) = ret_rtx;
1727+ }
1728+ else
1729+ returnjump = NULL_RTX;
1730 }
1731 else
1732 #endif
1733 {
1734 basic_block cur_bb;
1735
1736- if (! next_active_insn (BB_END (e->src)))
1737+ if (! next_active_insn (BB_END (exit_fallthru_edge->src)))
1738 goto epilogue_done;
1739 /* We have a fall-through edge to the exit block, the source is not
1740- at the end of the function, and there will be an assembler epilogue
1741- at the end of the function.
1742- We can't use force_nonfallthru here, because that would try to
1743- use return. Inserting a jump 'by hand' is extremely messy, so
1744+ at the end of the function, and there will be an assembler epilogue
1745+ at the end of the function.
1746+ We can't use force_nonfallthru here, because that would try to
1747+ use return. Inserting a jump 'by hand' is extremely messy, so
1748 we take advantage of cfg_layout_finalize using
1749- fixup_fallthru_exit_predecessor. */
1750+ fixup_fallthru_exit_predecessor. */
1751 cfg_layout_initialize (0);
1752 FOR_EACH_BB (cur_bb)
1753 if (cur_bb->index >= NUM_FIXED_BLOCKS
1754@@ -5244,6 +5582,7 @@
1755 cfg_layout_finalize ();
1756 }
1757 epilogue_done:
1758+
1759 default_rtl_profile ();
1760
1761 if (inserted)
1762@@ -5260,33 +5599,93 @@
1763 }
1764 }
1765
1766+#ifdef HAVE_simple_return
1767+ /* If there were branches to an empty LAST_BB which we tried to
1768+ convert to conditional simple_returns, but couldn't for some
1769+ reason, create a block to hold a simple_return insn and redirect
1770+ those remaining edges. */
1771+ if (unconverted_simple_returns)
1772+ {
1773+ edge_iterator ei2;
1774+ basic_block exit_pred = EXIT_BLOCK_PTR->prev_bb;
1775+
1776+ gcc_assert (entry_edge != orig_entry_edge);
1777+
1778+#ifdef HAVE_epilogue
1779+ if (simple_return_block == NULL && returnjump != NULL_RTX
1780+ && JUMP_LABEL (returnjump) == simple_return_rtx)
1781+ {
1782+ edge e = split_block (exit_fallthru_edge->src,
1783+ PREV_INSN (returnjump));
1784+ simple_return_block = e->dest;
1785+ }
1786+#endif
1787+ if (simple_return_block == NULL)
1788+ {
1789+ basic_block bb;
1790+ rtx start;
1791+
1792+ bb = create_basic_block (NULL, NULL, exit_pred);
1793+ start = emit_jump_insn_after (gen_simple_return (),
1794+ BB_END (bb));
1795+ JUMP_LABEL (start) = simple_return_rtx;
1796+ emit_barrier_after (start);
1797+
1798+ simple_return_block = bb;
1799+ make_edge (bb, EXIT_BLOCK_PTR, 0);
1800+ }
1801+
1802+ restart_scan:
1803+ for (ei2 = ei_start (last_bb->preds); (e = ei_safe_edge (ei2)); )
1804+ {
1805+ basic_block bb = e->src;
1806+
1807+ if (bb != ENTRY_BLOCK_PTR
1808+ && !bitmap_bit_p (&bb_flags, bb->index))
1809+ {
1810+ redirect_edge_and_branch_force (e, simple_return_block);
1811+ goto restart_scan;
1812+ }
1813+ ei_next (&ei2);
1814+
1815+ }
1816+ }
1817+#endif
1818+
1819 #ifdef HAVE_sibcall_epilogue
1820 /* Emit sibling epilogues before any sibling call sites. */
1821 for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
1822 {
1823 basic_block bb = e->src;
1824 rtx insn = BB_END (bb);
1825+ rtx ep_seq;
1826
1827 if (!CALL_P (insn)
1828- || ! SIBLING_CALL_P (insn))
1829+ || ! SIBLING_CALL_P (insn)
1830+ || (entry_edge != orig_entry_edge
1831+ && !bitmap_bit_p (&bb_flags, bb->index)))
1832 {
1833 ei_next (&ei);
1834 continue;
1835 }
1836
1837- start_sequence ();
1838- emit_note (NOTE_INSN_EPILOGUE_BEG);
1839- emit_insn (gen_sibcall_epilogue ());
1840- seq = get_insns ();
1841- end_sequence ();
1842-
1843- /* Retain a map of the epilogue insns. Used in life analysis to
1844- avoid getting rid of sibcall epilogue insns. Do this before we
1845- actually emit the sequence. */
1846- record_insns (seq, NULL, &epilogue_insn_hash);
1847- set_insn_locators (seq, epilogue_locator);
1848-
1849- emit_insn_before (seq, insn);
1850+ ep_seq = gen_sibcall_epilogue ();
1851+ if (ep_seq)
1852+ {
1853+ start_sequence ();
1854+ emit_note (NOTE_INSN_EPILOGUE_BEG);
1855+ emit_insn (ep_seq);
1856+ seq = get_insns ();
1857+ end_sequence ();
1858+
1859+ /* Retain a map of the epilogue insns. Used in life analysis to
1860+ avoid getting rid of sibcall epilogue insns. Do this before we
1861+ actually emit the sequence. */
1862+ record_insns (seq, NULL, &epilogue_insn_hash);
1863+ set_insn_locators (seq, epilogue_locator);
1864+
1865+ emit_insn_before (seq, insn);
1866+ }
1867 ei_next (&ei);
1868 }
1869 #endif
1870@@ -5311,6 +5710,8 @@
1871 }
1872 #endif
1873
1874+ bitmap_clear (&bb_flags);
1875+
1876 /* Threading the prologue and epilogue changes the artificial refs
1877 in the entry and exit blocks. */
1878 epilogue_completed = 1;
1879
1880=== modified file 'gcc/genemit.c'
1881--- old/gcc/genemit.c 2009-11-27 11:37:06 +0000
1882+++ new/gcc/genemit.c 2011-01-05 12:12:18 +0000
1883@@ -222,6 +222,12 @@
1884 case PC:
1885 printf ("pc_rtx");
1886 return;
1887+ case RETURN:
1888+ printf ("ret_rtx");
1889+ return;
1890+ case SIMPLE_RETURN:
1891+ printf ("simple_return_rtx");
1892+ return;
1893 case CLOBBER:
1894 if (REG_P (XEXP (x, 0)))
1895 {
1896@@ -544,8 +550,8 @@
1897 || (GET_CODE (next) == PARALLEL
1898 && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
1899 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
1900- || GET_CODE (XVECEXP (next, 0, 0)) == RETURN))
1901- || GET_CODE (next) == RETURN)
1902+ || ANY_RETURN_P (XVECEXP (next, 0, 0))))
1903+ || ANY_RETURN_P (next))
1904 printf (" emit_jump_insn (");
1905 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
1906 || GET_CODE (next) == CALL
1907@@ -660,7 +666,7 @@
1908 || (GET_CODE (next) == PARALLEL
1909 && GET_CODE (XVECEXP (next, 0, 0)) == SET
1910 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
1911- || GET_CODE (next) == RETURN)
1912+ || ANY_RETURN_P (next))
1913 printf (" emit_jump_insn (");
1914 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
1915 || GET_CODE (next) == CALL
1916
1917=== modified file 'gcc/gengenrtl.c'
1918--- old/gcc/gengenrtl.c 2007-08-22 23:30:39 +0000
1919+++ new/gcc/gengenrtl.c 2011-01-05 12:12:18 +0000
1920@@ -146,6 +146,10 @@
1921 || strcmp (defs[idx].enumname, "REG") == 0
1922 || strcmp (defs[idx].enumname, "SUBREG") == 0
1923 || strcmp (defs[idx].enumname, "MEM") == 0
1924+ || strcmp (defs[idx].enumname, "PC") == 0
1925+ || strcmp (defs[idx].enumname, "CC0") == 0
1926+ || strcmp (defs[idx].enumname, "RETURN") == 0
1927+ || strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0
1928 || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
1929 }
1930
1931
1932=== modified file 'gcc/haifa-sched.c'
1933--- old/gcc/haifa-sched.c 2010-08-12 08:14:47 +0000
1934+++ new/gcc/haifa-sched.c 2011-01-05 12:12:18 +0000
1935@@ -4231,7 +4231,7 @@
1936 /* Helper function.
1937 Find fallthru edge from PRED. */
1938 edge
1939-find_fallthru_edge (basic_block pred)
1940+find_fallthru_edge_from (basic_block pred)
1941 {
1942 edge e;
1943 edge_iterator ei;
1944@@ -4298,7 +4298,7 @@
1945 edge e;
1946
1947 last = EXIT_BLOCK_PTR->prev_bb;
1948- e = find_fallthru_edge (last);
1949+ e = find_fallthru_edge_from (last);
1950
1951 if (e)
1952 {
1953@@ -5234,6 +5234,11 @@
1954 gcc_assert (/* Usual case. */
1955 (EDGE_COUNT (bb->succs) > 1
1956 && !BARRIER_P (NEXT_INSN (head)))
1957+ /* Special cases, see cfglayout.c:
1958+ fixup_reorder_chain. */
1959+ || (EDGE_COUNT (bb->succs) == 1
1960+ && (!onlyjump_p (head)
1961+ || returnjump_p (head)))
1962 /* Or jump to the next instruction. */
1963 || (EDGE_COUNT (bb->succs) == 1
1964 && (BB_HEAD (EDGE_I (bb->succs, 0)->dest)
1965
1966=== modified file 'gcc/ifcvt.c'
1967--- old/gcc/ifcvt.c 2010-11-26 12:03:32 +0000
1968+++ new/gcc/ifcvt.c 2011-01-05 12:12:18 +0000
1969@@ -105,7 +105,7 @@
1970 static int find_if_case_2 (basic_block, edge, edge);
1971 static int find_memory (rtx *, void *);
1972 static int dead_or_predicable (basic_block, basic_block, basic_block,
1973- basic_block, int);
1974+ edge, int);
1975 static void noce_emit_move_insn (rtx, rtx);
1976 static rtx block_has_only_trap (basic_block);
1977
1978@@ -3791,6 +3791,7 @@
1979 basic_block then_bb = then_edge->dest;
1980 basic_block else_bb = else_edge->dest;
1981 basic_block new_bb;
1982+ rtx else_target = NULL_RTX;
1983 int then_bb_index;
1984
1985 /* If we are partitioning hot/cold basic blocks, we don't want to
1986@@ -3840,9 +3841,16 @@
1987 predictable_edge_p (then_edge)))))
1988 return FALSE;
1989
1990+ if (else_bb == EXIT_BLOCK_PTR)
1991+ {
1992+ rtx jump = BB_END (else_edge->src);
1993+ gcc_assert (JUMP_P (jump));
1994+ else_target = JUMP_LABEL (jump);
1995+ }
1996+
1997 /* Registers set are dead, or are predicable. */
1998 if (! dead_or_predicable (test_bb, then_bb, else_bb,
1999- single_succ (then_bb), 1))
2000+ single_succ_edge (then_bb), 1))
2001 return FALSE;
2002
2003 /* Conversion went ok, including moving the insns and fixing up the
2004@@ -3859,6 +3867,9 @@
2005 redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
2006 new_bb = 0;
2007 }
2008+ else if (else_bb == EXIT_BLOCK_PTR)
2009+ new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
2010+ else_bb, else_target);
2011 else
2012 new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
2013 else_bb);
2014@@ -3957,7 +3968,7 @@
2015 return FALSE;
2016
2017 /* Registers set are dead, or are predicable. */
2018- if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0))
2019+ if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, 0))
2020 return FALSE;
2021
2022 /* Conversion went ok, including moving the insns and fixing up the
2023@@ -3995,12 +4006,34 @@
2024
2025 static int
2026 dead_or_predicable (basic_block test_bb, basic_block merge_bb,
2027- basic_block other_bb, basic_block new_dest, int reversep)
2028+ basic_block other_bb, edge dest_edge, int reversep)
2029 {
2030- rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX;
2031+ basic_block new_dest = dest_edge->dest;
2032+ rtx head, end, jump, earliest = NULL_RTX, old_dest;
2033 bitmap merge_set = NULL;
2034 /* Number of pending changes. */
2035 int n_validated_changes = 0;
2036+ rtx new_dest_label;
2037+
2038+ jump = BB_END (dest_edge->src);
2039+ if (JUMP_P (jump))
2040+ {
2041+ new_dest_label = JUMP_LABEL (jump);
2042+ if (new_dest_label == NULL_RTX)
2043+ {
2044+ new_dest_label = PATTERN (jump);
2045+ gcc_assert (ANY_RETURN_P (new_dest_label));
2046+ }
2047+ }
2048+ else if (other_bb != new_dest)
2049+ {
2050+ if (new_dest == EXIT_BLOCK_PTR)
2051+ new_dest_label = ret_rtx;
2052+ else
2053+ new_dest_label = block_label (new_dest);
2054+ }
2055+ else
2056+ new_dest_label = NULL_RTX;
2057
2058 jump = BB_END (test_bb);
2059
2060@@ -4220,10 +4253,9 @@
2061 old_dest = JUMP_LABEL (jump);
2062 if (other_bb != new_dest)
2063 {
2064- new_label = block_label (new_dest);
2065 if (reversep
2066- ? ! invert_jump_1 (jump, new_label)
2067- : ! redirect_jump_1 (jump, new_label))
2068+ ? ! invert_jump_1 (jump, new_dest_label)
2069+ : ! redirect_jump_1 (jump, new_dest_label))
2070 goto cancel;
2071 }
2072
2073@@ -4234,7 +4266,7 @@
2074
2075 if (other_bb != new_dest)
2076 {
2077- redirect_jump_2 (jump, old_dest, new_label, 0, reversep);
2078+ redirect_jump_2 (jump, old_dest, new_dest_label, 0, reversep);
2079
2080 redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
2081 if (reversep)
2082
2083=== modified file 'gcc/jump.c'
2084--- old/gcc/jump.c 2010-12-13 10:05:52 +0000
2085+++ new/gcc/jump.c 2011-01-05 12:12:18 +0000
2086@@ -29,7 +29,8 @@
2087 JUMP_LABEL internal field. With this we can detect labels that
2088 become unused because of the deletion of all the jumps that
2089 formerly used them. The JUMP_LABEL info is sometimes looked
2090- at by later passes.
2091+ at by later passes. For return insns, it contains either a
2092+ RETURN or a SIMPLE_RETURN rtx.
2093
2094 The subroutines redirect_jump and invert_jump are used
2095 from other passes as well. */
2096@@ -742,10 +743,10 @@
2097 return (GET_CODE (x) == IF_THEN_ELSE
2098 && ((GET_CODE (XEXP (x, 2)) == PC
2099 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
2100- || GET_CODE (XEXP (x, 1)) == RETURN))
2101+ || ANY_RETURN_P (XEXP (x, 1))))
2102 || (GET_CODE (XEXP (x, 1)) == PC
2103 && (GET_CODE (XEXP (x, 2)) == LABEL_REF
2104- || GET_CODE (XEXP (x, 2)) == RETURN))));
2105+ || ANY_RETURN_P (XEXP (x, 2))))));
2106 }
2107
2108 /* Return nonzero if INSN is a (possibly) conditional jump inside a
2109@@ -774,11 +775,11 @@
2110 return 0;
2111 if (XEXP (SET_SRC (x), 2) == pc_rtx
2112 && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
2113- || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN))
2114+ || ANY_RETURN_P (XEXP (SET_SRC (x), 1)) == RETURN))
2115 return 1;
2116 if (XEXP (SET_SRC (x), 1) == pc_rtx
2117 && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
2118- || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN))
2119+ || ANY_RETURN_P (XEXP (SET_SRC (x), 2))))
2120 return 1;
2121 return 0;
2122 }
2123@@ -840,8 +841,9 @@
2124 a = GET_CODE (XEXP (SET_SRC (x), 1));
2125 b = GET_CODE (XEXP (SET_SRC (x), 2));
2126
2127- return ((b == PC && (a == LABEL_REF || a == RETURN))
2128- || (a == PC && (b == LABEL_REF || b == RETURN)));
2129+ return ((b == PC && (a == LABEL_REF || a == RETURN || a == SIMPLE_RETURN))
2130+ || (a == PC
2131+ && (b == LABEL_REF || b == RETURN || b == SIMPLE_RETURN)));
2132 }
2133
2134 /* Return the label of a conditional jump. */
2135@@ -878,6 +880,7 @@
2136 switch (GET_CODE (x))
2137 {
2138 case RETURN:
2139+ case SIMPLE_RETURN:
2140 case EH_RETURN:
2141 return true;
2142
2143@@ -1200,7 +1203,7 @@
2144 /* If deleting a jump, decrement the count of the label,
2145 and delete the label if it is now unused. */
2146
2147- if (JUMP_P (insn) && JUMP_LABEL (insn))
2148+ if (JUMP_P (insn) && JUMP_LABEL (insn) && !ANY_RETURN_P (JUMP_LABEL (insn)))
2149 {
2150 rtx lab = JUMP_LABEL (insn), lab_next;
2151
2152@@ -1331,6 +1334,18 @@
2153 is also an unconditional jump in that case. */
2154 }
2155
2156+/* A helper function for redirect_exp_1; examines its input X and returns
2157+ either a LABEL_REF around a label, or a RETURN if X was NULL. */
2158+static rtx
2159+redirect_target (rtx x)
2160+{
2161+ if (x == NULL_RTX)
2162+ return ret_rtx;
2163+ if (!ANY_RETURN_P (x))
2164+ return gen_rtx_LABEL_REF (Pmode, x);
2165+ return x;
2166+}
2167+
2168 /* Throughout LOC, redirect OLABEL to NLABEL. Treat null OLABEL or
2169 NLABEL as a return. Accrue modifications into the change group. */
2170
2171@@ -1342,37 +1357,19 @@
2172 int i;
2173 const char *fmt;
2174
2175- if (code == LABEL_REF)
2176- {
2177- if (XEXP (x, 0) == olabel)
2178- {
2179- rtx n;
2180- if (nlabel)
2181- n = gen_rtx_LABEL_REF (Pmode, nlabel);
2182- else
2183- n = gen_rtx_RETURN (VOIDmode);
2184-
2185- validate_change (insn, loc, n, 1);
2186- return;
2187- }
2188- }
2189- else if (code == RETURN && olabel == 0)
2190- {
2191- if (nlabel)
2192- x = gen_rtx_LABEL_REF (Pmode, nlabel);
2193- else
2194- x = gen_rtx_RETURN (VOIDmode);
2195- if (loc == &PATTERN (insn))
2196- x = gen_rtx_SET (VOIDmode, pc_rtx, x);
2197- validate_change (insn, loc, x, 1);
2198+ if ((code == LABEL_REF && XEXP (x, 0) == olabel)
2199+ || x == olabel)
2200+ {
2201+ validate_change (insn, loc, redirect_target (nlabel), 1);
2202 return;
2203 }
2204
2205- if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx
2206+ if (code == SET && SET_DEST (x) == pc_rtx
2207+ && ANY_RETURN_P (nlabel)
2208 && GET_CODE (SET_SRC (x)) == LABEL_REF
2209 && XEXP (SET_SRC (x), 0) == olabel)
2210 {
2211- validate_change (insn, loc, gen_rtx_RETURN (VOIDmode), 1);
2212+ validate_change (insn, loc, nlabel, 1);
2213 return;
2214 }
2215
2216@@ -1409,6 +1406,7 @@
2217 int ochanges = num_validated_changes ();
2218 rtx *loc, asmop;
2219
2220+ gcc_assert (nlabel);
2221 asmop = extract_asm_operands (PATTERN (jump));
2222 if (asmop)
2223 {
2224@@ -1430,17 +1428,20 @@
2225 jump target label is unused as a result, it and the code following
2226 it may be deleted.
2227
2228- If NLABEL is zero, we are to turn the jump into a (possibly conditional)
2229- RETURN insn.
2230+ Normally, NLABEL will be a label, but it may also be a RETURN or
2231+ SIMPLE_RETURN rtx; in that case we are to turn the jump into a
2232+ (possibly conditional) return insn.
2233
2234 The return value will be 1 if the change was made, 0 if it wasn't
2235- (this can only occur for NLABEL == 0). */
2236+ (this can only occur when trying to produce return insns). */
2237
2238 int
2239 redirect_jump (rtx jump, rtx nlabel, int delete_unused)
2240 {
2241 rtx olabel = JUMP_LABEL (jump);
2242
2243+ gcc_assert (nlabel != NULL_RTX);
2244+
2245 if (nlabel == olabel)
2246 return 1;
2247
2248@@ -1452,7 +1453,7 @@
2249 }
2250
2251 /* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
2252- NLABEL in JUMP.
2253+ NEW_DEST in JUMP.
2254 If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
2255 count has dropped to zero. */
2256 void
2257@@ -1468,13 +1469,14 @@
2258 about this. */
2259 gcc_assert (delete_unused >= 0);
2260 JUMP_LABEL (jump) = nlabel;
2261- if (nlabel)
2262+ if (nlabel && !ANY_RETURN_P (nlabel))
2263 ++LABEL_NUSES (nlabel);
2264
2265 /* Update labels in any REG_EQUAL note. */
2266 if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
2267 {
2268- if (!nlabel || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
2269+ if (ANY_RETURN_P (nlabel)
2270+ || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
2271 remove_note (jump, note);
2272 else
2273 {
2274@@ -1483,7 +1485,8 @@
2275 }
2276 }
2277
2278- if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
2279+ if (olabel && !ANY_RETURN_P (olabel)
2280+ && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
2281 /* Undefined labels will remain outside the insn stream. */
2282 && INSN_UID (olabel))
2283 delete_related_insns (olabel);
2284
2285=== modified file 'gcc/opts.c'
2286--- old/gcc/opts.c 2010-12-10 15:33:37 +0000
2287+++ new/gcc/opts.c 2011-01-05 12:12:18 +0000
2288@@ -908,6 +908,7 @@
2289 flag_ipa_cp = opt2;
2290 flag_ipa_sra = opt2;
2291 flag_ee = opt2;
2292+ flag_shrink_wrap = opt2;
2293
2294 /* Track fields in field-sensitive alias analysis. */
2295 set_param_value ("max-fields-for-field-sensitive",
2296
2297=== modified file 'gcc/print-rtl.c'
2298--- old/gcc/print-rtl.c 2010-03-26 16:18:51 +0000
2299+++ new/gcc/print-rtl.c 2011-01-05 12:12:18 +0000
2300@@ -308,9 +308,16 @@
2301 }
2302 }
2303 else if (i == 8 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL)
2304- /* Output the JUMP_LABEL reference. */
2305- fprintf (outfile, "\n%s%*s -> %d", print_rtx_head, indent * 2, "",
2306- INSN_UID (JUMP_LABEL (in_rtx)));
2307+ {
2308+ /* Output the JUMP_LABEL reference. */
2309+ fprintf (outfile, "\n%s%*s -> ", print_rtx_head, indent * 2, "");
2310+ if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN)
2311+ fprintf (outfile, "return");
2312+ else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN)
2313+ fprintf (outfile, "simple_return");
2314+ else
2315+ fprintf (outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
2316+ }
2317 else if (i == 0 && GET_CODE (in_rtx) == VALUE)
2318 {
2319 #ifndef GENERATOR_FILE
2320
2321=== modified file 'gcc/reorg.c'
2322--- old/gcc/reorg.c 2010-09-15 22:51:44 +0000
2323+++ new/gcc/reorg.c 2011-01-05 12:12:18 +0000
2324@@ -161,8 +161,11 @@
2325 #define unfilled_slots_next \
2326 ((rtx *) obstack_next_free (&unfilled_slots_obstack))
2327
2328-/* Points to the label before the end of the function. */
2329-static rtx end_of_function_label;
2330+/* Points to the label before the end of the function, or before a
2331+ return insn. */
2332+static rtx function_return_label;
2333+/* Likewise for a simple_return. */
2334+static rtx function_simple_return_label;
2335
2336 /* Mapping between INSN_UID's and position in the code since INSN_UID's do
2337 not always monotonically increase. */
2338@@ -175,7 +178,7 @@
2339 static int resource_conflicts_p (struct resources *, struct resources *);
2340 static int insn_references_resource_p (rtx, struct resources *, bool);
2341 static int insn_sets_resource_p (rtx, struct resources *, bool);
2342-static rtx find_end_label (void);
2343+static rtx find_end_label (rtx);
2344 static rtx emit_delay_sequence (rtx, rtx, int);
2345 static rtx add_to_delay_list (rtx, rtx);
2346 static rtx delete_from_delay_slot (rtx);
2347@@ -220,6 +223,15 @@
2348 static void make_return_insns (rtx);
2349 #endif
2350
2351+/* Return true iff INSN is a simplejump, or any kind of return insn. */
2352+
2353+static bool
2354+simplejump_or_return_p (rtx insn)
2355+{
2356+ return (JUMP_P (insn)
2357+ && (simplejump_p (insn) || ANY_RETURN_P (PATTERN (insn))));
2358+}
2359+
2360 /* Return TRUE if this insn should stop the search for insn to fill delay
2361 slots. LABELS_P indicates that labels should terminate the search.
2362 In all cases, jumps terminate the search. */
2363@@ -335,23 +347,29 @@
2364
2365 ??? There may be a problem with the current implementation. Suppose
2366 we start with a bare RETURN insn and call find_end_label. It may set
2367- end_of_function_label just before the RETURN. Suppose the machinery
2368+ function_return_label just before the RETURN. Suppose the machinery
2369 is able to fill the delay slot of the RETURN insn afterwards. Then
2370- end_of_function_label is no longer valid according to the property
2371+ function_return_label is no longer valid according to the property
2372 described above and find_end_label will still return it unmodified.
2373 Note that this is probably mitigated by the following observation:
2374- once end_of_function_label is made, it is very likely the target of
2375+ once function_return_label is made, it is very likely the target of
2376 a jump, so filling the delay slot of the RETURN will be much more
2377 difficult. */
2378
2379 static rtx
2380-find_end_label (void)
2381+find_end_label (rtx kind)
2382 {
2383 rtx insn;
2384+ rtx *plabel;
2385+
2386+ if (kind == ret_rtx)
2387+ plabel = &function_return_label;
2388+ else
2389+ plabel = &function_simple_return_label;
2390
2391 /* If we found one previously, return it. */
2392- if (end_of_function_label)
2393- return end_of_function_label;
2394+ if (*plabel)
2395+ return *plabel;
2396
2397 /* Otherwise, see if there is a label at the end of the function. If there
2398 is, it must be that RETURN insns aren't needed, so that is our return
2399@@ -366,44 +384,44 @@
2400
2401 /* When a target threads its epilogue we might already have a
2402 suitable return insn. If so put a label before it for the
2403- end_of_function_label. */
2404+ function_return_label. */
2405 if (BARRIER_P (insn)
2406 && JUMP_P (PREV_INSN (insn))
2407- && GET_CODE (PATTERN (PREV_INSN (insn))) == RETURN)
2408+ && PATTERN (PREV_INSN (insn)) == kind)
2409 {
2410 rtx temp = PREV_INSN (PREV_INSN (insn));
2411- end_of_function_label = gen_label_rtx ();
2412- LABEL_NUSES (end_of_function_label) = 0;
2413+ rtx label = gen_label_rtx ();
2414+ LABEL_NUSES (label) = 0;
2415
2416 /* Put the label before an USE insns that may precede the RETURN insn. */
2417 while (GET_CODE (temp) == USE)
2418 temp = PREV_INSN (temp);
2419
2420- emit_label_after (end_of_function_label, temp);
2421+ emit_label_after (label, temp);
2422+ *plabel = label;
2423 }
2424
2425 else if (LABEL_P (insn))
2426- end_of_function_label = insn;
2427+ *plabel = insn;
2428 else
2429 {
2430- end_of_function_label = gen_label_rtx ();
2431- LABEL_NUSES (end_of_function_label) = 0;
2432+ rtx label = gen_label_rtx ();
2433+ LABEL_NUSES (label) = 0;
2434 /* If the basic block reorder pass moves the return insn to
2435 some other place try to locate it again and put our
2436- end_of_function_label there. */
2437- while (insn && ! (JUMP_P (insn)
2438- && (GET_CODE (PATTERN (insn)) == RETURN)))
2439+ function_return_label there. */
2440+ while (insn && ! (JUMP_P (insn) && (PATTERN (insn) == kind)))
2441 insn = PREV_INSN (insn);
2442 if (insn)
2443 {
2444 insn = PREV_INSN (insn);
2445
2446- /* Put the label before an USE insns that may proceed the
2447+ /* Put the label before an USE insns that may precede the
2448 RETURN insn. */
2449 while (GET_CODE (insn) == USE)
2450 insn = PREV_INSN (insn);
2451
2452- emit_label_after (end_of_function_label, insn);
2453+ emit_label_after (label, insn);
2454 }
2455 else
2456 {
2457@@ -413,19 +431,16 @@
2458 && ! HAVE_return
2459 #endif
2460 )
2461- {
2462- /* The RETURN insn has its delay slot filled so we cannot
2463- emit the label just before it. Since we already have
2464- an epilogue and cannot emit a new RETURN, we cannot
2465- emit the label at all. */
2466- end_of_function_label = NULL_RTX;
2467- return end_of_function_label;
2468- }
2469+ /* The RETURN insn has its delay slot filled so we cannot
2470+ emit the label just before it. Since we already have
2471+ an epilogue and cannot emit a new RETURN, we cannot
2472+ emit the label at all. */
2473+ return NULL_RTX;
2474 #endif /* HAVE_epilogue */
2475
2476 /* Otherwise, make a new label and emit a RETURN and BARRIER,
2477 if needed. */
2478- emit_label (end_of_function_label);
2479+ emit_label (label);
2480 #ifdef HAVE_return
2481 /* We don't bother trying to create a return insn if the
2482 epilogue has filled delay-slots; we would have to try and
2483@@ -437,19 +452,21 @@
2484 /* The return we make may have delay slots too. */
2485 rtx insn = gen_return ();
2486 insn = emit_jump_insn (insn);
2487+ JUMP_LABEL (insn) = ret_rtx;
2488 emit_barrier ();
2489 if (num_delay_slots (insn) > 0)
2490 obstack_ptr_grow (&unfilled_slots_obstack, insn);
2491 }
2492 #endif
2493 }
2494+ *plabel = label;
2495 }
2496
2497 /* Show one additional use for this label so it won't go away until
2498 we are done. */
2499- ++LABEL_NUSES (end_of_function_label);
2500+ ++LABEL_NUSES (*plabel);
2501
2502- return end_of_function_label;
2503+ return *plabel;
2504 }
2505
2506 /* Put INSN and LIST together in a SEQUENCE rtx of LENGTH, and replace
2507@@ -797,10 +814,8 @@
2508 if ((next_trial == next_active_insn (JUMP_LABEL (insn))
2509 && ! (next_trial == 0 && crtl->epilogue_delay_list != 0))
2510 || (next_trial != 0
2511- && JUMP_P (next_trial)
2512- && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)
2513- && (simplejump_p (next_trial)
2514- || GET_CODE (PATTERN (next_trial)) == RETURN)))
2515+ && simplejump_or_return_p (next_trial)
2516+ && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)))
2517 {
2518 if (eligible_for_annul_false (insn, 0, trial, flags))
2519 {
2520@@ -819,13 +834,11 @@
2521 branch, thread our jump to the target of that branch. Don't
2522 change this into a RETURN here, because it may not accept what
2523 we have in the delay slot. We'll fix this up later. */
2524- if (next_trial && JUMP_P (next_trial)
2525- && (simplejump_p (next_trial)
2526- || GET_CODE (PATTERN (next_trial)) == RETURN))
2527+ if (next_trial && simplejump_or_return_p (next_trial))
2528 {
2529 rtx target_label = JUMP_LABEL (next_trial);
2530- if (target_label == 0)
2531- target_label = find_end_label ();
2532+ if (ANY_RETURN_P (target_label))
2533+ target_label = find_end_label (target_label);
2534
2535 if (target_label)
2536 {
2537@@ -866,7 +879,7 @@
2538 if (JUMP_P (insn)
2539 && (condjump_p (insn) || condjump_in_parallel_p (insn))
2540 && INSN_UID (insn) <= max_uid
2541- && label != 0
2542+ && label != 0 && !ANY_RETURN_P (label)
2543 && INSN_UID (label) <= max_uid)
2544 flags
2545 = (uid_to_ruid[INSN_UID (label)] > uid_to_ruid[INSN_UID (insn)])
2546@@ -1038,7 +1051,7 @@
2547 pat = XVECEXP (pat, 0, 0);
2548
2549 if (GET_CODE (pat) == RETURN)
2550- return target == 0 ? const_true_rtx : 0;
2551+ return ANY_RETURN_P (target) ? const_true_rtx : 0;
2552
2553 else if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
2554 return 0;
2555@@ -1318,7 +1331,11 @@
2556 }
2557
2558 /* Show the place to which we will be branching. */
2559- *pnew_thread = next_active_insn (JUMP_LABEL (XVECEXP (seq, 0, 0)));
2560+ temp = JUMP_LABEL (XVECEXP (seq, 0, 0));
2561+ if (ANY_RETURN_P (temp))
2562+ *pnew_thread = temp;
2563+ else
2564+ *pnew_thread = next_active_insn (temp);
2565
2566 /* Add any new insns to the delay list and update the count of the
2567 number of slots filled. */
2568@@ -1358,8 +1375,7 @@
2569 /* We can't do anything if SEQ's delay insn isn't an
2570 unconditional branch. */
2571
2572- if (! simplejump_p (XVECEXP (seq, 0, 0))
2573- && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) != RETURN)
2574+ if (! simplejump_or_return_p (XVECEXP (seq, 0, 0)))
2575 return delay_list;
2576
2577 for (i = 1; i < XVECLEN (seq, 0); i++)
2578@@ -1827,7 +1843,7 @@
2579 rtx insn;
2580
2581 /* We don't own the function end. */
2582- if (thread == 0)
2583+ if (ANY_RETURN_P (thread))
2584 return 0;
2585
2586 /* Get the first active insn, or THREAD, if it is an active insn. */
2587@@ -2245,7 +2261,8 @@
2588 && (!JUMP_P (insn)
2589 || ((condjump_p (insn) || condjump_in_parallel_p (insn))
2590 && ! simplejump_p (insn)
2591- && JUMP_LABEL (insn) != 0)))
2592+ && JUMP_LABEL (insn) != 0
2593+ && !ANY_RETURN_P (JUMP_LABEL (insn)))))
2594 {
2595 /* Invariant: If insn is a JUMP_INSN, the insn's jump
2596 label. Otherwise, zero. */
2597@@ -2270,7 +2287,7 @@
2598 target = JUMP_LABEL (insn);
2599 }
2600
2601- if (target == 0)
2602+ if (target == 0 || ANY_RETURN_P (target))
2603 for (trial = next_nonnote_insn (insn); trial; trial = next_trial)
2604 {
2605 next_trial = next_nonnote_insn (trial);
2606@@ -2349,6 +2366,7 @@
2607 && JUMP_P (trial)
2608 && simplejump_p (trial)
2609 && (target == 0 || JUMP_LABEL (trial) == target)
2610+ && !ANY_RETURN_P (JUMP_LABEL (trial))
2611 && (next_trial = next_active_insn (JUMP_LABEL (trial))) != 0
2612 && ! (NONJUMP_INSN_P (next_trial)
2613 && GET_CODE (PATTERN (next_trial)) == SEQUENCE)
2614@@ -2371,7 +2389,7 @@
2615 if (new_label != 0)
2616 new_label = get_label_before (new_label);
2617 else
2618- new_label = find_end_label ();
2619+ new_label = find_end_label (simple_return_rtx);
2620
2621 if (new_label)
2622 {
2623@@ -2503,7 +2521,8 @@
2624
2625 /* Follow any unconditional jump at LABEL;
2626 return the ultimate label reached by any such chain of jumps.
2627- Return null if the chain ultimately leads to a return instruction.
2628+ Return a suitable return rtx if the chain ultimately leads to a
2629+ return instruction.
2630 If LABEL is not followed by a jump, return LABEL.
2631 If the chain loops or we can't find end, return LABEL,
2632 since that tells caller to avoid changing the insn. */
2633@@ -2518,6 +2537,7 @@
2634
2635 for (depth = 0;
2636 (depth < 10
2637+ && !ANY_RETURN_P (value)
2638 && (insn = next_active_insn (value)) != 0
2639 && JUMP_P (insn)
2640 && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn)
2641@@ -2527,18 +2547,22 @@
2642 && BARRIER_P (next));
2643 depth++)
2644 {
2645- rtx tem;
2646+ rtx this_label = JUMP_LABEL (insn);
2647
2648 /* If we have found a cycle, make the insn jump to itself. */
2649- if (JUMP_LABEL (insn) == label)
2650+ if (this_label == label)
2651 return label;
2652
2653- tem = next_active_insn (JUMP_LABEL (insn));
2654- if (tem && (GET_CODE (PATTERN (tem)) == ADDR_VEC
2655+ if (!ANY_RETURN_P (this_label))
2656+ {
2657+ rtx tem = next_active_insn (this_label);
2658+ if (tem
2659+ && (GET_CODE (PATTERN (tem)) == ADDR_VEC
2660 || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC))
2661- break;
2662+ break;
2663+ }
2664
2665- value = JUMP_LABEL (insn);
2666+ value = this_label;
2667 }
2668 if (depth == 10)
2669 return label;
2670@@ -2901,6 +2925,7 @@
2671 arithmetic insn after the jump insn and put the arithmetic insn in the
2672 delay slot. If we can't do this, return. */
2673 if (delay_list == 0 && likely && new_thread
2674+ && !ANY_RETURN_P (new_thread)
2675 && NONJUMP_INSN_P (new_thread)
2676 && GET_CODE (PATTERN (new_thread)) != ASM_INPUT
2677 && asm_noperands (PATTERN (new_thread)) < 0)
2678@@ -2985,16 +3010,14 @@
2679
2680 gcc_assert (thread_if_true);
2681
2682- if (new_thread && JUMP_P (new_thread)
2683- && (simplejump_p (new_thread)
2684- || GET_CODE (PATTERN (new_thread)) == RETURN)
2685+ if (new_thread && simplejump_or_return_p (new_thread)
2686 && redirect_with_delay_list_safe_p (insn,
2687 JUMP_LABEL (new_thread),
2688 delay_list))
2689 new_thread = follow_jumps (JUMP_LABEL (new_thread));
2690
2691- if (new_thread == 0)
2692- label = find_end_label ();
2693+ if (ANY_RETURN_P (new_thread))
2694+ label = find_end_label (new_thread);
2695 else if (LABEL_P (new_thread))
2696 label = new_thread;
2697 else
2698@@ -3340,11 +3363,12 @@
2699 group of consecutive labels. */
2700 if (JUMP_P (insn)
2701 && (condjump_p (insn) || condjump_in_parallel_p (insn))
2702- && (target_label = JUMP_LABEL (insn)) != 0)
2703+ && (target_label = JUMP_LABEL (insn)) != 0
2704+ && !ANY_RETURN_P (target_label))
2705 {
2706 target_label = skip_consecutive_labels (follow_jumps (target_label));
2707- if (target_label == 0)
2708- target_label = find_end_label ();
2709+ if (ANY_RETURN_P (target_label))
2710+ target_label = find_end_label (target_label);
2711
2712 if (target_label && next_active_insn (target_label) == next
2713 && ! condjump_in_parallel_p (insn))
2714@@ -3359,9 +3383,8 @@
2715 /* See if this jump conditionally branches around an unconditional
2716 jump. If so, invert this jump and point it to the target of the
2717 second jump. */
2718- if (next && JUMP_P (next)
2719+ if (next && simplejump_or_return_p (next)
2720 && any_condjump_p (insn)
2721- && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
2722 && target_label
2723 && next_active_insn (target_label) == next_active_insn (next)
2724 && no_labels_between_p (insn, next))
2725@@ -3403,8 +3426,7 @@
2726 Don't do this if we expect the conditional branch to be true, because
2727 we would then be making the more common case longer. */
2728
2729- if (JUMP_P (insn)
2730- && (simplejump_p (insn) || GET_CODE (PATTERN (insn)) == RETURN)
2731+ if (simplejump_or_return_p (insn)
2732 && (other = prev_active_insn (insn)) != 0
2733 && any_condjump_p (other)
2734 && no_labels_between_p (other, insn)
2735@@ -3445,10 +3467,10 @@
2736 Only do so if optimizing for size since this results in slower, but
2737 smaller code. */
2738 if (optimize_function_for_size_p (cfun)
2739- && GET_CODE (PATTERN (delay_insn)) == RETURN
2740+ && ANY_RETURN_P (PATTERN (delay_insn))
2741 && next
2742 && JUMP_P (next)
2743- && GET_CODE (PATTERN (next)) == RETURN)
2744+ && PATTERN (next) == PATTERN (delay_insn))
2745 {
2746 rtx after;
2747 int i;
2748@@ -3487,14 +3509,16 @@
2749 continue;
2750
2751 target_label = JUMP_LABEL (delay_insn);
2752+ if (target_label && ANY_RETURN_P (target_label))
2753+ continue;
2754
2755 if (target_label)
2756 {
2757 /* If this jump goes to another unconditional jump, thread it, but
2758 don't convert a jump into a RETURN here. */
2759 trial = skip_consecutive_labels (follow_jumps (target_label));
2760- if (trial == 0)
2761- trial = find_end_label ();
2762+ if (ANY_RETURN_P (trial))
2763+ trial = find_end_label (trial);
2764
2765 if (trial && trial != target_label
2766 && redirect_with_delay_slots_safe_p (delay_insn, trial, insn))
2767@@ -3517,7 +3541,7 @@
2768 later incorrectly compute register live/death info. */
2769 rtx tmp = next_active_insn (trial);
2770 if (tmp == 0)
2771- tmp = find_end_label ();
2772+ tmp = find_end_label (simple_return_rtx);
2773
2774 if (tmp)
2775 {
2776@@ -3537,14 +3561,12 @@
2777 delay list and that insn is redundant, thread the jump. */
2778 if (trial && GET_CODE (PATTERN (trial)) == SEQUENCE
2779 && XVECLEN (PATTERN (trial), 0) == 2
2780- && JUMP_P (XVECEXP (PATTERN (trial), 0, 0))
2781- && (simplejump_p (XVECEXP (PATTERN (trial), 0, 0))
2782- || GET_CODE (PATTERN (XVECEXP (PATTERN (trial), 0, 0))) == RETURN)
2783+ && simplejump_or_return_p (XVECEXP (PATTERN (trial), 0, 0))
2784 && redundant_insn (XVECEXP (PATTERN (trial), 0, 1), insn, 0))
2785 {
2786 target_label = JUMP_LABEL (XVECEXP (PATTERN (trial), 0, 0));
2787- if (target_label == 0)
2788- target_label = find_end_label ();
2789+ if (ANY_RETURN_P (target_label))
2790+ target_label = find_end_label (target_label);
2791
2792 if (target_label
2793 && redirect_with_delay_slots_safe_p (delay_insn, target_label,
2794@@ -3622,16 +3644,15 @@
2795 a RETURN here. */
2796 if (! INSN_ANNULLED_BRANCH_P (delay_insn)
2797 && any_condjump_p (delay_insn)
2798- && next && JUMP_P (next)
2799- && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
2800+ && next && simplejump_or_return_p (next)
2801 && next_active_insn (target_label) == next_active_insn (next)
2802 && no_labels_between_p (insn, next))
2803 {
2804 rtx label = JUMP_LABEL (next);
2805 rtx old_label = JUMP_LABEL (delay_insn);
2806
2807- if (label == 0)
2808- label = find_end_label ();
2809+ if (ANY_RETURN_P (label))
2810+ label = find_end_label (label);
2811
2812 /* find_end_label can generate a new label. Check this first. */
2813 if (label
2814@@ -3692,7 +3713,8 @@
2815 make_return_insns (rtx first)
2816 {
2817 rtx insn, jump_insn, pat;
2818- rtx real_return_label = end_of_function_label;
2819+ rtx real_return_label = function_return_label;
2820+ rtx real_simple_return_label = function_simple_return_label;
2821 int slots, i;
2822
2823 #ifdef DELAY_SLOTS_FOR_EPILOGUE
2824@@ -3707,18 +3729,25 @@
2825 #endif
2826
2827 /* See if there is a RETURN insn in the function other than the one we
2828- made for END_OF_FUNCTION_LABEL. If so, set up anything we can't change
2829+ made for FUNCTION_RETURN_LABEL. If so, set up anything we can't change
2830 into a RETURN to jump to it. */
2831 for (insn = first; insn; insn = NEXT_INSN (insn))
2832- if (JUMP_P (insn) && GET_CODE (PATTERN (insn)) == RETURN)
2833+ if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
2834 {
2835- real_return_label = get_label_before (insn);
2836+ rtx t = get_label_before (insn);
2837+ if (PATTERN (insn) == ret_rtx)
2838+ real_return_label = t;
2839+ else
2840+ real_simple_return_label = t;
2841 break;
2842 }
2843
2844 /* Show an extra usage of REAL_RETURN_LABEL so it won't go away if it
2845- was equal to END_OF_FUNCTION_LABEL. */
2846- LABEL_NUSES (real_return_label)++;
2847+ was equal to FUNCTION_RETURN_LABEL. */
2848+ if (real_return_label)
2849+ LABEL_NUSES (real_return_label)++;
2850+ if (real_simple_return_label)
2851+ LABEL_NUSES (real_simple_return_label)++;
2852
2853 /* Clear the list of insns to fill so we can use it. */
2854 obstack_free (&unfilled_slots_obstack, unfilled_firstobj);
2855@@ -3726,13 +3755,27 @@
2856 for (insn = first; insn; insn = NEXT_INSN (insn))
2857 {
2858 int flags;
2859+ rtx kind, real_label;
2860
2861 /* Only look at filled JUMP_INSNs that go to the end of function
2862 label. */
2863 if (!NONJUMP_INSN_P (insn)
2864 || GET_CODE (PATTERN (insn)) != SEQUENCE
2865- || !JUMP_P (XVECEXP (PATTERN (insn), 0, 0))
2866- || JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) != end_of_function_label)
2867+ || !JUMP_P (XVECEXP (PATTERN (insn), 0, 0)))
2868+ continue;
2869+
2870+ if (JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) == function_return_label)
2871+ {
2872+ kind = ret_rtx;
2873+ real_label = real_return_label;
2874+ }
2875+ else if (JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0))
2876+ == function_simple_return_label)
2877+ {
2878+ kind = simple_return_rtx;
2879+ real_label = real_simple_return_label;
2880+ }
2881+ else
2882 continue;
2883
2884 pat = PATTERN (insn);
2885@@ -3740,14 +3783,12 @@
2886
2887 /* If we can't make the jump into a RETURN, try to redirect it to the best
2888 RETURN and go on to the next insn. */
2889- if (! reorg_redirect_jump (jump_insn, NULL_RTX))
2890+ if (! reorg_redirect_jump (jump_insn, kind))
2891 {
2892 /* Make sure redirecting the jump will not invalidate the delay
2893 slot insns. */
2894- if (redirect_with_delay_slots_safe_p (jump_insn,
2895- real_return_label,
2896- insn))
2897- reorg_redirect_jump (jump_insn, real_return_label);
2898+ if (redirect_with_delay_slots_safe_p (jump_insn, real_label, insn))
2899+ reorg_redirect_jump (jump_insn, real_label);
2900 continue;
2901 }
2902
2903@@ -3787,7 +3828,7 @@
2904 RETURN, delete the SEQUENCE and output the individual insns,
2905 followed by the RETURN. Then set things up so we try to find
2906 insns for its delay slots, if it needs some. */
2907- if (GET_CODE (PATTERN (jump_insn)) == RETURN)
2908+ if (ANY_RETURN_P (PATTERN (jump_insn)))
2909 {
2910 rtx prev = PREV_INSN (insn);
2911
2912@@ -3804,13 +3845,16 @@
2913 else
2914 /* It is probably more efficient to keep this with its current
2915 delay slot as a branch to a RETURN. */
2916- reorg_redirect_jump (jump_insn, real_return_label);
2917+ reorg_redirect_jump (jump_insn, real_label);
2918 }
2919
2920 /* Now delete REAL_RETURN_LABEL if we never used it. Then try to fill any
2921 new delay slots we have created. */
2922- if (--LABEL_NUSES (real_return_label) == 0)
2923+ if (real_return_label != NULL_RTX && --LABEL_NUSES (real_return_label) == 0)
2924 delete_related_insns (real_return_label);
2925+ if (real_simple_return_label != NULL_RTX
2926+ && --LABEL_NUSES (real_simple_return_label) == 0)
2927+ delete_related_insns (real_simple_return_label);
2928
2929 fill_simple_delay_slots (1);
2930 fill_simple_delay_slots (0);
2931@@ -3878,7 +3922,7 @@
2932 init_resource_info (epilogue_insn);
2933
2934 /* Show we haven't computed an end-of-function label yet. */
2935- end_of_function_label = 0;
2936+ function_return_label = function_simple_return_label = NULL_RTX;
2937
2938 /* Initialize the statistics for this function. */
2939 memset (num_insns_needing_delays, 0, sizeof num_insns_needing_delays);
2940@@ -3900,11 +3944,23 @@
2941 /* If we made an end of function label, indicate that it is now
2942 safe to delete it by undoing our prior adjustment to LABEL_NUSES.
2943 If it is now unused, delete it. */
2944- if (end_of_function_label && --LABEL_NUSES (end_of_function_label) == 0)
2945- delete_related_insns (end_of_function_label);
2946+ if (function_return_label && --LABEL_NUSES (function_return_label) == 0)
2947+ delete_related_insns (function_return_label);
2948+ if (function_simple_return_label
2949+ && --LABEL_NUSES (function_simple_return_label) == 0)
2950+ delete_related_insns (function_simple_return_label);
2951
2952+#if defined HAVE_return || defined HAVE_simple_return
2953+ if (
2954 #ifdef HAVE_return
2955- if (HAVE_return && end_of_function_label != 0)
2956+ (HAVE_return && function_return_label != 0)
2957+#else
2958+ 0
2959+#endif
2960+#ifdef HAVE_simple_return
2961+ || (HAVE_simple_return && function_simple_return_label != 0)
2962+#endif
2963+ )
2964 make_return_insns (first);
2965 #endif
2966
2967
2968=== modified file 'gcc/resource.c'
2969--- old/gcc/resource.c 2009-11-25 10:55:54 +0000
2970+++ new/gcc/resource.c 2011-01-05 12:12:18 +0000
2971@@ -495,6 +495,8 @@
2972 || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
2973 {
2974 next = JUMP_LABEL (this_jump_insn);
2975+ if (next && ANY_RETURN_P (next))
2976+ next = NULL_RTX;
2977 if (jump_insn == 0)
2978 {
2979 jump_insn = insn;
2980@@ -562,9 +564,10 @@
2981 AND_COMPL_HARD_REG_SET (scratch, needed.regs);
2982 AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
2983
2984- find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
2985- &target_res, 0, jump_count,
2986- target_set, needed);
2987+ if (!ANY_RETURN_P (JUMP_LABEL (this_jump_insn)))
2988+ find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
2989+ &target_res, 0, jump_count,
2990+ target_set, needed);
2991 find_dead_or_set_registers (next,
2992 &fallthrough_res, 0, jump_count,
2993 set, needed);
2994@@ -1097,6 +1100,8 @@
2995 struct resources new_resources;
2996 rtx stop_insn = next_active_insn (jump_insn);
2997
2998+ if (jump_target && ANY_RETURN_P (jump_target))
2999+ jump_target = NULL_RTX;
3000 mark_target_live_regs (insns, next_active_insn (jump_target),
3001 &new_resources);
3002 CLEAR_RESOURCE (&set);
3003
3004=== modified file 'gcc/rtl.c'
3005--- old/gcc/rtl.c 2010-12-13 10:05:52 +0000
3006+++ new/gcc/rtl.c 2011-01-05 12:12:18 +0000
3007@@ -256,6 +256,8 @@
3008 case CODE_LABEL:
3009 case PC:
3010 case CC0:
3011+ case RETURN:
3012+ case SIMPLE_RETURN:
3013 case SCRATCH:
3014 /* SCRATCH must be shared because they represent distinct values. */
3015 return orig;
3016
3017=== modified file 'gcc/rtl.def'
3018--- old/gcc/rtl.def 2010-04-02 18:54:46 +0000
3019+++ new/gcc/rtl.def 2011-01-05 12:12:18 +0000
3020@@ -296,6 +296,10 @@
3021
3022 DEF_RTL_EXPR(RETURN, "return", "", RTX_EXTRA)
3023
3024+/* A plain return, to be used on paths that are reached without going
3025+ through the function prologue. */
3026+DEF_RTL_EXPR(SIMPLE_RETURN, "simple_return", "", RTX_EXTRA)
3027+
3028 /* Special for EH return from subroutine. */
3029
3030 DEF_RTL_EXPR(EH_RETURN, "eh_return", "", RTX_EXTRA)
3031
3032=== modified file 'gcc/rtl.h'
3033--- old/gcc/rtl.h 2010-11-16 22:17:17 +0000
3034+++ new/gcc/rtl.h 2011-01-05 12:12:18 +0000
3035@@ -411,6 +411,10 @@
3036 (JUMP_P (INSN) && (GET_CODE (PATTERN (INSN)) == ADDR_VEC || \
3037 GET_CODE (PATTERN (INSN)) == ADDR_DIFF_VEC))
3038
3039+/* Predicate yielding nonzero iff X is a return or simple_preturn. */
3040+#define ANY_RETURN_P(X) \
3041+ (GET_CODE (X) == RETURN || GET_CODE (X) == SIMPLE_RETURN)
3042+
3043 /* 1 if X is a unary operator. */
3044
3045 #define UNARY_P(X) \
3046@@ -1998,6 +2002,8 @@
3047 {
3048 GR_PC,
3049 GR_CC0,
3050+ GR_RETURN,
3051+ GR_SIMPLE_RETURN,
3052 GR_STACK_POINTER,
3053 GR_FRAME_POINTER,
3054 /* For register elimination to work properly these hard_frame_pointer_rtx,
3055@@ -2032,6 +2038,8 @@
3056
3057 /* Standard pieces of rtx, to be substituted directly into things. */
3058 #define pc_rtx (global_rtl[GR_PC])
3059+#define ret_rtx (global_rtl[GR_RETURN])
3060+#define simple_return_rtx (global_rtl[GR_SIMPLE_RETURN])
3061 #define cc0_rtx (global_rtl[GR_CC0])
3062
3063 /* All references to certain hard regs, except those created
3064
3065=== modified file 'gcc/rtlanal.c'
3066--- old/gcc/rtlanal.c 2010-11-16 22:17:17 +0000
3067+++ new/gcc/rtlanal.c 2011-01-05 12:12:18 +0000
3068@@ -2673,6 +2673,7 @@
3069
3070 if (JUMP_P (insn)
3071 && (label = JUMP_LABEL (insn)) != NULL_RTX
3072+ && !ANY_RETURN_P (label)
3073 && (table = next_active_insn (label)) != NULL_RTX
3074 && JUMP_TABLE_DATA_P (table))
3075 {
3076
3077=== modified file 'gcc/sched-int.h'
3078--- old/gcc/sched-int.h 2010-06-02 16:31:39 +0000
3079+++ new/gcc/sched-int.h 2011-01-05 12:12:18 +0000
3080@@ -199,7 +199,7 @@
3081
3082 extern void ebb_compute_jump_reg_dependencies (rtx, regset, regset, regset);
3083
3084-extern edge find_fallthru_edge (basic_block);
3085+extern edge find_fallthru_edge_from (basic_block);
3086
3087 extern void (* sched_init_only_bb) (basic_block, basic_block);
3088 extern basic_block (* sched_split_block) (basic_block, rtx);
3089
3090=== modified file 'gcc/sched-vis.c'
3091--- old/gcc/sched-vis.c 2009-11-25 10:55:54 +0000
3092+++ new/gcc/sched-vis.c 2011-01-05 12:12:18 +0000
3093@@ -549,6 +549,9 @@
3094 case RETURN:
3095 sprintf (buf, "return");
3096 break;
3097+ case SIMPLE_RETURN:
3098+ sprintf (buf, "simple_return");
3099+ break;
3100 case CALL:
3101 print_exp (buf, x, verbose);
3102 break;
3103
3104=== modified file 'gcc/sel-sched-ir.c'
3105--- old/gcc/sel-sched-ir.c 2010-08-31 11:52:01 +0000
3106+++ new/gcc/sel-sched-ir.c 2011-01-05 12:12:18 +0000
3107@@ -686,7 +686,7 @@
3108
3109 /* Find fallthrough edge. */
3110 gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb);
3111- candidate = find_fallthru_edge (BLOCK_FOR_INSN (insn)->prev_bb);
3112+ candidate = find_fallthru_edge_from (BLOCK_FOR_INSN (insn)->prev_bb);
3113
3114 if (!candidate
3115 || (candidate->src != BLOCK_FOR_INSN (last_scheduled_insn)
3116
3117=== modified file 'gcc/sel-sched.c'
3118--- old/gcc/sel-sched.c 2010-11-12 15:47:38 +0000
3119+++ new/gcc/sel-sched.c 2011-01-05 12:12:18 +0000
3120@@ -617,8 +617,8 @@
3121 if (bb == BLOCK_FOR_INSN (succ))
3122 return true;
3123
3124- if (find_fallthru_edge (bb))
3125- bb = find_fallthru_edge (bb)->dest;
3126+ if (find_fallthru_edge_from (bb))
3127+ bb = find_fallthru_edge_from (bb)->dest;
3128 else
3129 return false;
3130
3131@@ -4911,7 +4911,7 @@
3132 next = PREV_INSN (insn);
3133 BND_TO (bnd) = insn;
3134
3135- ft_edge = find_fallthru_edge (block_from);
3136+ ft_edge = find_fallthru_edge_from (block_from);
3137 block_next = ft_edge->dest;
3138 /* There must be a fallthrough block (or where should go
3139 control flow in case of false jump predicate otherwise?). */
3140
3141=== modified file 'gcc/vec.h'
3142--- old/gcc/vec.h 2010-01-09 14:46:25 +0000
3143+++ new/gcc/vec.h 2011-01-05 12:12:18 +0000
3144@@ -188,6 +188,18 @@
3145
3146 #define VEC_iterate(T,V,I,P) (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P)))
3147
3148+/* Convenience macro for forward iteration. */
3149+
3150+#define FOR_EACH_VEC_ELT(T, V, I, P) \
3151+ for (I = 0; VEC_iterate (T, (V), (I), (P)); ++(I))
3152+
3153+/* Convenience macro for reverse iteration. */
3154+
3155+#define FOR_EACH_VEC_ELT_REVERSE(T,V,I,P) \
3156+ for (I = VEC_length (T, (V)) - 1; \
3157+ VEC_iterate (T, (V), (I), (P)); \
3158+ (I)--)
3159+
3160 /* Allocate new vector.
3161 VEC(T,A) *VEC_T_A_alloc(int reserve);
3162
3163
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99457.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99457.patch
new file mode 100644
index 000000000..47b897d5e
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99457.patch
@@ -0,0 +1,4236 @@
12010-12-03 Yao Qi <yao@codesourcery.com>
2
3 * config/arm/arm-ldmstm.ml: Rewrite ldm/stm RTL patterns to fix
4 regressions.
5 * config/arm/ldmstm.md: Regenreate.
6
72010-12-03 Yao Qi <yao@codesourcery.com>
8
9 Backport from FSF mainline:
10
11 2010-08-02 Bernd Schmidt <bernds@codesourcery.com>
12
13 PR target/40457
14 * config/arm/arm.h (arm_regs_in_sequence): Declare.
15 * config/arm/arm-protos.h (emit_ldm_seq, emit_stm_seq,
16 load_multiple_sequence, store_multiple_sequence): Delete
17 declarations.
18 (arm_gen_load_multiple, arm_gen_store_multiple): Adjust
19 declarations.
20 * config/arm/ldmstm.md: New file.
21 * config/arm/arm.c (arm_regs_in_sequence): New array.
22 (load_multiple_sequence): Now static. New args SAVED_ORDER,
23 CHECK_REGS. All callers changed.
24 If SAVED_ORDER is nonnull, copy the computed order into it.
25 If CHECK_REGS is false, don't sort REGS. Handle Thumb mode.
26 (store_multiple_sequence): Now static. New args NOPS_TOTAL,
27 SAVED_ORDER, REG_RTXS and CHECK_REGS. All callers changed.
28 If SAVED_ORDER is nonnull, copy the computed order into it.
29 If CHECK_REGS is false, don't sort REGS. Set up REG_RTXS just
30 like REGS. Handle Thumb mode.
31 (arm_gen_load_multiple_1): New function, broken out of
32 arm_gen_load_multiple.
33 (arm_gen_store_multiple_1): New function, broken out of
34 arm_gen_store_multiple.
35 (arm_gen_multiple_op): New function, with code from
36 arm_gen_load_multiple and arm_gen_store_multiple moved here.
37 (arm_gen_load_multiple, arm_gen_store_multiple): Now just
38 wrappers around arm_gen_multiple_op. Remove argument UP, all callers
39 changed.
40 (gen_ldm_seq, gen_stm_seq, gen_const_stm_seq): New functions.
41 * config/arm/predicates.md (commutative_binary_operator): New.
42 (load_multiple_operation, store_multiple_operation): Handle more
43 variants of these patterns with different starting offsets. Handle
44 Thumb-1.
45 * config/arm/arm.md: Include "ldmstm.md".
46 (ldmsi_postinc4, ldmsi_postinc4_thumb1, ldmsi_postinc3, ldmsi_postinc2,
47 ldmsi4, ldmsi3, ldmsi2, stmsi_postinc4, stmsi_postinc4_thumb1,
48 stmsi_postinc3, stmsi_postinc2, stmsi4, stmsi3, stmsi2 and related
49 peepholes): Delete.
50 * config/arm/ldmstm.md: New file.
51 * config/arm/arm-ldmstm.ml: New file.
52
53 * config/arm/arm.c (arm_rtx_costs_1): Remove second clause from the
54 if statement which adds extra costs to frame-related expressions.
55
56 2010-05-06 Bernd Schmidt <bernds@codesourcery.com>
57
58 * config/arm/arm.h (MAX_LDM_STM_OPS): New macro.
59 * config/arm/arm.c (multiple_operation_profitable_p,
60 compute_offset_order): New static functions.
61 (load_multiple_sequence, store_multiple_sequence): Use them.
62 Replace constant 4 with MAX_LDM_STM_OPS. Compute order[0] from
63 memory offsets, not register numbers.
64 (emit_ldm_seq, emit_stm_seq): Replace constant 4 with MAX_LDM_STM_OPS.
65
66 2010-04-16 Bernd Schmidt <bernds@codesourcery.com>
67
68 * recog.h (struct recog_data): New field is_operator.
69 (struct insn_operand_data): New field is_operator.
70 * recog.c (extract_insn): Set recog_data.is_operator.
71 * genoutput.c (output_operand_data): Emit code to set the
72 is_operator field.
73 * reload.c (find_reloads): Use it rather than testing for an
74 empty constraint string.
75
76=== added file 'gcc/config/arm/arm-ldmstm.ml'
77--- old/gcc/config/arm/arm-ldmstm.ml 1970-01-01 00:00:00 +0000
78+++ new/gcc/config/arm/arm-ldmstm.ml 2010-11-16 13:08:47 +0000
79@@ -0,0 +1,333 @@
80+(* Auto-generate ARM ldm/stm patterns
81+ Copyright (C) 2010 Free Software Foundation, Inc.
82+ Contributed by CodeSourcery.
83+
84+ This file is part of GCC.
85+
86+ GCC is free software; you can redistribute it and/or modify it under
87+ the terms of the GNU General Public License as published by the Free
88+ Software Foundation; either version 3, or (at your option) any later
89+ version.
90+
91+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
92+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
93+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
94+ for more details.
95+
96+ You should have received a copy of the GNU General Public License
97+ along with GCC; see the file COPYING3. If not see
98+ <http://www.gnu.org/licenses/>.
99+
100+ This is an O'Caml program. The O'Caml compiler is available from:
101+
102+ http://caml.inria.fr/
103+
104+ Or from your favourite OS's friendly packaging system. Tested with version
105+ 3.09.2, though other versions will probably work too.
106+
107+ Run with:
108+ ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.ml
109+*)
110+
111+type amode = IA | IB | DA | DB
112+
113+type optype = IN | OUT | INOUT
114+
115+let rec string_of_addrmode addrmode =
116+ match addrmode with
117+ IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
118+
119+let rec initial_offset addrmode nregs =
120+ match addrmode with
121+ IA -> 0
122+ | IB -> 4
123+ | DA -> -4 * nregs + 4
124+ | DB -> -4 * nregs
125+
126+let rec final_offset addrmode nregs =
127+ match addrmode with
128+ IA -> nregs * 4
129+ | IB -> nregs * 4
130+ | DA -> -4 * nregs
131+ | DB -> -4 * nregs
132+
133+let constr thumb =
134+ if thumb then "l" else "rk"
135+
136+let inout_constr op_type =
137+ match op_type with
138+ OUT -> "="
139+ | INOUT -> "+&"
140+ | IN -> ""
141+
142+let destreg nregs first op_type thumb =
143+ if not first then
144+ Printf.sprintf "(match_dup %d)" (nregs)
145+ else
146+ Printf.sprintf ("(match_operand:SI %d \"s_register_operand\" \"%s%s\")")
147+ (nregs) (inout_constr op_type) (constr thumb)
148+
149+let write_ldm_set thumb nregs offset opnr first =
150+ let indent = " " in
151+ Printf.printf "%s" (if first then " [" else indent);
152+ Printf.printf "(set (match_operand:SI %d \"arm_hard_register_operand\" \"\")\n" opnr;
153+ Printf.printf "%s (mem:SI " indent;
154+ begin if offset != 0 then Printf.printf "(plus:SI " end;
155+ Printf.printf "%s" (destreg nregs first IN thumb);
156+ begin if offset != 0 then Printf.printf "\n%s (const_int %d))" indent offset end;
157+ Printf.printf "))"
158+
159+let write_stm_set thumb nregs offset opnr first =
160+ let indent = " " in
161+ Printf.printf "%s" (if first then " [" else indent);
162+ Printf.printf "(set (mem:SI ";
163+ begin if offset != 0 then Printf.printf "(plus:SI " end;
164+ Printf.printf "%s" (destreg nregs first IN thumb);
165+ begin if offset != 0 then Printf.printf " (const_int %d))" offset end;
166+ Printf.printf ")\n%s (match_operand:SI %d \"arm_hard_register_operand\" \"\"))" indent opnr
167+
168+let write_ldm_peep_set extra_indent nregs opnr first =
169+ let indent = " " ^ extra_indent in
170+ Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
171+ Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
172+ Printf.printf "%s (match_operand:SI %d \"memory_operand\" \"\"))" indent (nregs + opnr)
173+
174+let write_stm_peep_set extra_indent nregs opnr first =
175+ let indent = " " ^ extra_indent in
176+ Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
177+ Printf.printf "(set (match_operand:SI %d \"memory_operand\" \"\")\n" (nregs + opnr);
178+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\"))" indent opnr
179+
180+let write_any_load optype nregs opnr first =
181+ let indent = " " in
182+ Printf.printf "%s" (if first then " [" else indent);
183+ Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
184+ Printf.printf "%s (match_operand:SI %d \"%s\" \"\"))" indent (nregs * 2 + opnr) optype
185+
186+let write_const_store nregs opnr first =
187+ let indent = " " in
188+ Printf.printf "%s(set (match_operand:SI %d \"memory_operand\" \"\")\n" indent (nregs + opnr);
189+ Printf.printf "%s (match_dup %d))" indent opnr
190+
191+let write_const_stm_peep_set nregs opnr first =
192+ write_any_load "const_int_operand" nregs opnr first;
193+ Printf.printf "\n";
194+ write_const_store nregs opnr false
195+
196+
197+let rec write_pat_sets func opnr offset first n_left =
198+ func offset opnr first;
199+ begin
200+ if n_left > 1 then begin
201+ Printf.printf "\n";
202+ write_pat_sets func (opnr + 1) (offset + 4) false (n_left - 1);
203+ end else
204+ Printf.printf "]"
205+ end
206+
207+let rec write_peep_sets func opnr first n_left =
208+ func opnr first;
209+ begin
210+ if n_left > 1 then begin
211+ Printf.printf "\n";
212+ write_peep_sets func (opnr + 1) false (n_left - 1);
213+ end
214+ end
215+
216+let can_thumb addrmode update is_store =
217+ match addrmode, update, is_store with
218+ (* Thumb1 mode only supports IA with update. However, for LDMIA,
219+ if the address register also appears in the list of loaded
220+ registers, the loaded value is stored, hence the RTL pattern
221+ to describe such an insn does not have an update. We check
222+ in the match_parallel predicate that the condition described
223+ above is met. *)
224+ IA, _, false -> true
225+ | IA, true, true -> true
226+ | _ -> false
227+
228+let target addrmode thumb =
229+ match addrmode, thumb with
230+ IA, true -> "TARGET_THUMB1"
231+ | IA, false -> "TARGET_32BIT"
232+ | DB, false -> "TARGET_32BIT"
233+ | _, false -> "TARGET_ARM"
234+
235+let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
236+ let astr = string_of_addrmode addrmode in
237+ Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
238+ (if thumb then "thumb_" else "") name nregs astr
239+ (if update then "_update" else "");
240+ Printf.printf " [(match_parallel 0 \"%s_multiple_operation\"\n" ls;
241+ begin
242+ if update then begin
243+ Printf.printf " [(set %s\n (plus:SI "
244+ (destreg 1 true OUT thumb); (*destreg 2 true IN thumb*)
245+ Printf.printf "(match_operand:SI 2 \"s_register_operand\" \"1\")";
246+ Printf.printf " (const_int %d)))\n"
247+ (final_offset addrmode nregs)
248+ end
249+ end;
250+ write_pat_sets
251+ (write_set_fn thumb (if update then 2 else 1)) (if update then 3 else 2)
252+ (initial_offset addrmode nregs)
253+ (not update) nregs;
254+ Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
255+ (target addrmode thumb)
256+ (if update then nregs + 1 else nregs);
257+ Printf.printf " \"%s%%(%s%%)\\t%%%d%s, {"
258+ name astr (1) (if update then "!" else "");
259+ for n = 1 to nregs; do
260+ Printf.printf "%%%d%s" (n+(if update then 2 else 1)) (if n < nregs then ", " else "")
261+ done;
262+ Printf.printf "}\"\n";
263+ Printf.printf " [(set_attr \"type\" \"%s%d\")" ls nregs;
264+ begin if not thumb then
265+ Printf.printf "\n (set_attr \"predicable\" \"yes\")";
266+ end;
267+ Printf.printf "])\n\n"
268+
269+let write_ldm_pattern addrmode nregs update =
270+ write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update false;
271+ begin if can_thumb addrmode update false then
272+ write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update true;
273+ end
274+
275+let write_stm_pattern addrmode nregs update =
276+ write_pattern_1 "stm" "store" addrmode nregs write_stm_set update false;
277+ begin if can_thumb addrmode update true then
278+ write_pattern_1 "stm" "store" addrmode nregs write_stm_set update true;
279+ end
280+
281+let write_ldm_commutative_peephole thumb =
282+ let nregs = 2 in
283+ Printf.printf "(define_peephole2\n";
284+ write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
285+ let indent = " " in
286+ if thumb then begin
287+ Printf.printf "\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
288+ Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
289+ Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
290+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
291+ end else begin
292+ Printf.printf "\n%s(parallel\n" indent;
293+ Printf.printf "%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
294+ Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
295+ Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
296+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
297+ Printf.printf "%s (clobber (reg:CC CC_REGNUM))])]\n" indent
298+ end;
299+ Printf.printf " \"(((operands[%d] == operands[0] && operands[%d] == operands[1])\n" (nregs * 2 + 2) (nregs * 2 + 3);
300+ Printf.printf " || (operands[%d] == operands[0] && operands[%d] == operands[1]))\n" (nregs * 2 + 3) (nregs * 2 + 2);
301+ Printf.printf " && peep2_reg_dead_p (%d, operands[0]) && peep2_reg_dead_p (%d, operands[1]))\"\n" (nregs + 1) (nregs + 1);
302+ begin
303+ if thumb then
304+ Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
305+ (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
306+ else begin
307+ Printf.printf " [(parallel\n";
308+ Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
309+ (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
310+ Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
311+ end
312+ end;
313+ Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
314+ Printf.printf "})\n\n"
315+
316+let write_ldm_peephole nregs =
317+ Printf.printf "(define_peephole2\n";
318+ write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
319+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
320+ Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
321+
322+let write_ldm_peephole_b nregs =
323+ if nregs > 2 then begin
324+ Printf.printf "(define_peephole2\n";
325+ write_ldm_peep_set "" nregs 0 true;
326+ Printf.printf "\n (parallel\n";
327+ write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
328+ Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
329+ Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
330+ end
331+
332+let write_stm_peephole nregs =
333+ Printf.printf "(define_peephole2\n";
334+ write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
335+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
336+ Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
337+
338+let write_stm_peephole_b nregs =
339+ if nregs > 2 then begin
340+ Printf.printf "(define_peephole2\n";
341+ write_stm_peep_set "" nregs 0 true;
342+ Printf.printf "\n (parallel\n";
343+ write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
344+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
345+ Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
346+ end
347+
348+let write_const_stm_peephole_a nregs =
349+ Printf.printf "(define_peephole2\n";
350+ write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
351+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
352+ Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
353+
354+let write_const_stm_peephole_b nregs =
355+ Printf.printf "(define_peephole2\n";
356+ write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
357+ Printf.printf "\n";
358+ write_peep_sets (write_const_store nregs) 0 false nregs;
359+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
360+ Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
361+
362+let patterns () =
363+ let addrmodes = [ IA; IB; DA; DB ] in
364+ let sizes = [ 4; 3; 2] in
365+ List.iter
366+ (fun n ->
367+ List.iter
368+ (fun addrmode ->
369+ write_ldm_pattern addrmode n false;
370+ write_ldm_pattern addrmode n true;
371+ write_stm_pattern addrmode n false;
372+ write_stm_pattern addrmode n true)
373+ addrmodes;
374+ write_ldm_peephole n;
375+ write_ldm_peephole_b n;
376+ write_const_stm_peephole_a n;
377+ write_const_stm_peephole_b n;
378+ write_stm_peephole n;)
379+ sizes;
380+ write_ldm_commutative_peephole false;
381+ write_ldm_commutative_peephole true
382+
383+let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
384+
385+(* Do it. *)
386+
387+let _ =
388+ print_lines [
389+"/* ARM ldm/stm instruction patterns. This file was automatically generated";
390+" using arm-ldmstm.ml. Please do not edit manually.";
391+"";
392+" Copyright (C) 2010 Free Software Foundation, Inc.";
393+" Contributed by CodeSourcery.";
394+"";
395+" This file is part of GCC.";
396+"";
397+" GCC is free software; you can redistribute it and/or modify it";
398+" under the terms of the GNU General Public License as published";
399+" by the Free Software Foundation; either version 3, or (at your";
400+" option) any later version.";
401+"";
402+" GCC is distributed in the hope that it will be useful, but WITHOUT";
403+" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
404+" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
405+" License for more details.";
406+"";
407+" You should have received a copy of the GNU General Public License and";
408+" a copy of the GCC Runtime Library Exception along with this program;";
409+" see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
410+" <http://www.gnu.org/licenses/>. */";
411+""];
412+ patterns ();
413
414=== modified file 'gcc/config/arm/arm-protos.h'
415--- old/gcc/config/arm/arm-protos.h 2011-01-05 12:12:18 +0000
416+++ new/gcc/config/arm/arm-protos.h 2011-01-05 18:20:37 +0000
417@@ -100,14 +100,11 @@
418 extern int label_mentioned_p (rtx);
419 extern RTX_CODE minmax_code (rtx);
420 extern int adjacent_mem_locations (rtx, rtx);
421-extern int load_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
422-extern const char *emit_ldm_seq (rtx *, int);
423-extern int store_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
424-extern const char * emit_stm_seq (rtx *, int);
425-extern rtx arm_gen_load_multiple (int, int, rtx, int, int,
426- rtx, HOST_WIDE_INT *);
427-extern rtx arm_gen_store_multiple (int, int, rtx, int, int,
428- rtx, HOST_WIDE_INT *);
429+extern bool gen_ldm_seq (rtx *, int, bool);
430+extern bool gen_stm_seq (rtx *, int);
431+extern bool gen_const_stm_seq (rtx *, int);
432+extern rtx arm_gen_load_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
433+extern rtx arm_gen_store_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
434 extern int arm_gen_movmemqi (rtx *);
435 extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
436 extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
437
438=== modified file 'gcc/config/arm/arm.c'
439--- old/gcc/config/arm/arm.c 2011-01-05 12:12:18 +0000
440+++ new/gcc/config/arm/arm.c 2011-01-05 18:20:37 +0000
441@@ -753,6 +753,12 @@
442 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
443 };
444
445+/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
446+int arm_regs_in_sequence[] =
447+{
448+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
449+};
450+
451 #define ARM_LSL_NAME (TARGET_UNIFIED_ASM ? "lsl" : "asl")
452 #define streq(string1, string2) (strcmp (string1, string2) == 0)
453
454@@ -9680,142 +9686,16 @@
455 return 0;
456 }
457
458-int
459-load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
460- HOST_WIDE_INT *load_offset)
461-{
462- int unsorted_regs[4];
463- HOST_WIDE_INT unsorted_offsets[4];
464- int order[4];
465- int base_reg = -1;
466- int i;
467-
468- if (low_irq_latency)
469- return 0;
470-
471- /* Can only handle 2, 3, or 4 insns at present,
472- though could be easily extended if required. */
473- gcc_assert (nops >= 2 && nops <= 4);
474-
475- memset (order, 0, 4 * sizeof (int));
476-
477- /* Loop over the operands and check that the memory references are
478- suitable (i.e. immediate offsets from the same base register). At
479- the same time, extract the target register, and the memory
480- offsets. */
481- for (i = 0; i < nops; i++)
482- {
483- rtx reg;
484- rtx offset;
485-
486- /* Convert a subreg of a mem into the mem itself. */
487- if (GET_CODE (operands[nops + i]) == SUBREG)
488- operands[nops + i] = alter_subreg (operands + (nops + i));
489-
490- gcc_assert (GET_CODE (operands[nops + i]) == MEM);
491-
492- /* Don't reorder volatile memory references; it doesn't seem worth
493- looking for the case where the order is ok anyway. */
494- if (MEM_VOLATILE_P (operands[nops + i]))
495- return 0;
496-
497- offset = const0_rtx;
498-
499- if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
500- || (GET_CODE (reg) == SUBREG
501- && GET_CODE (reg = SUBREG_REG (reg)) == REG))
502- || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
503- && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
504- == REG)
505- || (GET_CODE (reg) == SUBREG
506- && GET_CODE (reg = SUBREG_REG (reg)) == REG))
507- && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
508- == CONST_INT)))
509- {
510- if (i == 0)
511- {
512- base_reg = REGNO (reg);
513- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
514- ? REGNO (operands[i])
515- : REGNO (SUBREG_REG (operands[i])));
516- order[0] = 0;
517- }
518- else
519- {
520- if (base_reg != (int) REGNO (reg))
521- /* Not addressed from the same base register. */
522- return 0;
523-
524- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
525- ? REGNO (operands[i])
526- : REGNO (SUBREG_REG (operands[i])));
527- if (unsorted_regs[i] < unsorted_regs[order[0]])
528- order[0] = i;
529- }
530-
531- /* If it isn't an integer register, or if it overwrites the
532- base register but isn't the last insn in the list, then
533- we can't do this. */
534- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14
535- || (i != nops - 1 && unsorted_regs[i] == base_reg))
536- return 0;
537-
538- unsorted_offsets[i] = INTVAL (offset);
539- }
540- else
541- /* Not a suitable memory address. */
542- return 0;
543- }
544-
545- /* All the useful information has now been extracted from the
546- operands into unsorted_regs and unsorted_offsets; additionally,
547- order[0] has been set to the lowest numbered register in the
548- list. Sort the registers into order, and check that the memory
549- offsets are ascending and adjacent. */
550-
551- for (i = 1; i < nops; i++)
552- {
553- int j;
554-
555- order[i] = order[i - 1];
556- for (j = 0; j < nops; j++)
557- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
558- && (order[i] == order[i - 1]
559- || unsorted_regs[j] < unsorted_regs[order[i]]))
560- order[i] = j;
561-
562- /* Have we found a suitable register? if not, one must be used more
563- than once. */
564- if (order[i] == order[i - 1])
565- return 0;
566-
567- /* Is the memory address adjacent and ascending? */
568- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
569- return 0;
570- }
571-
572- if (base)
573- {
574- *base = base_reg;
575-
576- for (i = 0; i < nops; i++)
577- regs[i] = unsorted_regs[order[i]];
578-
579- *load_offset = unsorted_offsets[order[0]];
580- }
581-
582- if (unsorted_offsets[order[0]] == 0)
583- return 1; /* ldmia */
584-
585- if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
586- return 2; /* ldmib */
587-
588- if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
589- return 3; /* ldmda */
590-
591- if (unsorted_offsets[order[nops - 1]] == -4)
592- return 4; /* ldmdb */
593-
594+
595+/* Return true iff it would be profitable to turn a sequence of NOPS loads
596+ or stores (depending on IS_STORE) into a load-multiple or store-multiple
597+ instruction. ADD_OFFSET is nonzero if the base address register needs
598+ to be modified with an add instruction before we can use it. */
599+
600+static bool
601+multiple_operation_profitable_p (bool is_store ATTRIBUTE_UNUSED,
602+ int nops, HOST_WIDE_INT add_offset)
603+ {
604 /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
605 if the offset isn't small enough. The reason 2 ldrs are faster
606 is because these ARMs are able to do more than one cache access
607@@ -9845,91 +9725,239 @@
608 We cheat here and test 'arm_ld_sched' which we currently know to
609 only be true for the ARM8, ARM9 and StrongARM. If this ever
610 changes, then the test below needs to be reworked. */
611- if (nops == 2 && arm_ld_sched)
612+ if (nops == 2 && arm_ld_sched && add_offset != 0)
613+ return false;
614+
615+ return true;
616+}
617+
618+/* Subroutine of load_multiple_sequence and store_multiple_sequence.
619+ Given an array of UNSORTED_OFFSETS, of which there are NOPS, compute
620+ an array ORDER which describes the sequence to use when accessing the
621+ offsets that produces an ascending order. In this sequence, each
622+ offset must be larger by exactly 4 than the previous one. ORDER[0]
623+ must have been filled in with the lowest offset by the caller.
624+ If UNSORTED_REGS is nonnull, it is an array of register numbers that
625+ we use to verify that ORDER produces an ascending order of registers.
626+ Return true if it was possible to construct such an order, false if
627+ not. */
628+
629+static bool
630+compute_offset_order (int nops, HOST_WIDE_INT *unsorted_offsets, int *order,
631+ int *unsorted_regs)
632+{
633+ int i;
634+ for (i = 1; i < nops; i++)
635+ {
636+ int j;
637+
638+ order[i] = order[i - 1];
639+ for (j = 0; j < nops; j++)
640+ if (unsorted_offsets[j] == unsorted_offsets[order[i - 1]] + 4)
641+ {
642+ /* We must find exactly one offset that is higher than the
643+ previous one by 4. */
644+ if (order[i] != order[i - 1])
645+ return false;
646+ order[i] = j;
647+ }
648+ if (order[i] == order[i - 1])
649+ return false;
650+ /* The register numbers must be ascending. */
651+ if (unsorted_regs != NULL
652+ && unsorted_regs[order[i]] <= unsorted_regs[order[i - 1]])
653+ return false;
654+ }
655+ return true;
656+}
657+
658+/* Used to determine in a peephole whether a sequence of load
659+ instructions can be changed into a load-multiple instruction.
660+ NOPS is the number of separate load instructions we are examining. The
661+ first NOPS entries in OPERANDS are the destination registers, the
662+ next NOPS entries are memory operands. If this function is
663+ successful, *BASE is set to the common base register of the memory
664+ accesses; *LOAD_OFFSET is set to the first memory location's offset
665+ from that base register.
666+ REGS is an array filled in with the destination register numbers.
667+ SAVED_ORDER (if nonnull), is an array filled in with an order that maps
668+ insn numbers to to an ascending order of stores. If CHECK_REGS is true,
669+ the sequence of registers in REGS matches the loads from ascending memory
670+ locations, and the function verifies that the register numbers are
671+ themselves ascending. If CHECK_REGS is false, the register numbers
672+ are stored in the order they are found in the operands. */
673+static int
674+load_multiple_sequence (rtx *operands, int nops, int *regs, int *saved_order,
675+ int *base, HOST_WIDE_INT *load_offset, bool check_regs)
676+{
677+ int unsorted_regs[MAX_LDM_STM_OPS];
678+ HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
679+ int order[MAX_LDM_STM_OPS];
680+ rtx base_reg_rtx = NULL;
681+ int base_reg = -1;
682+ int i, ldm_case;
683+
684+ if (low_irq_latency)
685 return 0;
686
687- /* Can't do it without setting up the offset, only do this if it takes
688- no more than one insn. */
689- return (const_ok_for_arm (unsorted_offsets[order[0]])
690- || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
691-}
692-
693-const char *
694-emit_ldm_seq (rtx *operands, int nops)
695-{
696- int regs[4];
697- int base_reg;
698- HOST_WIDE_INT offset;
699- char buf[100];
700- int i;
701-
702- switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
703+ /* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
704+ easily extended if required. */
705+ gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
706+
707+ memset (order, 0, MAX_LDM_STM_OPS * sizeof (int));
708+
709+ /* Loop over the operands and check that the memory references are
710+ suitable (i.e. immediate offsets from the same base register). At
711+ the same time, extract the target register, and the memory
712+ offsets. */
713+ for (i = 0; i < nops; i++)
714 {
715- case 1:
716- strcpy (buf, "ldm%(ia%)\t");
717- break;
718-
719- case 2:
720- strcpy (buf, "ldm%(ib%)\t");
721- break;
722-
723- case 3:
724- strcpy (buf, "ldm%(da%)\t");
725- break;
726-
727- case 4:
728- strcpy (buf, "ldm%(db%)\t");
729- break;
730-
731- case 5:
732- if (offset >= 0)
733- sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
734- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
735- (long) offset);
736+ rtx reg;
737+ rtx offset;
738+
739+ /* Convert a subreg of a mem into the mem itself. */
740+ if (GET_CODE (operands[nops + i]) == SUBREG)
741+ operands[nops + i] = alter_subreg (operands + (nops + i));
742+
743+ gcc_assert (GET_CODE (operands[nops + i]) == MEM);
744+
745+ /* Don't reorder volatile memory references; it doesn't seem worth
746+ looking for the case where the order is ok anyway. */
747+ if (MEM_VOLATILE_P (operands[nops + i]))
748+ return 0;
749+
750+ offset = const0_rtx;
751+
752+ if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
753+ || (GET_CODE (reg) == SUBREG
754+ && GET_CODE (reg = SUBREG_REG (reg)) == REG))
755+ || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
756+ && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
757+ == REG)
758+ || (GET_CODE (reg) == SUBREG
759+ && GET_CODE (reg = SUBREG_REG (reg)) == REG))
760+ && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
761+ == CONST_INT)))
762+ {
763+ if (i == 0)
764+ {
765+ base_reg = REGNO (reg);
766+ base_reg_rtx = reg;
767+ if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
768+ return 0;
769+ }
770+ else if (base_reg != (int) REGNO (reg))
771+ /* Not addressed from the same base register. */
772+ return 0;
773+
774+ unsorted_regs[i] = (GET_CODE (operands[i]) == REG
775+ ? REGNO (operands[i])
776+ : REGNO (SUBREG_REG (operands[i])));
777+
778+ /* If it isn't an integer register, or if it overwrites the
779+ base register but isn't the last insn in the list, then
780+ we can't do this. */
781+ if (unsorted_regs[i] < 0
782+ || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
783+ || unsorted_regs[i] > 14
784+ || (i != nops - 1 && unsorted_regs[i] == base_reg))
785+ return 0;
786+
787+ unsorted_offsets[i] = INTVAL (offset);
788+ if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]])
789+ order[0] = i;
790+ }
791 else
792- sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
793- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
794- (long) -offset);
795- output_asm_insn (buf, operands);
796- base_reg = regs[0];
797- strcpy (buf, "ldm%(ia%)\t");
798- break;
799-
800- default:
801- gcc_unreachable ();
802- }
803-
804- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
805- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
806-
807- for (i = 1; i < nops; i++)
808- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
809- reg_names[regs[i]]);
810-
811- strcat (buf, "}\t%@ phole ldm");
812-
813- output_asm_insn (buf, operands);
814- return "";
815+ /* Not a suitable memory address. */
816+ return 0;
817+ }
818+
819+ /* All the useful information has now been extracted from the
820+ operands into unsorted_regs and unsorted_offsets; additionally,
821+ order[0] has been set to the lowest offset in the list. Sort
822+ the offsets into order, verifying that they are adjacent, and
823+ check that the register numbers are ascending. */
824+ if (!compute_offset_order (nops, unsorted_offsets, order,
825+ check_regs ? unsorted_regs : NULL))
826+ return 0;
827+
828+ if (saved_order)
829+ memcpy (saved_order, order, sizeof order);
830+
831+ if (base)
832+ {
833+ *base = base_reg;
834+
835+ for (i = 0; i < nops; i++)
836+ regs[i] = unsorted_regs[check_regs ? order[i] : i];
837+
838+ *load_offset = unsorted_offsets[order[0]];
839+ }
840+
841+ if (TARGET_THUMB1
842+ && !peep2_reg_dead_p (nops, base_reg_rtx))
843+ return 0;
844+
845+ if (unsorted_offsets[order[0]] == 0)
846+ ldm_case = 1; /* ldmia */
847+ else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
848+ ldm_case = 2; /* ldmib */
849+ else if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
850+ ldm_case = 3; /* ldmda */
851+ else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
852+ ldm_case = 4; /* ldmdb */
853+ else if (const_ok_for_arm (unsorted_offsets[order[0]])
854+ || const_ok_for_arm (-unsorted_offsets[order[0]]))
855+ ldm_case = 5;
856+ else
857+ return 0;
858+
859+ if (!multiple_operation_profitable_p (false, nops,
860+ ldm_case == 5
861+ ? unsorted_offsets[order[0]] : 0))
862+ return 0;
863+
864+ return ldm_case;
865 }
866
867-int
868-store_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
869- HOST_WIDE_INT * load_offset)
870+/* Used to determine in a peephole whether a sequence of store instructions can
871+ be changed into a store-multiple instruction.
872+ NOPS is the number of separate store instructions we are examining.
873+ NOPS_TOTAL is the total number of instructions recognized by the peephole
874+ pattern.
875+ The first NOPS entries in OPERANDS are the source registers, the next
876+ NOPS entries are memory operands. If this function is successful, *BASE is
877+ set to the common base register of the memory accesses; *LOAD_OFFSET is set
878+ to the first memory location's offset from that base register. REGS is an
879+ array filled in with the source register numbers, REG_RTXS (if nonnull) is
880+ likewise filled with the corresponding rtx's.
881+ SAVED_ORDER (if nonnull), is an array filled in with an order that maps insn
882+ numbers to to an ascending order of stores.
883+ If CHECK_REGS is true, the sequence of registers in *REGS matches the stores
884+ from ascending memory locations, and the function verifies that the register
885+ numbers are themselves ascending. If CHECK_REGS is false, the register
886+ numbers are stored in the order they are found in the operands. */
887+static int
888+store_multiple_sequence (rtx *operands, int nops, int nops_total,
889+ int *regs, rtx *reg_rtxs, int *saved_order, int *base,
890+ HOST_WIDE_INT *load_offset, bool check_regs)
891 {
892- int unsorted_regs[4];
893- HOST_WIDE_INT unsorted_offsets[4];
894- int order[4];
895+ int unsorted_regs[MAX_LDM_STM_OPS];
896+ rtx unsorted_reg_rtxs[MAX_LDM_STM_OPS];
897+ HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
898+ int order[MAX_LDM_STM_OPS];
899 int base_reg = -1;
900- int i;
901+ rtx base_reg_rtx = NULL;
902+ int i, stm_case;
903
904 if (low_irq_latency)
905 return 0;
906
907- /* Can only handle 2, 3, or 4 insns at present, though could be easily
908- extended if required. */
909- gcc_assert (nops >= 2 && nops <= 4);
910+ /* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
911+ easily extended if required. */
912+ gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
913
914- memset (order, 0, 4 * sizeof (int));
915+ memset (order, 0, MAX_LDM_STM_OPS * sizeof (int));
916
917 /* Loop over the operands and check that the memory references are
918 suitable (i.e. immediate offsets from the same base register). At
919@@ -9964,32 +9992,32 @@
920 && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
921 == CONST_INT)))
922 {
923+ unsorted_reg_rtxs[i] = (GET_CODE (operands[i]) == REG
924+ ? operands[i] : SUBREG_REG (operands[i]));
925+ unsorted_regs[i] = REGNO (unsorted_reg_rtxs[i]);
926+
927 if (i == 0)
928 {
929 base_reg = REGNO (reg);
930- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
931- ? REGNO (operands[i])
932- : REGNO (SUBREG_REG (operands[i])));
933- order[0] = 0;
934- }
935- else
936- {
937- if (base_reg != (int) REGNO (reg))
938- /* Not addressed from the same base register. */
939+ base_reg_rtx = reg;
940+ if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
941 return 0;
942-
943- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
944- ? REGNO (operands[i])
945- : REGNO (SUBREG_REG (operands[i])));
946- if (unsorted_regs[i] < unsorted_regs[order[0]])
947- order[0] = i;
948 }
949+ else if (base_reg != (int) REGNO (reg))
950+ /* Not addressed from the same base register. */
951+ return 0;
952
953 /* If it isn't an integer register, then we can't do this. */
954- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
955+ if (unsorted_regs[i] < 0
956+ || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
957+ || (TARGET_THUMB2 && unsorted_regs[i] == base_reg)
958+ || (TARGET_THUMB2 && unsorted_regs[i] == SP_REGNUM)
959+ || unsorted_regs[i] > 14)
960 return 0;
961
962 unsorted_offsets[i] = INTVAL (offset);
963+ if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]])
964+ order[0] = i;
965 }
966 else
967 /* Not a suitable memory address. */
968@@ -9998,111 +10026,65 @@
969
970 /* All the useful information has now been extracted from the
971 operands into unsorted_regs and unsorted_offsets; additionally,
972- order[0] has been set to the lowest numbered register in the
973- list. Sort the registers into order, and check that the memory
974- offsets are ascending and adjacent. */
975-
976- for (i = 1; i < nops; i++)
977- {
978- int j;
979-
980- order[i] = order[i - 1];
981- for (j = 0; j < nops; j++)
982- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
983- && (order[i] == order[i - 1]
984- || unsorted_regs[j] < unsorted_regs[order[i]]))
985- order[i] = j;
986-
987- /* Have we found a suitable register? if not, one must be used more
988- than once. */
989- if (order[i] == order[i - 1])
990- return 0;
991-
992- /* Is the memory address adjacent and ascending? */
993- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
994- return 0;
995- }
996+ order[0] has been set to the lowest offset in the list. Sort
997+ the offsets into order, verifying that they are adjacent, and
998+ check that the register numbers are ascending. */
999+ if (!compute_offset_order (nops, unsorted_offsets, order,
1000+ check_regs ? unsorted_regs : NULL))
1001+ return 0;
1002+
1003+ if (saved_order)
1004+ memcpy (saved_order, order, sizeof order);
1005
1006 if (base)
1007 {
1008 *base = base_reg;
1009
1010 for (i = 0; i < nops; i++)
1011- regs[i] = unsorted_regs[order[i]];
1012+ {
1013+ regs[i] = unsorted_regs[check_regs ? order[i] : i];
1014+ if (reg_rtxs)
1015+ reg_rtxs[i] = unsorted_reg_rtxs[check_regs ? order[i] : i];
1016+ }
1017
1018 *load_offset = unsorted_offsets[order[0]];
1019 }
1020
1021+ if (TARGET_THUMB1
1022+ && !peep2_reg_dead_p (nops_total, base_reg_rtx))
1023+ return 0;
1024+
1025 if (unsorted_offsets[order[0]] == 0)
1026- return 1; /* stmia */
1027-
1028- if (unsorted_offsets[order[0]] == 4)
1029- return 2; /* stmib */
1030-
1031- if (unsorted_offsets[order[nops - 1]] == 0)
1032- return 3; /* stmda */
1033-
1034- if (unsorted_offsets[order[nops - 1]] == -4)
1035- return 4; /* stmdb */
1036-
1037- return 0;
1038-}
1039-
1040-const char *
1041-emit_stm_seq (rtx *operands, int nops)
1042-{
1043- int regs[4];
1044- int base_reg;
1045- HOST_WIDE_INT offset;
1046- char buf[100];
1047- int i;
1048-
1049- switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
1050- {
1051- case 1:
1052- strcpy (buf, "stm%(ia%)\t");
1053- break;
1054-
1055- case 2:
1056- strcpy (buf, "stm%(ib%)\t");
1057- break;
1058-
1059- case 3:
1060- strcpy (buf, "stm%(da%)\t");
1061- break;
1062-
1063- case 4:
1064- strcpy (buf, "stm%(db%)\t");
1065- break;
1066-
1067- default:
1068- gcc_unreachable ();
1069- }
1070-
1071- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
1072- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
1073-
1074- for (i = 1; i < nops; i++)
1075- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
1076- reg_names[regs[i]]);
1077-
1078- strcat (buf, "}\t%@ phole stm");
1079-
1080- output_asm_insn (buf, operands);
1081- return "";
1082+ stm_case = 1; /* stmia */
1083+ else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
1084+ stm_case = 2; /* stmib */
1085+ else if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
1086+ stm_case = 3; /* stmda */
1087+ else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
1088+ stm_case = 4; /* stmdb */
1089+ else
1090+ return 0;
1091+
1092+ if (!multiple_operation_profitable_p (false, nops, 0))
1093+ return 0;
1094+
1095+ return stm_case;
1096 }
1097
1098 /* Routines for use in generating RTL. */
1099
1100-rtx
1101-arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
1102- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1103+/* Generate a load-multiple instruction. COUNT is the number of loads in
1104+ the instruction; REGS and MEMS are arrays containing the operands.
1105+ BASEREG is the base register to be used in addressing the memory operands.
1106+ WBACK_OFFSET is nonzero if the instruction should update the base
1107+ register. */
1108+
1109+static rtx
1110+arm_gen_load_multiple_1 (int count, int *regs, rtx *mems, rtx basereg,
1111+ HOST_WIDE_INT wback_offset)
1112 {
1113- HOST_WIDE_INT offset = *offsetp;
1114 int i = 0, j;
1115 rtx result;
1116- int sign = up ? 1 : -1;
1117- rtx mem, addr;
1118
1119 /* XScale has load-store double instructions, but they have stricter
1120 alignment requirements than load-store multiple, so we cannot
1121@@ -10139,18 +10121,10 @@
1122 start_sequence ();
1123
1124 for (i = 0; i < count; i++)
1125- {
1126- addr = plus_constant (from, i * 4 * sign);
1127- mem = adjust_automodify_address (basemem, SImode, addr, offset);
1128- emit_move_insn (gen_rtx_REG (SImode, base_regno + i), mem);
1129- offset += 4 * sign;
1130- }
1131+ emit_move_insn (gen_rtx_REG (SImode, regs[i]), mems[i]);
1132
1133- if (write_back)
1134- {
1135- emit_move_insn (from, plus_constant (from, count * 4 * sign));
1136- *offsetp = offset;
1137- }
1138+ if (wback_offset != 0)
1139+ emit_move_insn (basereg, plus_constant (basereg, wback_offset));
1140
1141 seq = get_insns ();
1142 end_sequence ();
1143@@ -10159,41 +10133,40 @@
1144 }
1145
1146 result = gen_rtx_PARALLEL (VOIDmode,
1147- rtvec_alloc (count + (write_back ? 1 : 0)));
1148- if (write_back)
1149+ rtvec_alloc (count + (wback_offset != 0 ? 1 : 0)));
1150+ if (wback_offset != 0)
1151 {
1152 XVECEXP (result, 0, 0)
1153- = gen_rtx_SET (VOIDmode, from, plus_constant (from, count * 4 * sign));
1154+ = gen_rtx_SET (VOIDmode, basereg,
1155+ plus_constant (basereg, wback_offset));
1156 i = 1;
1157 count++;
1158 }
1159
1160 for (j = 0; i < count; i++, j++)
1161- {
1162- addr = plus_constant (from, j * 4 * sign);
1163- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1164- XVECEXP (result, 0, i)
1165- = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, base_regno + j), mem);
1166- offset += 4 * sign;
1167- }
1168-
1169- if (write_back)
1170- *offsetp = offset;
1171+ XVECEXP (result, 0, i)
1172+ = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, regs[j]), mems[j]);
1173
1174 return result;
1175 }
1176
1177-rtx
1178-arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
1179- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1180+/* Generate a store-multiple instruction. COUNT is the number of stores in
1181+ the instruction; REGS and MEMS are arrays containing the operands.
1182+ BASEREG is the base register to be used in addressing the memory operands.
1183+ WBACK_OFFSET is nonzero if the instruction should update the base
1184+ register. */
1185+
1186+static rtx
1187+arm_gen_store_multiple_1 (int count, int *regs, rtx *mems, rtx basereg,
1188+ HOST_WIDE_INT wback_offset)
1189 {
1190- HOST_WIDE_INT offset = *offsetp;
1191 int i = 0, j;
1192 rtx result;
1193- int sign = up ? 1 : -1;
1194- rtx mem, addr;
1195-
1196- /* See arm_gen_load_multiple for discussion of
1197+
1198+ if (GET_CODE (basereg) == PLUS)
1199+ basereg = XEXP (basereg, 0);
1200+
1201+ /* See arm_gen_load_multiple_1 for discussion of
1202 the pros/cons of ldm/stm usage for XScale. */
1203 if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size))
1204 {
1205@@ -10202,18 +10175,10 @@
1206 start_sequence ();
1207
1208 for (i = 0; i < count; i++)
1209- {
1210- addr = plus_constant (to, i * 4 * sign);
1211- mem = adjust_automodify_address (basemem, SImode, addr, offset);
1212- emit_move_insn (mem, gen_rtx_REG (SImode, base_regno + i));
1213- offset += 4 * sign;
1214- }
1215+ emit_move_insn (mems[i], gen_rtx_REG (SImode, regs[i]));
1216
1217- if (write_back)
1218- {
1219- emit_move_insn (to, plus_constant (to, count * 4 * sign));
1220- *offsetp = offset;
1221- }
1222+ if (wback_offset != 0)
1223+ emit_move_insn (basereg, plus_constant (basereg, wback_offset));
1224
1225 seq = get_insns ();
1226 end_sequence ();
1227@@ -10222,29 +10187,319 @@
1228 }
1229
1230 result = gen_rtx_PARALLEL (VOIDmode,
1231- rtvec_alloc (count + (write_back ? 1 : 0)));
1232- if (write_back)
1233+ rtvec_alloc (count + (wback_offset != 0 ? 1 : 0)));
1234+ if (wback_offset != 0)
1235 {
1236 XVECEXP (result, 0, 0)
1237- = gen_rtx_SET (VOIDmode, to,
1238- plus_constant (to, count * 4 * sign));
1239+ = gen_rtx_SET (VOIDmode, basereg,
1240+ plus_constant (basereg, wback_offset));
1241 i = 1;
1242 count++;
1243 }
1244
1245 for (j = 0; i < count; i++, j++)
1246+ XVECEXP (result, 0, i)
1247+ = gen_rtx_SET (VOIDmode, mems[j], gen_rtx_REG (SImode, regs[j]));
1248+
1249+ return result;
1250+}
1251+
1252+/* Generate either a load-multiple or a store-multiple instruction. This
1253+ function can be used in situations where we can start with a single MEM
1254+ rtx and adjust its address upwards.
1255+ COUNT is the number of operations in the instruction, not counting a
1256+ possible update of the base register. REGS is an array containing the
1257+ register operands.
1258+ BASEREG is the base register to be used in addressing the memory operands,
1259+ which are constructed from BASEMEM.
1260+ WRITE_BACK specifies whether the generated instruction should include an
1261+ update of the base register.
1262+ OFFSETP is used to pass an offset to and from this function; this offset
1263+ is not used when constructing the address (instead BASEMEM should have an
1264+ appropriate offset in its address), it is used only for setting
1265+ MEM_OFFSET. It is updated only if WRITE_BACK is true.*/
1266+
1267+static rtx
1268+arm_gen_multiple_op (bool is_load, int *regs, int count, rtx basereg,
1269+ bool write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1270+{
1271+ rtx mems[MAX_LDM_STM_OPS];
1272+ HOST_WIDE_INT offset = *offsetp;
1273+ int i;
1274+
1275+ gcc_assert (count <= MAX_LDM_STM_OPS);
1276+
1277+ if (GET_CODE (basereg) == PLUS)
1278+ basereg = XEXP (basereg, 0);
1279+
1280+ for (i = 0; i < count; i++)
1281 {
1282- addr = plus_constant (to, j * 4 * sign);
1283- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1284- XVECEXP (result, 0, i)
1285- = gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (SImode, base_regno + j));
1286- offset += 4 * sign;
1287+ rtx addr = plus_constant (basereg, i * 4);
1288+ mems[i] = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1289+ offset += 4;
1290 }
1291
1292 if (write_back)
1293 *offsetp = offset;
1294
1295- return result;
1296+ if (is_load)
1297+ return arm_gen_load_multiple_1 (count, regs, mems, basereg,
1298+ write_back ? 4 * count : 0);
1299+ else
1300+ return arm_gen_store_multiple_1 (count, regs, mems, basereg,
1301+ write_back ? 4 * count : 0);
1302+}
1303+
1304+rtx
1305+arm_gen_load_multiple (int *regs, int count, rtx basereg, int write_back,
1306+ rtx basemem, HOST_WIDE_INT *offsetp)
1307+{
1308+ return arm_gen_multiple_op (TRUE, regs, count, basereg, write_back, basemem,
1309+ offsetp);
1310+}
1311+
1312+rtx
1313+arm_gen_store_multiple (int *regs, int count, rtx basereg, int write_back,
1314+ rtx basemem, HOST_WIDE_INT *offsetp)
1315+{
1316+ return arm_gen_multiple_op (FALSE, regs, count, basereg, write_back, basemem,
1317+ offsetp);
1318+}
1319+
1320+/* Called from a peephole2 expander to turn a sequence of loads into an
1321+ LDM instruction. OPERANDS are the operands found by the peephole matcher;
1322+ NOPS indicates how many separate loads we are trying to combine. SORT_REGS
1323+ is true if we can reorder the registers because they are used commutatively
1324+ subsequently.
1325+ Returns true iff we could generate a new instruction. */
1326+
1327+bool
1328+gen_ldm_seq (rtx *operands, int nops, bool sort_regs)
1329+{
1330+ int regs[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1331+ rtx mems[MAX_LDM_STM_OPS];
1332+ int i, j, base_reg;
1333+ rtx base_reg_rtx;
1334+ HOST_WIDE_INT offset;
1335+ int write_back = FALSE;
1336+ int ldm_case;
1337+ rtx addr;
1338+
1339+ ldm_case = load_multiple_sequence (operands, nops, regs, mem_order,
1340+ &base_reg, &offset, !sort_regs);
1341+
1342+ if (ldm_case == 0)
1343+ return false;
1344+
1345+ if (sort_regs)
1346+ for (i = 0; i < nops - 1; i++)
1347+ for (j = i + 1; j < nops; j++)
1348+ if (regs[i] > regs[j])
1349+ {
1350+ int t = regs[i];
1351+ regs[i] = regs[j];
1352+ regs[j] = t;
1353+ }
1354+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1355+
1356+ if (TARGET_THUMB1)
1357+ {
1358+ gcc_assert (peep2_reg_dead_p (nops, base_reg_rtx));
1359+ gcc_assert (ldm_case == 1 || ldm_case == 5);
1360+ write_back = TRUE;
1361+ }
1362+
1363+ if (ldm_case == 5)
1364+ {
1365+ rtx newbase = TARGET_THUMB1 ? base_reg_rtx : gen_rtx_REG (SImode, regs[0]);
1366+ emit_insn (gen_addsi3 (newbase, base_reg_rtx, GEN_INT (offset)));
1367+ offset = 0;
1368+ if (!TARGET_THUMB1)
1369+ {
1370+ base_reg = regs[0];
1371+ base_reg_rtx = newbase;
1372+ }
1373+ }
1374+
1375+ for (i = 0; i < nops; i++)
1376+ {
1377+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1378+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1379+ SImode, addr, 0);
1380+ }
1381+ emit_insn (arm_gen_load_multiple_1 (nops, regs, mems, base_reg_rtx,
1382+ write_back ? offset + i * 4 : 0));
1383+ return true;
1384+}
1385+
1386+/* Called from a peephole2 expander to turn a sequence of stores into an
1387+ STM instruction. OPERANDS are the operands found by the peephole matcher;
1388+ NOPS indicates how many separate stores we are trying to combine.
1389+ Returns true iff we could generate a new instruction. */
1390+
1391+bool
1392+gen_stm_seq (rtx *operands, int nops)
1393+{
1394+ int i;
1395+ int regs[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1396+ rtx mems[MAX_LDM_STM_OPS];
1397+ int base_reg;
1398+ rtx base_reg_rtx;
1399+ HOST_WIDE_INT offset;
1400+ int write_back = FALSE;
1401+ int stm_case;
1402+ rtx addr;
1403+ bool base_reg_dies;
1404+
1405+ stm_case = store_multiple_sequence (operands, nops, nops, regs, NULL,
1406+ mem_order, &base_reg, &offset, true);
1407+
1408+ if (stm_case == 0)
1409+ return false;
1410+
1411+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1412+
1413+ base_reg_dies = peep2_reg_dead_p (nops, base_reg_rtx);
1414+ if (TARGET_THUMB1)
1415+ {
1416+ gcc_assert (base_reg_dies);
1417+ write_back = TRUE;
1418+ }
1419+
1420+ if (stm_case == 5)
1421+ {
1422+ gcc_assert (base_reg_dies);
1423+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, GEN_INT (offset)));
1424+ offset = 0;
1425+ }
1426+
1427+ addr = plus_constant (base_reg_rtx, offset);
1428+
1429+ for (i = 0; i < nops; i++)
1430+ {
1431+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1432+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1433+ SImode, addr, 0);
1434+ }
1435+ emit_insn (arm_gen_store_multiple_1 (nops, regs, mems, base_reg_rtx,
1436+ write_back ? offset + i * 4 : 0));
1437+ return true;
1438+}
1439+
1440+/* Called from a peephole2 expander to turn a sequence of stores that are
1441+ preceded by constant loads into an STM instruction. OPERANDS are the
1442+ operands found by the peephole matcher; NOPS indicates how many
1443+ separate stores we are trying to combine; there are 2 * NOPS
1444+ instructions in the peephole.
1445+ Returns true iff we could generate a new instruction. */
1446+
1447+bool
1448+gen_const_stm_seq (rtx *operands, int nops)
1449+{
1450+ int regs[MAX_LDM_STM_OPS], sorted_regs[MAX_LDM_STM_OPS];
1451+ int reg_order[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1452+ rtx reg_rtxs[MAX_LDM_STM_OPS], orig_reg_rtxs[MAX_LDM_STM_OPS];
1453+ rtx mems[MAX_LDM_STM_OPS];
1454+ int base_reg;
1455+ rtx base_reg_rtx;
1456+ HOST_WIDE_INT offset;
1457+ int write_back = FALSE;
1458+ int stm_case;
1459+ rtx addr;
1460+ bool base_reg_dies;
1461+ int i, j;
1462+ HARD_REG_SET allocated;
1463+
1464+ stm_case = store_multiple_sequence (operands, nops, 2 * nops, regs, reg_rtxs,
1465+ mem_order, &base_reg, &offset, false);
1466+
1467+ if (stm_case == 0)
1468+ return false;
1469+
1470+ memcpy (orig_reg_rtxs, reg_rtxs, sizeof orig_reg_rtxs);
1471+
1472+ /* If the same register is used more than once, try to find a free
1473+ register. */
1474+ CLEAR_HARD_REG_SET (allocated);
1475+ for (i = 0; i < nops; i++)
1476+ {
1477+ for (j = i + 1; j < nops; j++)
1478+ if (regs[i] == regs[j])
1479+ {
1480+ rtx t = peep2_find_free_register (0, nops * 2,
1481+ TARGET_THUMB1 ? "l" : "r",
1482+ SImode, &allocated);
1483+ if (t == NULL_RTX)
1484+ return false;
1485+ reg_rtxs[i] = t;
1486+ regs[i] = REGNO (t);
1487+ }
1488+ }
1489+
1490+ /* Compute an ordering that maps the register numbers to an ascending
1491+ sequence. */
1492+ reg_order[0] = 0;
1493+ for (i = 0; i < nops; i++)
1494+ if (regs[i] < regs[reg_order[0]])
1495+ reg_order[0] = i;
1496+
1497+ for (i = 1; i < nops; i++)
1498+ {
1499+ int this_order = reg_order[i - 1];
1500+ for (j = 0; j < nops; j++)
1501+ if (regs[j] > regs[reg_order[i - 1]]
1502+ && (this_order == reg_order[i - 1]
1503+ || regs[j] < regs[this_order]))
1504+ this_order = j;
1505+ reg_order[i] = this_order;
1506+ }
1507+
1508+ /* Ensure that registers that must be live after the instruction end
1509+ up with the correct value. */
1510+ for (i = 0; i < nops; i++)
1511+ {
1512+ int this_order = reg_order[i];
1513+ if ((this_order != mem_order[i]
1514+ || orig_reg_rtxs[this_order] != reg_rtxs[this_order])
1515+ && !peep2_reg_dead_p (nops * 2, orig_reg_rtxs[this_order]))
1516+ return false;
1517+ }
1518+
1519+ /* Load the constants. */
1520+ for (i = 0; i < nops; i++)
1521+ {
1522+ rtx op = operands[2 * nops + mem_order[i]];
1523+ sorted_regs[i] = regs[reg_order[i]];
1524+ emit_move_insn (reg_rtxs[reg_order[i]], op);
1525+ }
1526+
1527+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1528+
1529+ base_reg_dies = peep2_reg_dead_p (nops * 2, base_reg_rtx);
1530+ if (TARGET_THUMB1)
1531+ {
1532+ gcc_assert (base_reg_dies);
1533+ write_back = TRUE;
1534+ }
1535+
1536+ if (stm_case == 5)
1537+ {
1538+ gcc_assert (base_reg_dies);
1539+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, GEN_INT (offset)));
1540+ offset = 0;
1541+ }
1542+
1543+ addr = plus_constant (base_reg_rtx, offset);
1544+
1545+ for (i = 0; i < nops; i++)
1546+ {
1547+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1548+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1549+ SImode, addr, 0);
1550+ }
1551+ emit_insn (arm_gen_store_multiple_1 (nops, sorted_regs, mems, base_reg_rtx,
1552+ write_back ? offset + i * 4 : 0));
1553+ return true;
1554 }
1555
1556 int
1557@@ -10280,20 +10535,21 @@
1558 for (i = 0; in_words_to_go >= 2; i+=4)
1559 {
1560 if (in_words_to_go > 4)
1561- emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
1562- srcbase, &srcoffset));
1563+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, src,
1564+ TRUE, srcbase, &srcoffset));
1565 else
1566- emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
1567- FALSE, srcbase, &srcoffset));
1568+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, in_words_to_go,
1569+ src, FALSE, srcbase,
1570+ &srcoffset));
1571
1572 if (out_words_to_go)
1573 {
1574 if (out_words_to_go > 4)
1575- emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
1576- dstbase, &dstoffset));
1577+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, dst,
1578+ TRUE, dstbase, &dstoffset));
1579 else if (out_words_to_go != 1)
1580- emit_insn (arm_gen_store_multiple (0, out_words_to_go,
1581- dst, TRUE,
1582+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence,
1583+ out_words_to_go, dst,
1584 (last_bytes == 0
1585 ? FALSE : TRUE),
1586 dstbase, &dstoffset));
1587
1588=== modified file 'gcc/config/arm/arm.h'
1589--- old/gcc/config/arm/arm.h 2011-01-05 12:12:18 +0000
1590+++ new/gcc/config/arm/arm.h 2011-01-05 18:20:37 +0000
1591@@ -1143,6 +1143,9 @@
1592 ((MODE) == TImode || (MODE) == EImode || (MODE) == OImode \
1593 || (MODE) == CImode || (MODE) == XImode)
1594
1595+/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
1596+extern int arm_regs_in_sequence[];
1597+
1598 /* The order in which register should be allocated. It is good to use ip
1599 since no saving is required (though calls clobber it) and it never contains
1600 function parameters. It is quite good to use lr since other calls may
1601@@ -2823,4 +2826,8 @@
1602 #define NEED_INDICATE_EXEC_STACK 0
1603 #endif
1604
1605+/* The maximum number of parallel loads or stores we support in an ldm/stm
1606+ instruction. */
1607+#define MAX_LDM_STM_OPS 4
1608+
1609 #endif /* ! GCC_ARM_H */
1610
1611=== modified file 'gcc/config/arm/arm.md'
1612--- old/gcc/config/arm/arm.md 2011-01-05 12:12:18 +0000
1613+++ new/gcc/config/arm/arm.md 2011-01-05 18:20:37 +0000
1614@@ -6282,7 +6282,7 @@
1615
1616 ;; load- and store-multiple insns
1617 ;; The arm can load/store any set of registers, provided that they are in
1618-;; ascending order; but that is beyond GCC so stick with what it knows.
1619+;; ascending order, but these expanders assume a contiguous set.
1620
1621 (define_expand "load_multiple"
1622 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
1623@@ -6303,126 +6303,12 @@
1624 FAIL;
1625
1626 operands[3]
1627- = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
1628+ = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
1629+ INTVAL (operands[2]),
1630 force_reg (SImode, XEXP (operands[1], 0)),
1631- TRUE, FALSE, operands[1], &offset);
1632+ FALSE, operands[1], &offset);
1633 })
1634
1635-;; Load multiple with write-back
1636-
1637-(define_insn "*ldmsi_postinc4"
1638- [(match_parallel 0 "load_multiple_operation"
1639- [(set (match_operand:SI 1 "s_register_operand" "=r")
1640- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1641- (const_int 16)))
1642- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1643- (mem:SI (match_dup 2)))
1644- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1645- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1646- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1647- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
1648- (set (match_operand:SI 6 "arm_hard_register_operand" "")
1649- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
1650- "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
1651- "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
1652- [(set_attr "type" "load4")
1653- (set_attr "predicable" "yes")]
1654-)
1655-
1656-(define_insn "*ldmsi_postinc4_thumb1"
1657- [(match_parallel 0 "load_multiple_operation"
1658- [(set (match_operand:SI 1 "s_register_operand" "=l")
1659- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1660- (const_int 16)))
1661- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1662- (mem:SI (match_dup 2)))
1663- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1664- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1665- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1666- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
1667- (set (match_operand:SI 6 "arm_hard_register_operand" "")
1668- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
1669- "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
1670- "ldmia\\t%1!, {%3, %4, %5, %6}"
1671- [(set_attr "type" "load4")]
1672-)
1673-
1674-(define_insn "*ldmsi_postinc3"
1675- [(match_parallel 0 "load_multiple_operation"
1676- [(set (match_operand:SI 1 "s_register_operand" "=r")
1677- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1678- (const_int 12)))
1679- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1680- (mem:SI (match_dup 2)))
1681- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1682- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1683- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1684- (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
1685- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1686- "ldm%(ia%)\\t%1!, {%3, %4, %5}"
1687- [(set_attr "type" "load3")
1688- (set_attr "predicable" "yes")]
1689-)
1690-
1691-(define_insn "*ldmsi_postinc2"
1692- [(match_parallel 0 "load_multiple_operation"
1693- [(set (match_operand:SI 1 "s_register_operand" "=r")
1694- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1695- (const_int 8)))
1696- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1697- (mem:SI (match_dup 2)))
1698- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1699- (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
1700- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1701- "ldm%(ia%)\\t%1!, {%3, %4}"
1702- [(set_attr "type" "load2")
1703- (set_attr "predicable" "yes")]
1704-)
1705-
1706-;; Ordinary load multiple
1707-
1708-(define_insn "*ldmsi4"
1709- [(match_parallel 0 "load_multiple_operation"
1710- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1711- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1712- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1713- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
1714- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1715- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
1716- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1717- (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
1718- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1719- "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
1720- [(set_attr "type" "load4")
1721- (set_attr "predicable" "yes")]
1722-)
1723-
1724-(define_insn "*ldmsi3"
1725- [(match_parallel 0 "load_multiple_operation"
1726- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1727- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1728- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1729- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
1730- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1731- (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
1732- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1733- "ldm%(ia%)\\t%1, {%2, %3, %4}"
1734- [(set_attr "type" "load3")
1735- (set_attr "predicable" "yes")]
1736-)
1737-
1738-(define_insn "*ldmsi2"
1739- [(match_parallel 0 "load_multiple_operation"
1740- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1741- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1742- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1743- (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
1744- "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
1745- "ldm%(ia%)\\t%1, {%2, %3}"
1746- [(set_attr "type" "load2")
1747- (set_attr "predicable" "yes")]
1748-)
1749-
1750 (define_expand "store_multiple"
1751 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
1752 (match_operand:SI 1 "" ""))
1753@@ -6442,125 +6328,12 @@
1754 FAIL;
1755
1756 operands[3]
1757- = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
1758+ = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
1759+ INTVAL (operands[2]),
1760 force_reg (SImode, XEXP (operands[0], 0)),
1761- TRUE, FALSE, operands[0], &offset);
1762+ FALSE, operands[0], &offset);
1763 })
1764
1765-;; Store multiple with write-back
1766-
1767-(define_insn "*stmsi_postinc4"
1768- [(match_parallel 0 "store_multiple_operation"
1769- [(set (match_operand:SI 1 "s_register_operand" "=r")
1770- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1771- (const_int 16)))
1772- (set (mem:SI (match_dup 2))
1773- (match_operand:SI 3 "arm_hard_register_operand" ""))
1774- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1775- (match_operand:SI 4 "arm_hard_register_operand" ""))
1776- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1777- (match_operand:SI 5 "arm_hard_register_operand" ""))
1778- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
1779- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
1780- "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
1781- "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
1782- [(set_attr "predicable" "yes")
1783- (set_attr "type" "store4")]
1784-)
1785-
1786-(define_insn "*stmsi_postinc4_thumb1"
1787- [(match_parallel 0 "store_multiple_operation"
1788- [(set (match_operand:SI 1 "s_register_operand" "=l")
1789- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1790- (const_int 16)))
1791- (set (mem:SI (match_dup 2))
1792- (match_operand:SI 3 "arm_hard_register_operand" ""))
1793- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1794- (match_operand:SI 4 "arm_hard_register_operand" ""))
1795- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1796- (match_operand:SI 5 "arm_hard_register_operand" ""))
1797- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
1798- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
1799- "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
1800- "stmia\\t%1!, {%3, %4, %5, %6}"
1801- [(set_attr "type" "store4")]
1802-)
1803-
1804-(define_insn "*stmsi_postinc3"
1805- [(match_parallel 0 "store_multiple_operation"
1806- [(set (match_operand:SI 1 "s_register_operand" "=r")
1807- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1808- (const_int 12)))
1809- (set (mem:SI (match_dup 2))
1810- (match_operand:SI 3 "arm_hard_register_operand" ""))
1811- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1812- (match_operand:SI 4 "arm_hard_register_operand" ""))
1813- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1814- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
1815- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1816- "stm%(ia%)\\t%1!, {%3, %4, %5}"
1817- [(set_attr "predicable" "yes")
1818- (set_attr "type" "store3")]
1819-)
1820-
1821-(define_insn "*stmsi_postinc2"
1822- [(match_parallel 0 "store_multiple_operation"
1823- [(set (match_operand:SI 1 "s_register_operand" "=r")
1824- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1825- (const_int 8)))
1826- (set (mem:SI (match_dup 2))
1827- (match_operand:SI 3 "arm_hard_register_operand" ""))
1828- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1829- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
1830- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1831- "stm%(ia%)\\t%1!, {%3, %4}"
1832- [(set_attr "predicable" "yes")
1833- (set_attr "type" "store2")]
1834-)
1835-
1836-;; Ordinary store multiple
1837-
1838-(define_insn "*stmsi4"
1839- [(match_parallel 0 "store_multiple_operation"
1840- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1841- (match_operand:SI 2 "arm_hard_register_operand" ""))
1842- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1843- (match_operand:SI 3 "arm_hard_register_operand" ""))
1844- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
1845- (match_operand:SI 4 "arm_hard_register_operand" ""))
1846- (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
1847- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
1848- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1849- "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
1850- [(set_attr "predicable" "yes")
1851- (set_attr "type" "store4")]
1852-)
1853-
1854-(define_insn "*stmsi3"
1855- [(match_parallel 0 "store_multiple_operation"
1856- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1857- (match_operand:SI 2 "arm_hard_register_operand" ""))
1858- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1859- (match_operand:SI 3 "arm_hard_register_operand" ""))
1860- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
1861- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
1862- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1863- "stm%(ia%)\\t%1, {%2, %3, %4}"
1864- [(set_attr "predicable" "yes")
1865- (set_attr "type" "store3")]
1866-)
1867-
1868-(define_insn "*stmsi2"
1869- [(match_parallel 0 "store_multiple_operation"
1870- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1871- (match_operand:SI 2 "arm_hard_register_operand" ""))
1872- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1873- (match_operand:SI 3 "arm_hard_register_operand" ""))])]
1874- "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
1875- "stm%(ia%)\\t%1, {%2, %3}"
1876- [(set_attr "predicable" "yes")
1877- (set_attr "type" "store2")]
1878-)
1879
1880 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
1881 ;; We could let this apply for blocks of less than this, but it clobbers so
1882@@ -9031,8 +8804,8 @@
1883 if (REGNO (reg) == R0_REGNUM)
1884 {
1885 /* On thumb we have to use a write-back instruction. */
1886- emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
1887- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1888+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
1889+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1890 size = TARGET_ARM ? 16 : 0;
1891 }
1892 else
1893@@ -9078,8 +8851,8 @@
1894 if (REGNO (reg) == R0_REGNUM)
1895 {
1896 /* On thumb we have to use a write-back instruction. */
1897- emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
1898- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1899+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
1900+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1901 size = TARGET_ARM ? 16 : 0;
1902 }
1903 else
1904@@ -10672,87 +10445,6 @@
1905 ""
1906 )
1907
1908-; Peepholes to spot possible load- and store-multiples, if the ordering is
1909-; reversed, check that the memory references aren't volatile.
1910-
1911-(define_peephole
1912- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1913- (match_operand:SI 4 "memory_operand" "m"))
1914- (set (match_operand:SI 1 "s_register_operand" "=rk")
1915- (match_operand:SI 5 "memory_operand" "m"))
1916- (set (match_operand:SI 2 "s_register_operand" "=rk")
1917- (match_operand:SI 6 "memory_operand" "m"))
1918- (set (match_operand:SI 3 "s_register_operand" "=rk")
1919- (match_operand:SI 7 "memory_operand" "m"))]
1920- "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
1921- "*
1922- return emit_ldm_seq (operands, 4);
1923- "
1924-)
1925-
1926-(define_peephole
1927- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1928- (match_operand:SI 3 "memory_operand" "m"))
1929- (set (match_operand:SI 1 "s_register_operand" "=rk")
1930- (match_operand:SI 4 "memory_operand" "m"))
1931- (set (match_operand:SI 2 "s_register_operand" "=rk")
1932- (match_operand:SI 5 "memory_operand" "m"))]
1933- "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
1934- "*
1935- return emit_ldm_seq (operands, 3);
1936- "
1937-)
1938-
1939-(define_peephole
1940- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1941- (match_operand:SI 2 "memory_operand" "m"))
1942- (set (match_operand:SI 1 "s_register_operand" "=rk")
1943- (match_operand:SI 3 "memory_operand" "m"))]
1944- "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
1945- "*
1946- return emit_ldm_seq (operands, 2);
1947- "
1948-)
1949-
1950-(define_peephole
1951- [(set (match_operand:SI 4 "memory_operand" "=m")
1952- (match_operand:SI 0 "s_register_operand" "rk"))
1953- (set (match_operand:SI 5 "memory_operand" "=m")
1954- (match_operand:SI 1 "s_register_operand" "rk"))
1955- (set (match_operand:SI 6 "memory_operand" "=m")
1956- (match_operand:SI 2 "s_register_operand" "rk"))
1957- (set (match_operand:SI 7 "memory_operand" "=m")
1958- (match_operand:SI 3 "s_register_operand" "rk"))]
1959- "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
1960- "*
1961- return emit_stm_seq (operands, 4);
1962- "
1963-)
1964-
1965-(define_peephole
1966- [(set (match_operand:SI 3 "memory_operand" "=m")
1967- (match_operand:SI 0 "s_register_operand" "rk"))
1968- (set (match_operand:SI 4 "memory_operand" "=m")
1969- (match_operand:SI 1 "s_register_operand" "rk"))
1970- (set (match_operand:SI 5 "memory_operand" "=m")
1971- (match_operand:SI 2 "s_register_operand" "rk"))]
1972- "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
1973- "*
1974- return emit_stm_seq (operands, 3);
1975- "
1976-)
1977-
1978-(define_peephole
1979- [(set (match_operand:SI 2 "memory_operand" "=m")
1980- (match_operand:SI 0 "s_register_operand" "rk"))
1981- (set (match_operand:SI 3 "memory_operand" "=m")
1982- (match_operand:SI 1 "s_register_operand" "rk"))]
1983- "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
1984- "*
1985- return emit_stm_seq (operands, 2);
1986- "
1987-)
1988-
1989 (define_split
1990 [(set (match_operand:SI 0 "s_register_operand" "")
1991 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
1992@@ -11559,6 +11251,8 @@
1993 "
1994 )
1995
1996+;; Load the load/store multiple patterns
1997+(include "ldmstm.md")
1998 ;; Load the FPA co-processor patterns
1999 (include "fpa.md")
2000 ;; Load the Maverick co-processor patterns
2001
2002=== added file 'gcc/config/arm/ldmstm.md'
2003--- old/gcc/config/arm/ldmstm.md 1970-01-01 00:00:00 +0000
2004+++ new/gcc/config/arm/ldmstm.md 2010-11-16 13:08:47 +0000
2005@@ -0,0 +1,1191 @@
2006+/* ARM ldm/stm instruction patterns. This file was automatically generated
2007+ using arm-ldmstm.ml. Please do not edit manually.
2008+
2009+ Copyright (C) 2010 Free Software Foundation, Inc.
2010+ Contributed by CodeSourcery.
2011+
2012+ This file is part of GCC.
2013+
2014+ GCC is free software; you can redistribute it and/or modify it
2015+ under the terms of the GNU General Public License as published
2016+ by the Free Software Foundation; either version 3, or (at your
2017+ option) any later version.
2018+
2019+ GCC is distributed in the hope that it will be useful, but WITHOUT
2020+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
2021+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
2022+ License for more details.
2023+
2024+ You should have received a copy of the GNU General Public License and
2025+ a copy of the GCC Runtime Library Exception along with this program;
2026+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2027+ <http://www.gnu.org/licenses/>. */
2028+
2029+(define_insn "*ldm4_ia"
2030+ [(match_parallel 0 "load_multiple_operation"
2031+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2032+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2033+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2034+ (mem:SI (plus:SI (match_dup 1)
2035+ (const_int 4))))
2036+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2037+ (mem:SI (plus:SI (match_dup 1)
2038+ (const_int 8))))
2039+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2040+ (mem:SI (plus:SI (match_dup 1)
2041+ (const_int 12))))])]
2042+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2043+ "ldm%(ia%)\t%1, {%2, %3, %4, %5}"
2044+ [(set_attr "type" "load4")
2045+ (set_attr "predicable" "yes")])
2046+
2047+(define_insn "*thumb_ldm4_ia"
2048+ [(match_parallel 0 "load_multiple_operation"
2049+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2050+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2051+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2052+ (mem:SI (plus:SI (match_dup 1)
2053+ (const_int 4))))
2054+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2055+ (mem:SI (plus:SI (match_dup 1)
2056+ (const_int 8))))
2057+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2058+ (mem:SI (plus:SI (match_dup 1)
2059+ (const_int 12))))])]
2060+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2061+ "ldm%(ia%)\t%1, {%2, %3, %4, %5}"
2062+ [(set_attr "type" "load4")])
2063+
2064+(define_insn "*ldm4_ia_update"
2065+ [(match_parallel 0 "load_multiple_operation"
2066+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2067+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2068+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2069+ (mem:SI (match_dup 2)))
2070+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2071+ (mem:SI (plus:SI (match_dup 2)
2072+ (const_int 4))))
2073+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2074+ (mem:SI (plus:SI (match_dup 2)
2075+ (const_int 8))))
2076+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2077+ (mem:SI (plus:SI (match_dup 2)
2078+ (const_int 12))))])]
2079+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2080+ "ldm%(ia%)\t%1!, {%3, %4, %5, %6}"
2081+ [(set_attr "type" "load4")
2082+ (set_attr "predicable" "yes")])
2083+
2084+(define_insn "*thumb_ldm4_ia_update"
2085+ [(match_parallel 0 "load_multiple_operation"
2086+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2087+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2088+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2089+ (mem:SI (match_dup 2)))
2090+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2091+ (mem:SI (plus:SI (match_dup 2)
2092+ (const_int 4))))
2093+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2094+ (mem:SI (plus:SI (match_dup 2)
2095+ (const_int 8))))
2096+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2097+ (mem:SI (plus:SI (match_dup 2)
2098+ (const_int 12))))])]
2099+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
2100+ "ldm%(ia%)\t%1!, {%3, %4, %5, %6}"
2101+ [(set_attr "type" "load4")])
2102+
2103+(define_insn "*stm4_ia"
2104+ [(match_parallel 0 "store_multiple_operation"
2105+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2106+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2107+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2108+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2109+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2110+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2111+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2112+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2113+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2114+ "stm%(ia%)\t%1, {%2, %3, %4, %5}"
2115+ [(set_attr "type" "store4")
2116+ (set_attr "predicable" "yes")])
2117+
2118+(define_insn "*stm4_ia_update"
2119+ [(match_parallel 0 "store_multiple_operation"
2120+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2121+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2122+ (set (mem:SI (match_dup 2))
2123+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2124+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2125+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2126+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2127+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2128+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2129+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2130+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2131+ "stm%(ia%)\t%1!, {%3, %4, %5, %6}"
2132+ [(set_attr "type" "store4")
2133+ (set_attr "predicable" "yes")])
2134+
2135+(define_insn "*thumb_stm4_ia_update"
2136+ [(match_parallel 0 "store_multiple_operation"
2137+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2138+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2139+ (set (mem:SI (match_dup 2))
2140+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2141+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2142+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2143+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2144+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2145+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2146+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2147+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
2148+ "stm%(ia%)\t%1!, {%3, %4, %5, %6}"
2149+ [(set_attr "type" "store4")])
2150+
2151+(define_insn "*ldm4_ib"
2152+ [(match_parallel 0 "load_multiple_operation"
2153+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2154+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2155+ (const_int 4))))
2156+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2157+ (mem:SI (plus:SI (match_dup 1)
2158+ (const_int 8))))
2159+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2160+ (mem:SI (plus:SI (match_dup 1)
2161+ (const_int 12))))
2162+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2163+ (mem:SI (plus:SI (match_dup 1)
2164+ (const_int 16))))])]
2165+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2166+ "ldm%(ib%)\t%1, {%2, %3, %4, %5}"
2167+ [(set_attr "type" "load4")
2168+ (set_attr "predicable" "yes")])
2169+
2170+(define_insn "*ldm4_ib_update"
2171+ [(match_parallel 0 "load_multiple_operation"
2172+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2173+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2174+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2175+ (mem:SI (plus:SI (match_dup 2)
2176+ (const_int 4))))
2177+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2178+ (mem:SI (plus:SI (match_dup 2)
2179+ (const_int 8))))
2180+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2181+ (mem:SI (plus:SI (match_dup 2)
2182+ (const_int 12))))
2183+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2184+ (mem:SI (plus:SI (match_dup 2)
2185+ (const_int 16))))])]
2186+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2187+ "ldm%(ib%)\t%1!, {%3, %4, %5, %6}"
2188+ [(set_attr "type" "load4")
2189+ (set_attr "predicable" "yes")])
2190+
2191+(define_insn "*stm4_ib"
2192+ [(match_parallel 0 "store_multiple_operation"
2193+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2194+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2195+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2196+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2197+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2198+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2199+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
2200+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2201+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2202+ "stm%(ib%)\t%1, {%2, %3, %4, %5}"
2203+ [(set_attr "type" "store4")
2204+ (set_attr "predicable" "yes")])
2205+
2206+(define_insn "*stm4_ib_update"
2207+ [(match_parallel 0 "store_multiple_operation"
2208+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2209+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2210+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2211+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2212+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2213+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2214+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2215+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2216+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16)))
2217+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2218+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2219+ "stm%(ib%)\t%1!, {%3, %4, %5, %6}"
2220+ [(set_attr "type" "store4")
2221+ (set_attr "predicable" "yes")])
2222+
2223+(define_insn "*ldm4_da"
2224+ [(match_parallel 0 "load_multiple_operation"
2225+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2226+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2227+ (const_int -12))))
2228+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2229+ (mem:SI (plus:SI (match_dup 1)
2230+ (const_int -8))))
2231+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2232+ (mem:SI (plus:SI (match_dup 1)
2233+ (const_int -4))))
2234+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2235+ (mem:SI (match_dup 1)))])]
2236+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2237+ "ldm%(da%)\t%1, {%2, %3, %4, %5}"
2238+ [(set_attr "type" "load4")
2239+ (set_attr "predicable" "yes")])
2240+
2241+(define_insn "*ldm4_da_update"
2242+ [(match_parallel 0 "load_multiple_operation"
2243+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2244+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2245+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2246+ (mem:SI (plus:SI (match_dup 2)
2247+ (const_int -12))))
2248+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2249+ (mem:SI (plus:SI (match_dup 2)
2250+ (const_int -8))))
2251+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2252+ (mem:SI (plus:SI (match_dup 2)
2253+ (const_int -4))))
2254+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2255+ (mem:SI (match_dup 2)))])]
2256+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2257+ "ldm%(da%)\t%1!, {%3, %4, %5, %6}"
2258+ [(set_attr "type" "load4")
2259+ (set_attr "predicable" "yes")])
2260+
2261+(define_insn "*stm4_da"
2262+ [(match_parallel 0 "store_multiple_operation"
2263+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -12)))
2264+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2265+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2266+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2267+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2268+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2269+ (set (mem:SI (match_dup 1))
2270+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2271+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2272+ "stm%(da%)\t%1, {%2, %3, %4, %5}"
2273+ [(set_attr "type" "store4")
2274+ (set_attr "predicable" "yes")])
2275+
2276+(define_insn "*stm4_da_update"
2277+ [(match_parallel 0 "store_multiple_operation"
2278+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2279+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2280+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2281+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2282+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2283+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2284+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2285+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2286+ (set (mem:SI (match_dup 2))
2287+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2288+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2289+ "stm%(da%)\t%1!, {%3, %4, %5, %6}"
2290+ [(set_attr "type" "store4")
2291+ (set_attr "predicable" "yes")])
2292+
2293+(define_insn "*ldm4_db"
2294+ [(match_parallel 0 "load_multiple_operation"
2295+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2296+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2297+ (const_int -16))))
2298+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2299+ (mem:SI (plus:SI (match_dup 1)
2300+ (const_int -12))))
2301+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2302+ (mem:SI (plus:SI (match_dup 1)
2303+ (const_int -8))))
2304+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2305+ (mem:SI (plus:SI (match_dup 1)
2306+ (const_int -4))))])]
2307+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2308+ "ldm%(db%)\t%1, {%2, %3, %4, %5}"
2309+ [(set_attr "type" "load4")
2310+ (set_attr "predicable" "yes")])
2311+
2312+(define_insn "*ldm4_db_update"
2313+ [(match_parallel 0 "load_multiple_operation"
2314+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2315+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2316+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2317+ (mem:SI (plus:SI (match_dup 2)
2318+ (const_int -16))))
2319+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2320+ (mem:SI (plus:SI (match_dup 2)
2321+ (const_int -12))))
2322+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2323+ (mem:SI (plus:SI (match_dup 2)
2324+ (const_int -8))))
2325+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2326+ (mem:SI (plus:SI (match_dup 2)
2327+ (const_int -4))))])]
2328+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2329+ "ldm%(db%)\t%1!, {%3, %4, %5, %6}"
2330+ [(set_attr "type" "load4")
2331+ (set_attr "predicable" "yes")])
2332+
2333+(define_insn "*stm4_db"
2334+ [(match_parallel 0 "store_multiple_operation"
2335+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -16)))
2336+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2337+ (set (mem:SI (plus:SI (match_dup 1) (const_int -12)))
2338+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2339+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2340+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2341+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2342+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2343+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2344+ "stm%(db%)\t%1, {%2, %3, %4, %5}"
2345+ [(set_attr "type" "store4")
2346+ (set_attr "predicable" "yes")])
2347+
2348+(define_insn "*stm4_db_update"
2349+ [(match_parallel 0 "store_multiple_operation"
2350+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2351+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2352+ (set (mem:SI (plus:SI (match_dup 2) (const_int -16)))
2353+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2354+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2355+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2356+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2357+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2358+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2359+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2360+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2361+ "stm%(db%)\t%1!, {%3, %4, %5, %6}"
2362+ [(set_attr "type" "store4")
2363+ (set_attr "predicable" "yes")])
2364+
2365+(define_peephole2
2366+ [(set (match_operand:SI 0 "s_register_operand" "")
2367+ (match_operand:SI 4 "memory_operand" ""))
2368+ (set (match_operand:SI 1 "s_register_operand" "")
2369+ (match_operand:SI 5 "memory_operand" ""))
2370+ (set (match_operand:SI 2 "s_register_operand" "")
2371+ (match_operand:SI 6 "memory_operand" ""))
2372+ (set (match_operand:SI 3 "s_register_operand" "")
2373+ (match_operand:SI 7 "memory_operand" ""))]
2374+ ""
2375+ [(const_int 0)]
2376+{
2377+ if (gen_ldm_seq (operands, 4, false))
2378+ DONE;
2379+ else
2380+ FAIL;
2381+})
2382+
2383+(define_peephole2
2384+ [(set (match_operand:SI 0 "s_register_operand" "")
2385+ (match_operand:SI 4 "memory_operand" ""))
2386+ (parallel
2387+ [(set (match_operand:SI 1 "s_register_operand" "")
2388+ (match_operand:SI 5 "memory_operand" ""))
2389+ (set (match_operand:SI 2 "s_register_operand" "")
2390+ (match_operand:SI 6 "memory_operand" ""))
2391+ (set (match_operand:SI 3 "s_register_operand" "")
2392+ (match_operand:SI 7 "memory_operand" ""))])]
2393+ ""
2394+ [(const_int 0)]
2395+{
2396+ if (gen_ldm_seq (operands, 4, false))
2397+ DONE;
2398+ else
2399+ FAIL;
2400+})
2401+
2402+(define_peephole2
2403+ [(set (match_operand:SI 0 "s_register_operand" "")
2404+ (match_operand:SI 8 "const_int_operand" ""))
2405+ (set (match_operand:SI 4 "memory_operand" "")
2406+ (match_dup 0))
2407+ (set (match_operand:SI 1 "s_register_operand" "")
2408+ (match_operand:SI 9 "const_int_operand" ""))
2409+ (set (match_operand:SI 5 "memory_operand" "")
2410+ (match_dup 1))
2411+ (set (match_operand:SI 2 "s_register_operand" "")
2412+ (match_operand:SI 10 "const_int_operand" ""))
2413+ (set (match_operand:SI 6 "memory_operand" "")
2414+ (match_dup 2))
2415+ (set (match_operand:SI 3 "s_register_operand" "")
2416+ (match_operand:SI 11 "const_int_operand" ""))
2417+ (set (match_operand:SI 7 "memory_operand" "")
2418+ (match_dup 3))]
2419+ ""
2420+ [(const_int 0)]
2421+{
2422+ if (gen_const_stm_seq (operands, 4))
2423+ DONE;
2424+ else
2425+ FAIL;
2426+})
2427+
2428+(define_peephole2
2429+ [(set (match_operand:SI 0 "s_register_operand" "")
2430+ (match_operand:SI 8 "const_int_operand" ""))
2431+ (set (match_operand:SI 1 "s_register_operand" "")
2432+ (match_operand:SI 9 "const_int_operand" ""))
2433+ (set (match_operand:SI 2 "s_register_operand" "")
2434+ (match_operand:SI 10 "const_int_operand" ""))
2435+ (set (match_operand:SI 3 "s_register_operand" "")
2436+ (match_operand:SI 11 "const_int_operand" ""))
2437+ (set (match_operand:SI 4 "memory_operand" "")
2438+ (match_dup 0))
2439+ (set (match_operand:SI 5 "memory_operand" "")
2440+ (match_dup 1))
2441+ (set (match_operand:SI 6 "memory_operand" "")
2442+ (match_dup 2))
2443+ (set (match_operand:SI 7 "memory_operand" "")
2444+ (match_dup 3))]
2445+ ""
2446+ [(const_int 0)]
2447+{
2448+ if (gen_const_stm_seq (operands, 4))
2449+ DONE;
2450+ else
2451+ FAIL;
2452+})
2453+
2454+(define_peephole2
2455+ [(set (match_operand:SI 4 "memory_operand" "")
2456+ (match_operand:SI 0 "s_register_operand" ""))
2457+ (set (match_operand:SI 5 "memory_operand" "")
2458+ (match_operand:SI 1 "s_register_operand" ""))
2459+ (set (match_operand:SI 6 "memory_operand" "")
2460+ (match_operand:SI 2 "s_register_operand" ""))
2461+ (set (match_operand:SI 7 "memory_operand" "")
2462+ (match_operand:SI 3 "s_register_operand" ""))]
2463+ ""
2464+ [(const_int 0)]
2465+{
2466+ if (gen_stm_seq (operands, 4))
2467+ DONE;
2468+ else
2469+ FAIL;
2470+})
2471+
2472+(define_insn "*ldm3_ia"
2473+ [(match_parallel 0 "load_multiple_operation"
2474+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2475+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2476+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2477+ (mem:SI (plus:SI (match_dup 1)
2478+ (const_int 4))))
2479+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2480+ (mem:SI (plus:SI (match_dup 1)
2481+ (const_int 8))))])]
2482+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2483+ "ldm%(ia%)\t%1, {%2, %3, %4}"
2484+ [(set_attr "type" "load3")
2485+ (set_attr "predicable" "yes")])
2486+
2487+(define_insn "*thumb_ldm3_ia"
2488+ [(match_parallel 0 "load_multiple_operation"
2489+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2490+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2491+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2492+ (mem:SI (plus:SI (match_dup 1)
2493+ (const_int 4))))
2494+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2495+ (mem:SI (plus:SI (match_dup 1)
2496+ (const_int 8))))])]
2497+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2498+ "ldm%(ia%)\t%1, {%2, %3, %4}"
2499+ [(set_attr "type" "load3")])
2500+
2501+(define_insn "*ldm3_ia_update"
2502+ [(match_parallel 0 "load_multiple_operation"
2503+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2504+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2505+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2506+ (mem:SI (match_dup 2)))
2507+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2508+ (mem:SI (plus:SI (match_dup 2)
2509+ (const_int 4))))
2510+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2511+ (mem:SI (plus:SI (match_dup 2)
2512+ (const_int 8))))])]
2513+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2514+ "ldm%(ia%)\t%1!, {%3, %4, %5}"
2515+ [(set_attr "type" "load3")
2516+ (set_attr "predicable" "yes")])
2517+
2518+(define_insn "*thumb_ldm3_ia_update"
2519+ [(match_parallel 0 "load_multiple_operation"
2520+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2521+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2522+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2523+ (mem:SI (match_dup 2)))
2524+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2525+ (mem:SI (plus:SI (match_dup 2)
2526+ (const_int 4))))
2527+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2528+ (mem:SI (plus:SI (match_dup 2)
2529+ (const_int 8))))])]
2530+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2531+ "ldm%(ia%)\t%1!, {%3, %4, %5}"
2532+ [(set_attr "type" "load3")])
2533+
2534+(define_insn "*stm3_ia"
2535+ [(match_parallel 0 "store_multiple_operation"
2536+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2537+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2538+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2539+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2540+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2541+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2542+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2543+ "stm%(ia%)\t%1, {%2, %3, %4}"
2544+ [(set_attr "type" "store3")
2545+ (set_attr "predicable" "yes")])
2546+
2547+(define_insn "*stm3_ia_update"
2548+ [(match_parallel 0 "store_multiple_operation"
2549+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2550+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2551+ (set (mem:SI (match_dup 2))
2552+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2553+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2554+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2555+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2556+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2557+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2558+ "stm%(ia%)\t%1!, {%3, %4, %5}"
2559+ [(set_attr "type" "store3")
2560+ (set_attr "predicable" "yes")])
2561+
2562+(define_insn "*thumb_stm3_ia_update"
2563+ [(match_parallel 0 "store_multiple_operation"
2564+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2565+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2566+ (set (mem:SI (match_dup 2))
2567+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2568+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2569+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2570+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2571+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2572+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2573+ "stm%(ia%)\t%1!, {%3, %4, %5}"
2574+ [(set_attr "type" "store3")])
2575+
2576+(define_insn "*ldm3_ib"
2577+ [(match_parallel 0 "load_multiple_operation"
2578+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2579+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2580+ (const_int 4))))
2581+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2582+ (mem:SI (plus:SI (match_dup 1)
2583+ (const_int 8))))
2584+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2585+ (mem:SI (plus:SI (match_dup 1)
2586+ (const_int 12))))])]
2587+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2588+ "ldm%(ib%)\t%1, {%2, %3, %4}"
2589+ [(set_attr "type" "load3")
2590+ (set_attr "predicable" "yes")])
2591+
2592+(define_insn "*ldm3_ib_update"
2593+ [(match_parallel 0 "load_multiple_operation"
2594+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2595+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2596+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2597+ (mem:SI (plus:SI (match_dup 2)
2598+ (const_int 4))))
2599+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2600+ (mem:SI (plus:SI (match_dup 2)
2601+ (const_int 8))))
2602+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2603+ (mem:SI (plus:SI (match_dup 2)
2604+ (const_int 12))))])]
2605+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2606+ "ldm%(ib%)\t%1!, {%3, %4, %5}"
2607+ [(set_attr "type" "load3")
2608+ (set_attr "predicable" "yes")])
2609+
2610+(define_insn "*stm3_ib"
2611+ [(match_parallel 0 "store_multiple_operation"
2612+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2613+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2614+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2615+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2616+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2617+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2618+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2619+ "stm%(ib%)\t%1, {%2, %3, %4}"
2620+ [(set_attr "type" "store3")
2621+ (set_attr "predicable" "yes")])
2622+
2623+(define_insn "*stm3_ib_update"
2624+ [(match_parallel 0 "store_multiple_operation"
2625+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2626+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2627+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2628+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2629+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2630+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2631+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2632+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2633+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2634+ "stm%(ib%)\t%1!, {%3, %4, %5}"
2635+ [(set_attr "type" "store3")
2636+ (set_attr "predicable" "yes")])
2637+
2638+(define_insn "*ldm3_da"
2639+ [(match_parallel 0 "load_multiple_operation"
2640+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2641+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2642+ (const_int -8))))
2643+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2644+ (mem:SI (plus:SI (match_dup 1)
2645+ (const_int -4))))
2646+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2647+ (mem:SI (match_dup 1)))])]
2648+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2649+ "ldm%(da%)\t%1, {%2, %3, %4}"
2650+ [(set_attr "type" "load3")
2651+ (set_attr "predicable" "yes")])
2652+
2653+(define_insn "*ldm3_da_update"
2654+ [(match_parallel 0 "load_multiple_operation"
2655+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2656+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2657+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2658+ (mem:SI (plus:SI (match_dup 2)
2659+ (const_int -8))))
2660+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2661+ (mem:SI (plus:SI (match_dup 2)
2662+ (const_int -4))))
2663+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2664+ (mem:SI (match_dup 2)))])]
2665+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2666+ "ldm%(da%)\t%1!, {%3, %4, %5}"
2667+ [(set_attr "type" "load3")
2668+ (set_attr "predicable" "yes")])
2669+
2670+(define_insn "*stm3_da"
2671+ [(match_parallel 0 "store_multiple_operation"
2672+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -8)))
2673+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2674+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2675+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2676+ (set (mem:SI (match_dup 1))
2677+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2678+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2679+ "stm%(da%)\t%1, {%2, %3, %4}"
2680+ [(set_attr "type" "store3")
2681+ (set_attr "predicable" "yes")])
2682+
2683+(define_insn "*stm3_da_update"
2684+ [(match_parallel 0 "store_multiple_operation"
2685+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2686+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2687+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2688+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2689+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2690+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2691+ (set (mem:SI (match_dup 2))
2692+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2693+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2694+ "stm%(da%)\t%1!, {%3, %4, %5}"
2695+ [(set_attr "type" "store3")
2696+ (set_attr "predicable" "yes")])
2697+
2698+(define_insn "*ldm3_db"
2699+ [(match_parallel 0 "load_multiple_operation"
2700+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2701+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2702+ (const_int -12))))
2703+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2704+ (mem:SI (plus:SI (match_dup 1)
2705+ (const_int -8))))
2706+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2707+ (mem:SI (plus:SI (match_dup 1)
2708+ (const_int -4))))])]
2709+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2710+ "ldm%(db%)\t%1, {%2, %3, %4}"
2711+ [(set_attr "type" "load3")
2712+ (set_attr "predicable" "yes")])
2713+
2714+(define_insn "*ldm3_db_update"
2715+ [(match_parallel 0 "load_multiple_operation"
2716+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2717+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2718+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2719+ (mem:SI (plus:SI (match_dup 2)
2720+ (const_int -12))))
2721+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2722+ (mem:SI (plus:SI (match_dup 2)
2723+ (const_int -8))))
2724+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2725+ (mem:SI (plus:SI (match_dup 2)
2726+ (const_int -4))))])]
2727+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2728+ "ldm%(db%)\t%1!, {%3, %4, %5}"
2729+ [(set_attr "type" "load3")
2730+ (set_attr "predicable" "yes")])
2731+
2732+(define_insn "*stm3_db"
2733+ [(match_parallel 0 "store_multiple_operation"
2734+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -12)))
2735+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2736+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2737+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2738+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2739+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2740+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2741+ "stm%(db%)\t%1, {%2, %3, %4}"
2742+ [(set_attr "type" "store3")
2743+ (set_attr "predicable" "yes")])
2744+
2745+(define_insn "*stm3_db_update"
2746+ [(match_parallel 0 "store_multiple_operation"
2747+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2748+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2749+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2750+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2751+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2752+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2753+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2754+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2755+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2756+ "stm%(db%)\t%1!, {%3, %4, %5}"
2757+ [(set_attr "type" "store3")
2758+ (set_attr "predicable" "yes")])
2759+
2760+(define_peephole2
2761+ [(set (match_operand:SI 0 "s_register_operand" "")
2762+ (match_operand:SI 3 "memory_operand" ""))
2763+ (set (match_operand:SI 1 "s_register_operand" "")
2764+ (match_operand:SI 4 "memory_operand" ""))
2765+ (set (match_operand:SI 2 "s_register_operand" "")
2766+ (match_operand:SI 5 "memory_operand" ""))]
2767+ ""
2768+ [(const_int 0)]
2769+{
2770+ if (gen_ldm_seq (operands, 3, false))
2771+ DONE;
2772+ else
2773+ FAIL;
2774+})
2775+
2776+(define_peephole2
2777+ [(set (match_operand:SI 0 "s_register_operand" "")
2778+ (match_operand:SI 3 "memory_operand" ""))
2779+ (parallel
2780+ [(set (match_operand:SI 1 "s_register_operand" "")
2781+ (match_operand:SI 4 "memory_operand" ""))
2782+ (set (match_operand:SI 2 "s_register_operand" "")
2783+ (match_operand:SI 5 "memory_operand" ""))])]
2784+ ""
2785+ [(const_int 0)]
2786+{
2787+ if (gen_ldm_seq (operands, 3, false))
2788+ DONE;
2789+ else
2790+ FAIL;
2791+})
2792+
2793+(define_peephole2
2794+ [(set (match_operand:SI 0 "s_register_operand" "")
2795+ (match_operand:SI 6 "const_int_operand" ""))
2796+ (set (match_operand:SI 3 "memory_operand" "")
2797+ (match_dup 0))
2798+ (set (match_operand:SI 1 "s_register_operand" "")
2799+ (match_operand:SI 7 "const_int_operand" ""))
2800+ (set (match_operand:SI 4 "memory_operand" "")
2801+ (match_dup 1))
2802+ (set (match_operand:SI 2 "s_register_operand" "")
2803+ (match_operand:SI 8 "const_int_operand" ""))
2804+ (set (match_operand:SI 5 "memory_operand" "")
2805+ (match_dup 2))]
2806+ ""
2807+ [(const_int 0)]
2808+{
2809+ if (gen_const_stm_seq (operands, 3))
2810+ DONE;
2811+ else
2812+ FAIL;
2813+})
2814+
2815+(define_peephole2
2816+ [(set (match_operand:SI 0 "s_register_operand" "")
2817+ (match_operand:SI 6 "const_int_operand" ""))
2818+ (set (match_operand:SI 1 "s_register_operand" "")
2819+ (match_operand:SI 7 "const_int_operand" ""))
2820+ (set (match_operand:SI 2 "s_register_operand" "")
2821+ (match_operand:SI 8 "const_int_operand" ""))
2822+ (set (match_operand:SI 3 "memory_operand" "")
2823+ (match_dup 0))
2824+ (set (match_operand:SI 4 "memory_operand" "")
2825+ (match_dup 1))
2826+ (set (match_operand:SI 5 "memory_operand" "")
2827+ (match_dup 2))]
2828+ ""
2829+ [(const_int 0)]
2830+{
2831+ if (gen_const_stm_seq (operands, 3))
2832+ DONE;
2833+ else
2834+ FAIL;
2835+})
2836+
2837+(define_peephole2
2838+ [(set (match_operand:SI 3 "memory_operand" "")
2839+ (match_operand:SI 0 "s_register_operand" ""))
2840+ (set (match_operand:SI 4 "memory_operand" "")
2841+ (match_operand:SI 1 "s_register_operand" ""))
2842+ (set (match_operand:SI 5 "memory_operand" "")
2843+ (match_operand:SI 2 "s_register_operand" ""))]
2844+ ""
2845+ [(const_int 0)]
2846+{
2847+ if (gen_stm_seq (operands, 3))
2848+ DONE;
2849+ else
2850+ FAIL;
2851+})
2852+
2853+(define_insn "*ldm2_ia"
2854+ [(match_parallel 0 "load_multiple_operation"
2855+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2856+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2857+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2858+ (mem:SI (plus:SI (match_dup 1)
2859+ (const_int 4))))])]
2860+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
2861+ "ldm%(ia%)\t%1, {%2, %3}"
2862+ [(set_attr "type" "load2")
2863+ (set_attr "predicable" "yes")])
2864+
2865+(define_insn "*thumb_ldm2_ia"
2866+ [(match_parallel 0 "load_multiple_operation"
2867+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2868+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2869+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2870+ (mem:SI (plus:SI (match_dup 1)
2871+ (const_int 4))))])]
2872+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 2"
2873+ "ldm%(ia%)\t%1, {%2, %3}"
2874+ [(set_attr "type" "load2")])
2875+
2876+(define_insn "*ldm2_ia_update"
2877+ [(match_parallel 0 "load_multiple_operation"
2878+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2879+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2880+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2881+ (mem:SI (match_dup 2)))
2882+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2883+ (mem:SI (plus:SI (match_dup 2)
2884+ (const_int 4))))])]
2885+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2886+ "ldm%(ia%)\t%1!, {%3, %4}"
2887+ [(set_attr "type" "load2")
2888+ (set_attr "predicable" "yes")])
2889+
2890+(define_insn "*thumb_ldm2_ia_update"
2891+ [(match_parallel 0 "load_multiple_operation"
2892+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2893+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2894+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2895+ (mem:SI (match_dup 2)))
2896+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2897+ (mem:SI (plus:SI (match_dup 2)
2898+ (const_int 4))))])]
2899+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2900+ "ldm%(ia%)\t%1!, {%3, %4}"
2901+ [(set_attr "type" "load2")])
2902+
2903+(define_insn "*stm2_ia"
2904+ [(match_parallel 0 "store_multiple_operation"
2905+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2906+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2907+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2908+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
2909+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
2910+ "stm%(ia%)\t%1, {%2, %3}"
2911+ [(set_attr "type" "store2")
2912+ (set_attr "predicable" "yes")])
2913+
2914+(define_insn "*stm2_ia_update"
2915+ [(match_parallel 0 "store_multiple_operation"
2916+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2917+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2918+ (set (mem:SI (match_dup 2))
2919+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2920+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2921+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2922+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2923+ "stm%(ia%)\t%1!, {%3, %4}"
2924+ [(set_attr "type" "store2")
2925+ (set_attr "predicable" "yes")])
2926+
2927+(define_insn "*thumb_stm2_ia_update"
2928+ [(match_parallel 0 "store_multiple_operation"
2929+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2930+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2931+ (set (mem:SI (match_dup 2))
2932+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2933+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2934+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2935+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2936+ "stm%(ia%)\t%1!, {%3, %4}"
2937+ [(set_attr "type" "store2")])
2938+
2939+(define_insn "*ldm2_ib"
2940+ [(match_parallel 0 "load_multiple_operation"
2941+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2942+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2943+ (const_int 4))))
2944+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2945+ (mem:SI (plus:SI (match_dup 1)
2946+ (const_int 8))))])]
2947+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2948+ "ldm%(ib%)\t%1, {%2, %3}"
2949+ [(set_attr "type" "load2")
2950+ (set_attr "predicable" "yes")])
2951+
2952+(define_insn "*ldm2_ib_update"
2953+ [(match_parallel 0 "load_multiple_operation"
2954+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2955+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2956+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2957+ (mem:SI (plus:SI (match_dup 2)
2958+ (const_int 4))))
2959+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2960+ (mem:SI (plus:SI (match_dup 2)
2961+ (const_int 8))))])]
2962+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2963+ "ldm%(ib%)\t%1!, {%3, %4}"
2964+ [(set_attr "type" "load2")
2965+ (set_attr "predicable" "yes")])
2966+
2967+(define_insn "*stm2_ib"
2968+ [(match_parallel 0 "store_multiple_operation"
2969+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2970+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2971+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2972+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
2973+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2974+ "stm%(ib%)\t%1, {%2, %3}"
2975+ [(set_attr "type" "store2")
2976+ (set_attr "predicable" "yes")])
2977+
2978+(define_insn "*stm2_ib_update"
2979+ [(match_parallel 0 "store_multiple_operation"
2980+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2981+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2982+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2983+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2984+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2985+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2986+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2987+ "stm%(ib%)\t%1!, {%3, %4}"
2988+ [(set_attr "type" "store2")
2989+ (set_attr "predicable" "yes")])
2990+
2991+(define_insn "*ldm2_da"
2992+ [(match_parallel 0 "load_multiple_operation"
2993+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2994+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2995+ (const_int -4))))
2996+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2997+ (mem:SI (match_dup 1)))])]
2998+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2999+ "ldm%(da%)\t%1, {%2, %3}"
3000+ [(set_attr "type" "load2")
3001+ (set_attr "predicable" "yes")])
3002+
3003+(define_insn "*ldm2_da_update"
3004+ [(match_parallel 0 "load_multiple_operation"
3005+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
3006+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3007+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
3008+ (mem:SI (plus:SI (match_dup 2)
3009+ (const_int -4))))
3010+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
3011+ (mem:SI (match_dup 2)))])]
3012+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
3013+ "ldm%(da%)\t%1!, {%3, %4}"
3014+ [(set_attr "type" "load2")
3015+ (set_attr "predicable" "yes")])
3016+
3017+(define_insn "*stm2_da"
3018+ [(match_parallel 0 "store_multiple_operation"
3019+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -4)))
3020+ (match_operand:SI 2 "arm_hard_register_operand" ""))
3021+ (set (mem:SI (match_dup 1))
3022+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
3023+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
3024+ "stm%(da%)\t%1, {%2, %3}"
3025+ [(set_attr "type" "store2")
3026+ (set_attr "predicable" "yes")])
3027+
3028+(define_insn "*stm2_da_update"
3029+ [(match_parallel 0 "store_multiple_operation"
3030+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
3031+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3032+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
3033+ (match_operand:SI 3 "arm_hard_register_operand" ""))
3034+ (set (mem:SI (match_dup 2))
3035+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
3036+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
3037+ "stm%(da%)\t%1!, {%3, %4}"
3038+ [(set_attr "type" "store2")
3039+ (set_attr "predicable" "yes")])
3040+
3041+(define_insn "*ldm2_db"
3042+ [(match_parallel 0 "load_multiple_operation"
3043+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
3044+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
3045+ (const_int -8))))
3046+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
3047+ (mem:SI (plus:SI (match_dup 1)
3048+ (const_int -4))))])]
3049+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
3050+ "ldm%(db%)\t%1, {%2, %3}"
3051+ [(set_attr "type" "load2")
3052+ (set_attr "predicable" "yes")])
3053+
3054+(define_insn "*ldm2_db_update"
3055+ [(match_parallel 0 "load_multiple_operation"
3056+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
3057+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3058+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
3059+ (mem:SI (plus:SI (match_dup 2)
3060+ (const_int -8))))
3061+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
3062+ (mem:SI (plus:SI (match_dup 2)
3063+ (const_int -4))))])]
3064+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
3065+ "ldm%(db%)\t%1!, {%3, %4}"
3066+ [(set_attr "type" "load2")
3067+ (set_attr "predicable" "yes")])
3068+
3069+(define_insn "*stm2_db"
3070+ [(match_parallel 0 "store_multiple_operation"
3071+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -8)))
3072+ (match_operand:SI 2 "arm_hard_register_operand" ""))
3073+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
3074+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
3075+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
3076+ "stm%(db%)\t%1, {%2, %3}"
3077+ [(set_attr "type" "store2")
3078+ (set_attr "predicable" "yes")])
3079+
3080+(define_insn "*stm2_db_update"
3081+ [(match_parallel 0 "store_multiple_operation"
3082+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
3083+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3084+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
3085+ (match_operand:SI 3 "arm_hard_register_operand" ""))
3086+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
3087+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
3088+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
3089+ "stm%(db%)\t%1!, {%3, %4}"
3090+ [(set_attr "type" "store2")
3091+ (set_attr "predicable" "yes")])
3092+
3093+(define_peephole2
3094+ [(set (match_operand:SI 0 "s_register_operand" "")
3095+ (match_operand:SI 2 "memory_operand" ""))
3096+ (set (match_operand:SI 1 "s_register_operand" "")
3097+ (match_operand:SI 3 "memory_operand" ""))]
3098+ ""
3099+ [(const_int 0)]
3100+{
3101+ if (gen_ldm_seq (operands, 2, false))
3102+ DONE;
3103+ else
3104+ FAIL;
3105+})
3106+
3107+(define_peephole2
3108+ [(set (match_operand:SI 0 "s_register_operand" "")
3109+ (match_operand:SI 4 "const_int_operand" ""))
3110+ (set (match_operand:SI 2 "memory_operand" "")
3111+ (match_dup 0))
3112+ (set (match_operand:SI 1 "s_register_operand" "")
3113+ (match_operand:SI 5 "const_int_operand" ""))
3114+ (set (match_operand:SI 3 "memory_operand" "")
3115+ (match_dup 1))]
3116+ ""
3117+ [(const_int 0)]
3118+{
3119+ if (gen_const_stm_seq (operands, 2))
3120+ DONE;
3121+ else
3122+ FAIL;
3123+})
3124+
3125+(define_peephole2
3126+ [(set (match_operand:SI 0 "s_register_operand" "")
3127+ (match_operand:SI 4 "const_int_operand" ""))
3128+ (set (match_operand:SI 1 "s_register_operand" "")
3129+ (match_operand:SI 5 "const_int_operand" ""))
3130+ (set (match_operand:SI 2 "memory_operand" "")
3131+ (match_dup 0))
3132+ (set (match_operand:SI 3 "memory_operand" "")
3133+ (match_dup 1))]
3134+ ""
3135+ [(const_int 0)]
3136+{
3137+ if (gen_const_stm_seq (operands, 2))
3138+ DONE;
3139+ else
3140+ FAIL;
3141+})
3142+
3143+(define_peephole2
3144+ [(set (match_operand:SI 2 "memory_operand" "")
3145+ (match_operand:SI 0 "s_register_operand" ""))
3146+ (set (match_operand:SI 3 "memory_operand" "")
3147+ (match_operand:SI 1 "s_register_operand" ""))]
3148+ ""
3149+ [(const_int 0)]
3150+{
3151+ if (gen_stm_seq (operands, 2))
3152+ DONE;
3153+ else
3154+ FAIL;
3155+})
3156+
3157+(define_peephole2
3158+ [(set (match_operand:SI 0 "s_register_operand" "")
3159+ (match_operand:SI 2 "memory_operand" ""))
3160+ (set (match_operand:SI 1 "s_register_operand" "")
3161+ (match_operand:SI 3 "memory_operand" ""))
3162+ (parallel
3163+ [(set (match_operand:SI 4 "s_register_operand" "")
3164+ (match_operator:SI 5 "commutative_binary_operator"
3165+ [(match_operand:SI 6 "s_register_operand" "")
3166+ (match_operand:SI 7 "s_register_operand" "")]))
3167+ (clobber (reg:CC CC_REGNUM))])]
3168+ "(((operands[6] == operands[0] && operands[7] == operands[1])
3169+ || (operands[7] == operands[0] && operands[6] == operands[1]))
3170+ && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[1]))"
3171+ [(parallel
3172+ [(set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))
3173+ (clobber (reg:CC CC_REGNUM))])]
3174+{
3175+ if (!gen_ldm_seq (operands, 2, true))
3176+ FAIL;
3177+})
3178+
3179+(define_peephole2
3180+ [(set (match_operand:SI 0 "s_register_operand" "")
3181+ (match_operand:SI 2 "memory_operand" ""))
3182+ (set (match_operand:SI 1 "s_register_operand" "")
3183+ (match_operand:SI 3 "memory_operand" ""))
3184+ (set (match_operand:SI 4 "s_register_operand" "")
3185+ (match_operator:SI 5 "commutative_binary_operator"
3186+ [(match_operand:SI 6 "s_register_operand" "")
3187+ (match_operand:SI 7 "s_register_operand" "")]))]
3188+ "(((operands[6] == operands[0] && operands[7] == operands[1])
3189+ || (operands[7] == operands[0] && operands[6] == operands[1]))
3190+ && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[1]))"
3191+ [(set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))]
3192+{
3193+ if (!gen_ldm_seq (operands, 2, true))
3194+ FAIL;
3195+})
3196+
3197
3198=== modified file 'gcc/config/arm/predicates.md'
3199--- old/gcc/config/arm/predicates.md 2010-11-04 10:45:05 +0000
3200+++ new/gcc/config/arm/predicates.md 2010-11-16 12:32:34 +0000
3201@@ -211,6 +211,11 @@
3202 (and (match_code "ior,xor,and")
3203 (match_test "mode == GET_MODE (op)")))
3204
3205+;; True for commutative operators
3206+(define_special_predicate "commutative_binary_operator"
3207+ (and (match_code "ior,xor,and,plus")
3208+ (match_test "mode == GET_MODE (op)")))
3209+
3210 ;; True for shift operators.
3211 (define_special_predicate "shift_operator"
3212 (and (ior (ior (and (match_code "mult")
3213@@ -334,16 +339,20 @@
3214 (match_code "parallel")
3215 {
3216 HOST_WIDE_INT count = XVECLEN (op, 0);
3217- int dest_regno;
3218+ unsigned dest_regno;
3219 rtx src_addr;
3220 HOST_WIDE_INT i = 1, base = 0;
3221+ HOST_WIDE_INT offset = 0;
3222 rtx elt;
3223+ bool addr_reg_loaded = false;
3224+ bool update = false;
3225
3226 if (low_irq_latency)
3227 return false;
3228
3229 if (count <= 1
3230- || GET_CODE (XVECEXP (op, 0, 0)) != SET)
3231+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
3232+ || !REG_P (SET_DEST (XVECEXP (op, 0, 0))))
3233 return false;
3234
3235 /* Check to see if this might be a write-back. */
3236@@ -351,6 +360,7 @@
3237 {
3238 i++;
3239 base = 1;
3240+ update = true;
3241
3242 /* Now check it more carefully. */
3243 if (GET_CODE (SET_DEST (elt)) != REG
3244@@ -369,6 +379,15 @@
3245
3246 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
3247 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
3248+ if (GET_CODE (src_addr) == PLUS)
3249+ {
3250+ if (GET_CODE (XEXP (src_addr, 1)) != CONST_INT)
3251+ return false;
3252+ offset = INTVAL (XEXP (src_addr, 1));
3253+ src_addr = XEXP (src_addr, 0);
3254+ }
3255+ if (!REG_P (src_addr))
3256+ return false;
3257
3258 for (; i < count; i++)
3259 {
3260@@ -377,16 +396,28 @@
3261 if (GET_CODE (elt) != SET
3262 || GET_CODE (SET_DEST (elt)) != REG
3263 || GET_MODE (SET_DEST (elt)) != SImode
3264- || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
3265+ || REGNO (SET_DEST (elt)) <= dest_regno
3266 || GET_CODE (SET_SRC (elt)) != MEM
3267 || GET_MODE (SET_SRC (elt)) != SImode
3268- || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
3269- || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
3270- || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
3271- || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4)
3272+ || ((GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
3273+ || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
3274+ || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
3275+ || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != offset + (i - base) * 4)
3276+ && (!REG_P (XEXP (SET_SRC (elt), 0))
3277+ || offset + (i - base) * 4 != 0)))
3278 return false;
3279+ dest_regno = REGNO (SET_DEST (elt));
3280+ if (dest_regno == REGNO (src_addr))
3281+ addr_reg_loaded = true;
3282 }
3283-
3284+ /* For Thumb, we only have updating instructions. If the pattern does
3285+ not describe an update, it must be because the address register is
3286+ in the list of loaded registers - on the hardware, this has the effect
3287+ of overriding the update. */
3288+ if (update && addr_reg_loaded)
3289+ return false;
3290+ if (TARGET_THUMB1)
3291+ return update || addr_reg_loaded;
3292 return true;
3293 })
3294
3295@@ -394,9 +425,9 @@
3296 (match_code "parallel")
3297 {
3298 HOST_WIDE_INT count = XVECLEN (op, 0);
3299- int src_regno;
3300+ unsigned src_regno;
3301 rtx dest_addr;
3302- HOST_WIDE_INT i = 1, base = 0;
3303+ HOST_WIDE_INT i = 1, base = 0, offset = 0;
3304 rtx elt;
3305
3306 if (low_irq_latency)
3307@@ -430,6 +461,16 @@
3308 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
3309 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
3310
3311+ if (GET_CODE (dest_addr) == PLUS)
3312+ {
3313+ if (GET_CODE (XEXP (dest_addr, 1)) != CONST_INT)
3314+ return false;
3315+ offset = INTVAL (XEXP (dest_addr, 1));
3316+ dest_addr = XEXP (dest_addr, 0);
3317+ }
3318+ if (!REG_P (dest_addr))
3319+ return false;
3320+
3321 for (; i < count; i++)
3322 {
3323 elt = XVECEXP (op, 0, i);
3324@@ -437,14 +478,17 @@
3325 if (GET_CODE (elt) != SET
3326 || GET_CODE (SET_SRC (elt)) != REG
3327 || GET_MODE (SET_SRC (elt)) != SImode
3328- || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
3329+ || REGNO (SET_SRC (elt)) <= src_regno
3330 || GET_CODE (SET_DEST (elt)) != MEM
3331 || GET_MODE (SET_DEST (elt)) != SImode
3332- || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
3333- || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
3334- || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
3335- || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
3336+ || ((GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
3337+ || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
3338+ || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
3339+ || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != offset + (i - base) * 4)
3340+ && (!REG_P (XEXP (SET_DEST (elt), 0))
3341+ || offset + (i - base) * 4 != 0)))
3342 return false;
3343+ src_regno = REGNO (SET_SRC (elt));
3344 }
3345
3346 return true;
3347
3348=== modified file 'gcc/config/i386/i386.md'
3349--- old/gcc/config/i386/i386.md 2011-01-05 12:12:18 +0000
3350+++ new/gcc/config/i386/i386.md 2011-01-05 18:20:37 +0000
3351@@ -20023,15 +20023,14 @@
3352 ;; leal (%edx,%eax,4), %eax
3353
3354 (define_peephole2
3355- [(parallel [(set (match_operand 0 "register_operand" "")
3356+ [(match_scratch:SI 5 "r")
3357+ (parallel [(set (match_operand 0 "register_operand" "")
3358 (ashift (match_operand 1 "register_operand" "")
3359 (match_operand 2 "const_int_operand" "")))
3360 (clobber (reg:CC FLAGS_REG))])
3361- (set (match_operand 3 "register_operand")
3362- (match_operand 4 "x86_64_general_operand" ""))
3363- (parallel [(set (match_operand 5 "register_operand" "")
3364- (plus (match_operand 6 "register_operand" "")
3365- (match_operand 7 "register_operand" "")))
3366+ (parallel [(set (match_operand 3 "register_operand" "")
3367+ (plus (match_dup 0)
3368+ (match_operand 4 "x86_64_general_operand" "")))
3369 (clobber (reg:CC FLAGS_REG))])]
3370 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
3371 /* Validate MODE for lea. */
3372@@ -20041,30 +20040,21 @@
3373 || GET_MODE (operands[0]) == SImode
3374 || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
3375 /* We reorder load and the shift. */
3376- && !rtx_equal_p (operands[1], operands[3])
3377- && !reg_overlap_mentioned_p (operands[0], operands[4])
3378- /* Last PLUS must consist of operand 0 and 3. */
3379- && !rtx_equal_p (operands[0], operands[3])
3380- && (rtx_equal_p (operands[3], operands[6])
3381- || rtx_equal_p (operands[3], operands[7]))
3382- && (rtx_equal_p (operands[0], operands[6])
3383- || rtx_equal_p (operands[0], operands[7]))
3384- /* The intermediate operand 0 must die or be same as output. */
3385- && (rtx_equal_p (operands[0], operands[5])
3386- || peep2_reg_dead_p (3, operands[0]))"
3387- [(set (match_dup 3) (match_dup 4))
3388+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
3389+ [(set (match_dup 5) (match_dup 4))
3390 (set (match_dup 0) (match_dup 1))]
3391 {
3392- enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
3393+ enum machine_mode mode = GET_MODE (operands[1]) == DImode ? DImode : SImode;
3394 int scale = 1 << INTVAL (operands[2]);
3395 rtx index = gen_lowpart (Pmode, operands[1]);
3396- rtx base = gen_lowpart (Pmode, operands[3]);
3397- rtx dest = gen_lowpart (mode, operands[5]);
3398+ rtx base = gen_lowpart (Pmode, operands[5]);
3399+ rtx dest = gen_lowpart (mode, operands[3]);
3400
3401 operands[1] = gen_rtx_PLUS (Pmode, base,
3402 gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
3403 if (mode != Pmode)
3404 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
3405+ operands[5] = base;
3406 operands[0] = dest;
3407 })
3408
3409
3410=== modified file 'gcc/df-problems.c'
3411--- old/gcc/df-problems.c 2010-11-16 22:17:17 +0000
3412+++ new/gcc/df-problems.c 2010-12-02 13:42:47 +0000
3413@@ -3748,9 +3748,22 @@
3414 for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
3415 {
3416 df_ref def = *def_rec;
3417- /* If the def is to only part of the reg, it does
3418- not kill the other defs that reach here. */
3419- if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
3420+ bitmap_set_bit (defs, DF_REF_REGNO (def));
3421+ }
3422+}
3423+
3424+/* Find the set of real DEFs, which are not clobbers, for INSN. */
3425+
3426+void
3427+df_simulate_find_noclobber_defs (rtx insn, bitmap defs)
3428+{
3429+ df_ref *def_rec;
3430+ unsigned int uid = INSN_UID (insn);
3431+
3432+ for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
3433+ {
3434+ df_ref def = *def_rec;
3435+ if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
3436 bitmap_set_bit (defs, DF_REF_REGNO (def));
3437 }
3438 }
3439@@ -3921,7 +3934,7 @@
3440 {
3441 df_ref def = *def_rec;
3442 if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
3443- bitmap_clear_bit (live, DF_REF_REGNO (def));
3444+ bitmap_set_bit (live, DF_REF_REGNO (def));
3445 }
3446 }
3447
3448@@ -3942,7 +3955,7 @@
3449 while here the scan is performed forwards! So, first assume that the
3450 def is live, and if this is not true REG_UNUSED notes will rectify the
3451 situation. */
3452- df_simulate_find_defs (insn, live);
3453+ df_simulate_find_noclobber_defs (insn, live);
3454
3455 /* Clear all of the registers that go dead. */
3456 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
3457
3458=== modified file 'gcc/df.h'
3459--- old/gcc/df.h 2010-01-29 12:14:47 +0000
3460+++ new/gcc/df.h 2010-12-02 13:42:47 +0000
3461@@ -978,6 +978,7 @@
3462 extern void df_md_add_problem (void);
3463 extern void df_md_simulate_artificial_defs_at_top (basic_block, bitmap);
3464 extern void df_md_simulate_one_insn (basic_block, rtx, bitmap);
3465+extern void df_simulate_find_noclobber_defs (rtx, bitmap);
3466 extern void df_simulate_find_defs (rtx, bitmap);
3467 extern void df_simulate_defs (rtx, bitmap);
3468 extern void df_simulate_uses (rtx, bitmap);
3469
3470=== modified file 'gcc/fwprop.c'
3471--- old/gcc/fwprop.c 2010-04-02 18:54:46 +0000
3472+++ new/gcc/fwprop.c 2010-11-16 12:32:34 +0000
3473@@ -228,7 +228,10 @@
3474
3475 process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP);
3476 process_defs (df_get_artificial_defs (bb_index), DF_REF_AT_TOP);
3477- df_simulate_initialize_forwards (bb, local_lr);
3478+
3479+ /* We don't call df_simulate_initialize_forwards, as it may overestimate
3480+ the live registers if there are unused artificial defs. We prefer
3481+ liveness to be underestimated. */
3482
3483 FOR_BB_INSNS (bb, insn)
3484 if (INSN_P (insn))
3485
3486=== modified file 'gcc/genoutput.c'
3487--- old/gcc/genoutput.c 2009-04-08 14:00:34 +0000
3488+++ new/gcc/genoutput.c 2010-11-16 12:32:34 +0000
3489@@ -266,6 +266,8 @@
3490
3491 printf (" %d,\n", d->strict_low);
3492
3493+ printf (" %d,\n", d->constraint == NULL ? 1 : 0);
3494+
3495 printf (" %d\n", d->eliminable);
3496
3497 printf(" },\n");
3498
3499=== modified file 'gcc/genrecog.c'
3500--- old/gcc/genrecog.c 2009-06-22 09:29:13 +0000
3501+++ new/gcc/genrecog.c 2010-11-16 12:32:34 +0000
3502@@ -1782,20 +1782,11 @@
3503 int odepth = strlen (oldpos);
3504 int ndepth = strlen (newpos);
3505 int depth;
3506- int old_has_insn, new_has_insn;
3507
3508 /* Pop up as many levels as necessary. */
3509 for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
3510 continue;
3511
3512- /* Hunt for the last [A-Z] in both strings. */
3513- for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
3514- if (ISUPPER (oldpos[old_has_insn]))
3515- break;
3516- for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
3517- if (ISUPPER (newpos[new_has_insn]))
3518- break;
3519-
3520 /* Go down to desired level. */
3521 while (depth < ndepth)
3522 {
3523
3524=== modified file 'gcc/ifcvt.c'
3525--- old/gcc/ifcvt.c 2011-01-05 12:12:18 +0000
3526+++ new/gcc/ifcvt.c 2011-01-05 18:20:37 +0000
3527@@ -4011,6 +4011,7 @@
3528 basic_block new_dest = dest_edge->dest;
3529 rtx head, end, jump, earliest = NULL_RTX, old_dest;
3530 bitmap merge_set = NULL;
3531+ bitmap merge_set_noclobber = NULL;
3532 /* Number of pending changes. */
3533 int n_validated_changes = 0;
3534 rtx new_dest_label;
3535@@ -4169,6 +4170,7 @@
3536 end of the block. */
3537
3538 merge_set = BITMAP_ALLOC (&reg_obstack);
3539+ merge_set_noclobber = BITMAP_ALLOC (&reg_obstack);
3540
3541 /* If we allocated new pseudos (e.g. in the conditional move
3542 expander called from noce_emit_cmove), we must resize the
3543@@ -4187,6 +4189,7 @@
3544 df_ref def = *def_rec;
3545 bitmap_set_bit (merge_set, DF_REF_REGNO (def));
3546 }
3547+ df_simulate_find_noclobber_defs (insn, merge_set_noclobber);
3548 }
3549 }
3550
3551@@ -4197,7 +4200,7 @@
3552 unsigned i;
3553 bitmap_iterator bi;
3554
3555- EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
3556+ EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi)
3557 {
3558 if (i < FIRST_PSEUDO_REGISTER
3559 && ! fixed_regs[i]
3560@@ -4233,7 +4236,7 @@
3561 TEST_SET & DF_LIVE_IN (merge_bb)
3562 are empty. */
3563
3564- if (bitmap_intersect_p (merge_set, test_set)
3565+ if (bitmap_intersect_p (merge_set_noclobber, test_set)
3566 || bitmap_intersect_p (merge_set, test_live)
3567 || bitmap_intersect_p (test_set, df_get_live_in (merge_bb)))
3568 intersect = true;
3569@@ -4320,6 +4323,7 @@
3570 remove_reg_equal_equiv_notes_for_regno (i);
3571
3572 BITMAP_FREE (merge_set);
3573+ BITMAP_FREE (merge_set_noclobber);
3574 }
3575
3576 reorder_insns (head, end, PREV_INSN (earliest));
3577@@ -4340,7 +4344,10 @@
3578 cancel_changes (0);
3579 fail:
3580 if (merge_set)
3581- BITMAP_FREE (merge_set);
3582+ {
3583+ BITMAP_FREE (merge_set);
3584+ BITMAP_FREE (merge_set_noclobber);
3585+ }
3586 return FALSE;
3587 }
3588
3589
3590=== modified file 'gcc/recog.c'
3591--- old/gcc/recog.c 2010-08-05 15:28:47 +0000
3592+++ new/gcc/recog.c 2010-11-16 12:32:34 +0000
3593@@ -2082,6 +2082,7 @@
3594 recog_data.operand_loc,
3595 recog_data.constraints,
3596 recog_data.operand_mode, NULL);
3597+ memset (recog_data.is_operator, 0, sizeof recog_data.is_operator);
3598 if (noperands > 0)
3599 {
3600 const char *p = recog_data.constraints[0];
3601@@ -2111,6 +2112,7 @@
3602 for (i = 0; i < noperands; i++)
3603 {
3604 recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
3605+ recog_data.is_operator[i] = insn_data[icode].operand[i].is_operator;
3606 recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
3607 /* VOIDmode match_operands gets mode from their real operand. */
3608 if (recog_data.operand_mode[i] == VOIDmode)
3609@@ -2909,6 +2911,10 @@
3610
3611 static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
3612 static int peep2_current;
3613+
3614+static bool peep2_do_rebuild_jump_labels;
3615+static bool peep2_do_cleanup_cfg;
3616+
3617 /* The number of instructions available to match a peep2. */
3618 int peep2_current_count;
3619
3620@@ -2917,6 +2923,16 @@
3621 DF_LIVE_OUT for the block. */
3622 #define PEEP2_EOB pc_rtx
3623
3624+/* Wrap N to fit into the peep2_insn_data buffer. */
3625+
3626+static int
3627+peep2_buf_position (int n)
3628+{
3629+ if (n >= MAX_INSNS_PER_PEEP2 + 1)
3630+ n -= MAX_INSNS_PER_PEEP2 + 1;
3631+ return n;
3632+}
3633+
3634 /* Return the Nth non-note insn after `current', or return NULL_RTX if it
3635 does not exist. Used by the recognizer to find the next insn to match
3636 in a multi-insn pattern. */
3637@@ -2926,9 +2942,7 @@
3638 {
3639 gcc_assert (n <= peep2_current_count);
3640
3641- n += peep2_current;
3642- if (n >= MAX_INSNS_PER_PEEP2 + 1)
3643- n -= MAX_INSNS_PER_PEEP2 + 1;
3644+ n = peep2_buf_position (peep2_current + n);
3645
3646 return peep2_insn_data[n].insn;
3647 }
3648@@ -2941,9 +2955,7 @@
3649 {
3650 gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3651
3652- ofs += peep2_current;
3653- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
3654- ofs -= MAX_INSNS_PER_PEEP2 + 1;
3655+ ofs = peep2_buf_position (peep2_current + ofs);
3656
3657 gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3658
3659@@ -2959,9 +2971,7 @@
3660
3661 gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3662
3663- ofs += peep2_current;
3664- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
3665- ofs -= MAX_INSNS_PER_PEEP2 + 1;
3666+ ofs = peep2_buf_position (peep2_current + ofs);
3667
3668 gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3669
3670@@ -2996,12 +3006,8 @@
3671 gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
3672 gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
3673
3674- from += peep2_current;
3675- if (from >= MAX_INSNS_PER_PEEP2 + 1)
3676- from -= MAX_INSNS_PER_PEEP2 + 1;
3677- to += peep2_current;
3678- if (to >= MAX_INSNS_PER_PEEP2 + 1)
3679- to -= MAX_INSNS_PER_PEEP2 + 1;
3680+ from = peep2_buf_position (peep2_current + from);
3681+ to = peep2_buf_position (peep2_current + to);
3682
3683 gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3684 REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
3685@@ -3010,8 +3016,7 @@
3686 {
3687 HARD_REG_SET this_live;
3688
3689- if (++from >= MAX_INSNS_PER_PEEP2 + 1)
3690- from = 0;
3691+ from = peep2_buf_position (from + 1);
3692 gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3693 REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
3694 IOR_HARD_REG_SET (live, this_live);
3695@@ -3104,19 +3109,234 @@
3696 COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
3697 }
3698
3699+/* While scanning basic block BB, we found a match of length MATCH_LEN,
3700+ starting at INSN. Perform the replacement, removing the old insns and
3701+ replacing them with ATTEMPT. Returns the last insn emitted. */
3702+
3703+static rtx
3704+peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt)
3705+{
3706+ int i;
3707+ rtx last, note, before_try, x;
3708+ bool was_call = false;
3709+
3710+ /* If we are splitting a CALL_INSN, look for the CALL_INSN
3711+ in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
3712+ cfg-related call notes. */
3713+ for (i = 0; i <= match_len; ++i)
3714+ {
3715+ int j;
3716+ rtx old_insn, new_insn, note;
3717+
3718+ j = peep2_buf_position (peep2_current + i);
3719+ old_insn = peep2_insn_data[j].insn;
3720+ if (!CALL_P (old_insn))
3721+ continue;
3722+ was_call = true;
3723+
3724+ new_insn = attempt;
3725+ while (new_insn != NULL_RTX)
3726+ {
3727+ if (CALL_P (new_insn))
3728+ break;
3729+ new_insn = NEXT_INSN (new_insn);
3730+ }
3731+
3732+ gcc_assert (new_insn != NULL_RTX);
3733+
3734+ CALL_INSN_FUNCTION_USAGE (new_insn)
3735+ = CALL_INSN_FUNCTION_USAGE (old_insn);
3736+
3737+ for (note = REG_NOTES (old_insn);
3738+ note;
3739+ note = XEXP (note, 1))
3740+ switch (REG_NOTE_KIND (note))
3741+ {
3742+ case REG_NORETURN:
3743+ case REG_SETJMP:
3744+ add_reg_note (new_insn, REG_NOTE_KIND (note),
3745+ XEXP (note, 0));
3746+ break;
3747+ default:
3748+ /* Discard all other reg notes. */
3749+ break;
3750+ }
3751+
3752+ /* Croak if there is another call in the sequence. */
3753+ while (++i <= match_len)
3754+ {
3755+ j = peep2_buf_position (peep2_current + i);
3756+ old_insn = peep2_insn_data[j].insn;
3757+ gcc_assert (!CALL_P (old_insn));
3758+ }
3759+ break;
3760+ }
3761+
3762+ i = peep2_buf_position (peep2_current + match_len);
3763+
3764+ note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX);
3765+
3766+ /* Replace the old sequence with the new. */
3767+ last = emit_insn_after_setloc (attempt,
3768+ peep2_insn_data[i].insn,
3769+ INSN_LOCATOR (peep2_insn_data[i].insn));
3770+ before_try = PREV_INSN (insn);
3771+ delete_insn_chain (insn, peep2_insn_data[i].insn, false);
3772+
3773+ /* Re-insert the EH_REGION notes. */
3774+ if (note || (was_call && nonlocal_goto_handler_labels))
3775+ {
3776+ edge eh_edge;
3777+ edge_iterator ei;
3778+
3779+ FOR_EACH_EDGE (eh_edge, ei, bb->succs)
3780+ if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
3781+ break;
3782+
3783+ if (note)
3784+ copy_reg_eh_region_note_backward (note, last, before_try);
3785+
3786+ if (eh_edge)
3787+ for (x = last; x != before_try; x = PREV_INSN (x))
3788+ if (x != BB_END (bb)
3789+ && (can_throw_internal (x)
3790+ || can_nonlocal_goto (x)))
3791+ {
3792+ edge nfte, nehe;
3793+ int flags;
3794+
3795+ nfte = split_block (bb, x);
3796+ flags = (eh_edge->flags
3797+ & (EDGE_EH | EDGE_ABNORMAL));
3798+ if (CALL_P (x))
3799+ flags |= EDGE_ABNORMAL_CALL;
3800+ nehe = make_edge (nfte->src, eh_edge->dest,
3801+ flags);
3802+
3803+ nehe->probability = eh_edge->probability;
3804+ nfte->probability
3805+ = REG_BR_PROB_BASE - nehe->probability;
3806+
3807+ peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
3808+ bb = nfte->src;
3809+ eh_edge = nehe;
3810+ }
3811+
3812+ /* Converting possibly trapping insn to non-trapping is
3813+ possible. Zap dummy outgoing edges. */
3814+ peep2_do_cleanup_cfg |= purge_dead_edges (bb);
3815+ }
3816+
3817+ /* If we generated a jump instruction, it won't have
3818+ JUMP_LABEL set. Recompute after we're done. */
3819+ for (x = last; x != before_try; x = PREV_INSN (x))
3820+ if (JUMP_P (x))
3821+ {
3822+ peep2_do_rebuild_jump_labels = true;
3823+ break;
3824+ }
3825+
3826+ return last;
3827+}
3828+
3829+/* After performing a replacement in basic block BB, fix up the life
3830+ information in our buffer. LAST is the last of the insns that we
3831+ emitted as a replacement. PREV is the insn before the start of
3832+ the replacement. MATCH_LEN is the number of instructions that were
3833+ matched, and which now need to be replaced in the buffer. */
3834+
3835+static void
3836+peep2_update_life (basic_block bb, int match_len, rtx last, rtx prev)
3837+{
3838+ int i = peep2_buf_position (peep2_current + match_len + 1);
3839+ rtx x;
3840+ regset_head live;
3841+
3842+ INIT_REG_SET (&live);
3843+ COPY_REG_SET (&live, peep2_insn_data[i].live_before);
3844+
3845+ gcc_assert (peep2_current_count >= match_len + 1);
3846+ peep2_current_count -= match_len + 1;
3847+
3848+ x = last;
3849+ do
3850+ {
3851+ if (INSN_P (x))
3852+ {
3853+ df_insn_rescan (x);
3854+ if (peep2_current_count < MAX_INSNS_PER_PEEP2)
3855+ {
3856+ peep2_current_count++;
3857+ if (--i < 0)
3858+ i = MAX_INSNS_PER_PEEP2;
3859+ peep2_insn_data[i].insn = x;
3860+ df_simulate_one_insn_backwards (bb, x, &live);
3861+ COPY_REG_SET (peep2_insn_data[i].live_before, &live);
3862+ }
3863+ }
3864+ x = PREV_INSN (x);
3865+ }
3866+ while (x != prev);
3867+ CLEAR_REG_SET (&live);
3868+
3869+ peep2_current = i;
3870+}
3871+
3872+/* Add INSN, which is in BB, at the end of the peep2 insn buffer if possible.
3873+ Return true if we added it, false otherwise. The caller will try to match
3874+ peepholes against the buffer if we return false; otherwise it will try to
3875+ add more instructions to the buffer. */
3876+
3877+static bool
3878+peep2_fill_buffer (basic_block bb, rtx insn, regset live)
3879+{
3880+ int pos;
3881+
3882+ /* Once we have filled the maximum number of insns the buffer can hold,
3883+ allow the caller to match the insns against peepholes. We wait until
3884+ the buffer is full in case the target has similar peepholes of different
3885+ length; we always want to match the longest if possible. */
3886+ if (peep2_current_count == MAX_INSNS_PER_PEEP2)
3887+ return false;
3888+
3889+ /* If an insn has RTX_FRAME_RELATED_P set, peephole substitution would lose
3890+ the REG_FRAME_RELATED_EXPR that is attached. */
3891+ if (RTX_FRAME_RELATED_P (insn))
3892+ {
3893+ /* Let the buffer drain first. */
3894+ if (peep2_current_count > 0)
3895+ return false;
3896+ /* Step over the insn then return true without adding the insn
3897+ to the buffer; this will cause us to process the next
3898+ insn. */
3899+ df_simulate_one_insn_forwards (bb, insn, live);
3900+ return true;
3901+ }
3902+
3903+ pos = peep2_buf_position (peep2_current + peep2_current_count);
3904+ peep2_insn_data[pos].insn = insn;
3905+ COPY_REG_SET (peep2_insn_data[pos].live_before, live);
3906+ peep2_current_count++;
3907+
3908+ df_simulate_one_insn_forwards (bb, insn, live);
3909+ return true;
3910+}
3911+
3912 /* Perform the peephole2 optimization pass. */
3913
3914 static void
3915 peephole2_optimize (void)
3916 {
3917- rtx insn, prev;
3918+ rtx insn;
3919 bitmap live;
3920 int i;
3921 basic_block bb;
3922- bool do_cleanup_cfg = false;
3923- bool do_rebuild_jump_labels = false;
3924+
3925+ peep2_do_cleanup_cfg = false;
3926+ peep2_do_rebuild_jump_labels = false;
3927
3928 df_set_flags (DF_LR_RUN_DCE);
3929+ df_note_add_problem ();
3930 df_analyze ();
3931
3932 /* Initialize the regsets we're going to use. */
3933@@ -3126,214 +3346,59 @@
3934
3935 FOR_EACH_BB_REVERSE (bb)
3936 {
3937+ bool past_end = false;
3938+ int pos;
3939+
3940 rtl_profile_for_bb (bb);
3941
3942 /* Start up propagation. */
3943- bitmap_copy (live, DF_LR_OUT (bb));
3944- df_simulate_initialize_backwards (bb, live);
3945+ bitmap_copy (live, DF_LR_IN (bb));
3946+ df_simulate_initialize_forwards (bb, live);
3947 peep2_reinit_state (live);
3948
3949- for (insn = BB_END (bb); ; insn = prev)
3950+ insn = BB_HEAD (bb);
3951+ for (;;)
3952 {
3953- prev = PREV_INSN (insn);
3954- if (NONDEBUG_INSN_P (insn))
3955+ rtx attempt, head;
3956+ int match_len;
3957+
3958+ if (!past_end && !NONDEBUG_INSN_P (insn))
3959 {
3960- rtx attempt, before_try, x;
3961- int match_len;
3962- rtx note;
3963- bool was_call = false;
3964-
3965- /* Record this insn. */
3966- if (--peep2_current < 0)
3967- peep2_current = MAX_INSNS_PER_PEEP2;
3968- if (peep2_current_count < MAX_INSNS_PER_PEEP2
3969- && peep2_insn_data[peep2_current].insn == NULL_RTX)
3970- peep2_current_count++;
3971- peep2_insn_data[peep2_current].insn = insn;
3972- df_simulate_one_insn_backwards (bb, insn, live);
3973- COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
3974-
3975- if (RTX_FRAME_RELATED_P (insn))
3976- {
3977- /* If an insn has RTX_FRAME_RELATED_P set, peephole
3978- substitution would lose the
3979- REG_FRAME_RELATED_EXPR that is attached. */
3980- peep2_reinit_state (live);
3981- attempt = NULL;
3982- }
3983- else
3984- /* Match the peephole. */
3985- attempt = peephole2_insns (PATTERN (insn), insn, &match_len);
3986-
3987- if (attempt != NULL)
3988- {
3989- /* If we are splitting a CALL_INSN, look for the CALL_INSN
3990- in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
3991- cfg-related call notes. */
3992- for (i = 0; i <= match_len; ++i)
3993- {
3994- int j;
3995- rtx old_insn, new_insn, note;
3996-
3997- j = i + peep2_current;
3998- if (j >= MAX_INSNS_PER_PEEP2 + 1)
3999- j -= MAX_INSNS_PER_PEEP2 + 1;
4000- old_insn = peep2_insn_data[j].insn;
4001- if (!CALL_P (old_insn))
4002- continue;
4003- was_call = true;
4004-
4005- new_insn = attempt;
4006- while (new_insn != NULL_RTX)
4007- {
4008- if (CALL_P (new_insn))
4009- break;
4010- new_insn = NEXT_INSN (new_insn);
4011- }
4012-
4013- gcc_assert (new_insn != NULL_RTX);
4014-
4015- CALL_INSN_FUNCTION_USAGE (new_insn)
4016- = CALL_INSN_FUNCTION_USAGE (old_insn);
4017-
4018- for (note = REG_NOTES (old_insn);
4019- note;
4020- note = XEXP (note, 1))
4021- switch (REG_NOTE_KIND (note))
4022- {
4023- case REG_NORETURN:
4024- case REG_SETJMP:
4025- add_reg_note (new_insn, REG_NOTE_KIND (note),
4026- XEXP (note, 0));
4027- break;
4028- default:
4029- /* Discard all other reg notes. */
4030- break;
4031- }
4032-
4033- /* Croak if there is another call in the sequence. */
4034- while (++i <= match_len)
4035- {
4036- j = i + peep2_current;
4037- if (j >= MAX_INSNS_PER_PEEP2 + 1)
4038- j -= MAX_INSNS_PER_PEEP2 + 1;
4039- old_insn = peep2_insn_data[j].insn;
4040- gcc_assert (!CALL_P (old_insn));
4041- }
4042- break;
4043- }
4044-
4045- i = match_len + peep2_current;
4046- if (i >= MAX_INSNS_PER_PEEP2 + 1)
4047- i -= MAX_INSNS_PER_PEEP2 + 1;
4048-
4049- note = find_reg_note (peep2_insn_data[i].insn,
4050- REG_EH_REGION, NULL_RTX);
4051-
4052- /* Replace the old sequence with the new. */
4053- attempt = emit_insn_after_setloc (attempt,
4054- peep2_insn_data[i].insn,
4055- INSN_LOCATOR (peep2_insn_data[i].insn));
4056- before_try = PREV_INSN (insn);
4057- delete_insn_chain (insn, peep2_insn_data[i].insn, false);
4058-
4059- /* Re-insert the EH_REGION notes. */
4060- if (note || (was_call && nonlocal_goto_handler_labels))
4061- {
4062- edge eh_edge;
4063- edge_iterator ei;
4064-
4065- FOR_EACH_EDGE (eh_edge, ei, bb->succs)
4066- if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
4067- break;
4068-
4069- if (note)
4070- copy_reg_eh_region_note_backward (note, attempt,
4071- before_try);
4072-
4073- if (eh_edge)
4074- for (x = attempt ; x != before_try ; x = PREV_INSN (x))
4075- if (x != BB_END (bb)
4076- && (can_throw_internal (x)
4077- || can_nonlocal_goto (x)))
4078- {
4079- edge nfte, nehe;
4080- int flags;
4081-
4082- nfte = split_block (bb, x);
4083- flags = (eh_edge->flags
4084- & (EDGE_EH | EDGE_ABNORMAL));
4085- if (CALL_P (x))
4086- flags |= EDGE_ABNORMAL_CALL;
4087- nehe = make_edge (nfte->src, eh_edge->dest,
4088- flags);
4089-
4090- nehe->probability = eh_edge->probability;
4091- nfte->probability
4092- = REG_BR_PROB_BASE - nehe->probability;
4093-
4094- do_cleanup_cfg |= purge_dead_edges (nfte->dest);
4095- bb = nfte->src;
4096- eh_edge = nehe;
4097- }
4098-
4099- /* Converting possibly trapping insn to non-trapping is
4100- possible. Zap dummy outgoing edges. */
4101- do_cleanup_cfg |= purge_dead_edges (bb);
4102- }
4103-
4104- if (targetm.have_conditional_execution ())
4105- {
4106- for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
4107- peep2_insn_data[i].insn = NULL_RTX;
4108- peep2_insn_data[peep2_current].insn = PEEP2_EOB;
4109- peep2_current_count = 0;
4110- }
4111- else
4112- {
4113- /* Back up lifetime information past the end of the
4114- newly created sequence. */
4115- if (++i >= MAX_INSNS_PER_PEEP2 + 1)
4116- i = 0;
4117- bitmap_copy (live, peep2_insn_data[i].live_before);
4118-
4119- /* Update life information for the new sequence. */
4120- x = attempt;
4121- do
4122- {
4123- if (INSN_P (x))
4124- {
4125- if (--i < 0)
4126- i = MAX_INSNS_PER_PEEP2;
4127- if (peep2_current_count < MAX_INSNS_PER_PEEP2
4128- && peep2_insn_data[i].insn == NULL_RTX)
4129- peep2_current_count++;
4130- peep2_insn_data[i].insn = x;
4131- df_insn_rescan (x);
4132- df_simulate_one_insn_backwards (bb, x, live);
4133- bitmap_copy (peep2_insn_data[i].live_before,
4134- live);
4135- }
4136- x = PREV_INSN (x);
4137- }
4138- while (x != prev);
4139-
4140- peep2_current = i;
4141- }
4142-
4143- /* If we generated a jump instruction, it won't have
4144- JUMP_LABEL set. Recompute after we're done. */
4145- for (x = attempt; x != before_try; x = PREV_INSN (x))
4146- if (JUMP_P (x))
4147- {
4148- do_rebuild_jump_labels = true;
4149- break;
4150- }
4151- }
4152+ next_insn:
4153+ insn = NEXT_INSN (insn);
4154+ if (insn == NEXT_INSN (BB_END (bb)))
4155+ past_end = true;
4156+ continue;
4157 }
4158+ if (!past_end && peep2_fill_buffer (bb, insn, live))
4159+ goto next_insn;
4160
4161- if (insn == BB_HEAD (bb))
4162+ /* If we did not fill an empty buffer, it signals the end of the
4163+ block. */
4164+ if (peep2_current_count == 0)
4165 break;
4166+
4167+ /* The buffer filled to the current maximum, so try to match. */
4168+
4169+ pos = peep2_buf_position (peep2_current + peep2_current_count);
4170+ peep2_insn_data[pos].insn = PEEP2_EOB;
4171+ COPY_REG_SET (peep2_insn_data[pos].live_before, live);
4172+
4173+ /* Match the peephole. */
4174+ head = peep2_insn_data[peep2_current].insn;
4175+ attempt = peephole2_insns (PATTERN (head), head, &match_len);
4176+ if (attempt != NULL)
4177+ {
4178+ rtx last;
4179+ last = peep2_attempt (bb, head, match_len, attempt);
4180+ peep2_update_life (bb, match_len, last, PREV_INSN (attempt));
4181+ }
4182+ else
4183+ {
4184+ /* If no match, advance the buffer by one insn. */
4185+ peep2_current = peep2_buf_position (peep2_current + 1);
4186+ peep2_current_count--;
4187+ }
4188 }
4189 }
4190
4191@@ -3341,7 +3406,7 @@
4192 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
4193 BITMAP_FREE (peep2_insn_data[i].live_before);
4194 BITMAP_FREE (live);
4195- if (do_rebuild_jump_labels)
4196+ if (peep2_do_rebuild_jump_labels)
4197 rebuild_jump_labels (get_insns ());
4198 }
4199 #endif /* HAVE_peephole2 */
4200
4201=== modified file 'gcc/recog.h'
4202--- old/gcc/recog.h 2009-10-26 21:55:59 +0000
4203+++ new/gcc/recog.h 2010-11-16 12:32:34 +0000
4204@@ -194,6 +194,9 @@
4205 /* Gives the constraint string for operand N. */
4206 const char *constraints[MAX_RECOG_OPERANDS];
4207
4208+ /* Nonzero if operand N is a match_operator or a match_parallel. */
4209+ char is_operator[MAX_RECOG_OPERANDS];
4210+
4211 /* Gives the mode of operand N. */
4212 enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
4213
4214@@ -260,6 +263,8 @@
4215
4216 const char strict_low;
4217
4218+ const char is_operator;
4219+
4220 const char eliminable;
4221 };
4222
4223
4224=== modified file 'gcc/reload.c'
4225--- old/gcc/reload.c 2009-12-21 16:32:44 +0000
4226+++ new/gcc/reload.c 2010-11-16 12:32:34 +0000
4227@@ -3631,7 +3631,7 @@
4228 || modified[j] != RELOAD_WRITE)
4229 && j != i
4230 /* Ignore things like match_operator operands. */
4231- && *recog_data.constraints[j] != 0
4232+ && !recog_data.is_operator[j]
4233 /* Don't count an input operand that is constrained to match
4234 the early clobber operand. */
4235 && ! (this_alternative_matches[j] == i
4236
diff --git a/recipes-devtools/gcc/gcc-4.5/sh4-multilib.patch b/recipes-devtools/gcc/gcc-4.5/sh4-multilib.patch
new file mode 100644
index 000000000..c895c95e1
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/sh4-multilib.patch
@@ -0,0 +1,25 @@
1# DP: Fix multilib (m4/m4-nofpu) for sh4-linux
2
3---
4 a/gcc/config.gcc | 5 +++--
5 1 files changed, 3 insertions(+), 2 deletions(-)
6
7Index: gcc-4_5-branch/gcc/config.gcc
8===================================================================
9--- gcc-4_5-branch.orig/gcc/config.gcc 2010-12-23 00:33:39.000000000 -0800
10+++ gcc-4_5-branch/gcc/config.gcc 2011-01-09 02:57:36.608656002 -0800
11@@ -2321,11 +2321,12 @@
12 if test "$sh_multilibs" = "default" ; then
13 case ${target} in
14 sh64-superh-linux* | \
15- sh[1234]*) sh_multilibs=${sh_cpu_target} ;;
16 sh64* | sh5*) sh_multilibs=m5-32media,m5-32media-nofpu,m5-compact,m5-compact-nofpu,m5-64media,m5-64media-nofpu ;;
17- sh-superh-*) sh_multilibs=m4,m4-single,m4-single-only,m4-nofpu ;;
18+ sh-superh-* | \
19+ sh4-*-linux*) sh_multilibs=m4,m4-nofpu ;;
20 sh*-*-linux*) sh_multilibs=m1,m3e,m4 ;;
21 sh*-*-netbsd*) sh_multilibs=m3,m3e,m4 ;;
22+ sh-superh-*) sh_multilibs=m4,m4-single,m4-single-only,m4-nofpu ;;
23 *) sh_multilibs=m1,m2,m2e,m4,m4-single,m4-single-only,m2a,m2a-single ;;
24 esac
25 if test x$with_fp = xno; then
diff --git a/recipes-devtools/gcc/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch b/recipes-devtools/gcc/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch
new file mode 100644
index 000000000..9ae01c3fc
--- /dev/null
+++ b/recipes-devtools/gcc/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch
@@ -0,0 +1,33 @@
1# by default c++ include directories are not relative to "--sysroot"
2# which brings one trouble when using the toolchain in an environment
3# where the build directory generating that toolchain doesn't exist,
4# e.g. in sstate, machine specific sysroot and relocatable SDK
5# toolchain. This patch now enables c++ include paths under sysroot.
6# This way it's enough as long as "--sysroot" is correctly enabled
7# in the new environment.
8#
9# Signed-off-by Kevin Tian <kevin.tian@intel.com>, 2010-12-30
10
11diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c
12index 5024f48..9b47d1c 100644
13--- a/gcc/cppdefault.c
14+++ b/gcc/cppdefault.c
15@@ -48,15 +48,15 @@ const struct default_include cpp_include_defaults[]
16 = {
17 #ifdef GPLUSPLUS_INCLUDE_DIR
18 /* Pick up GNU C++ generic include files. */
19- { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0, 0 },
20+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 1, 0 },
21 #endif
22 #ifdef GPLUSPLUS_TOOL_INCLUDE_DIR
23 /* Pick up GNU C++ target-dependent include files. */
24- { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, 0, 1 },
25+ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, 1, 1 },
26 #endif
27 #ifdef GPLUSPLUS_BACKWARD_INCLUDE_DIR
28 /* Pick up GNU C++ backward and deprecated include files. */
29- { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, 0, 0 },
30+ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, 1, 0 },
31 #endif
32 #ifdef LOCAL_INCLUDE_DIR
33 /* /usr/local/include comes before the fixincluded header files. */