summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKhem Raj <raj.khem@gmail.com>2011-03-12 05:31:52 -0800
committerKoen Kooi <koen@dominion.thruhere.net>2011-03-12 16:20:55 +0100
commit154d33a2149fc80e435085ce08d97162c7ef2a0b (patch)
treeed5d2c9872a4650ff38cac05cc0afa56e6eb07ae
parent6d9070a43ab436a9d490e2f384db05ea7b1649fc (diff)
downloadmeta-openembedded-154d33a2149fc80e435085ce08d97162c7ef2a0b.tar.gz
gcc-4.5: Sync from OE
Remove unneeded patches. This should bring all the changes from OE uptodate. Now we are left with syncing the changes from oe-core then we will ready to push it into oe-core. Signed-off-by: Khem Raj <raj.khem@gmail.com> Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
-rw-r--r--recipes-devtools/gcc/gcc-4.5.inc81
-rw-r--r--recipes-devtools/gcc/gcc-4.5/103-uclibc-conf-noupstream.patch15
-rw-r--r--recipes-devtools/gcc/gcc-4.5/200-uclibc-locale.patch2840
-rw-r--r--recipes-devtools/gcc/gcc-4.5/203-uclibc-locale-no__x.patch233
-rw-r--r--recipes-devtools/gcc/gcc-4.5/204-uclibc-locale-wchar_fix.patch48
-rw-r--r--recipes-devtools/gcc/gcc-4.5/205-uclibc-locale-update.patch519
-rw-r--r--recipes-devtools/gcc/gcc-4.5/301-missing-execinfo_h.patch13
-rw-r--r--recipes-devtools/gcc/gcc-4.5/302-c99-snprintf.patch13
-rw-r--r--recipes-devtools/gcc/gcc-4.5/303-c99-complex-ugly-hack.patch14
-rw-r--r--recipes-devtools/gcc/gcc-4.5/304-index_macro.patch28
-rw-r--r--recipes-devtools/gcc/gcc-4.5/305-libmudflap-susv3-legacy.patch49
-rw-r--r--recipes-devtools/gcc/gcc-4.5/306-libstdc++-namespace.patch38
-rw-r--r--recipes-devtools/gcc/gcc-4.5/307-locale_facets.patch19
-rw-r--r--recipes-devtools/gcc/gcc-4.5/arm-bswapsi2.patch13
-rw-r--r--recipes-devtools/gcc/gcc-4.5/arm-lib1funcs.as-fix-mismatch-between-conditions-of-an-IT-block.patch18
-rw-r--r--recipes-devtools/gcc/gcc-4.5/arm-nolibfloat.patch24
-rw-r--r--recipes-devtools/gcc/gcc-4.5/arm-softfloat.patch16
-rw-r--r--recipes-devtools/gcc/gcc-4.5/gcc-4.3.3-SYSROOT_CFLAGS_FOR_TARGET.patch114
-rw-r--r--recipes-devtools/gcc/gcc-4.5/gcc-arm-frename-registers.patch25
-rw-r--r--recipes-devtools/gcc/gcc-4.5/gcc-linaro-fix-lp-653316.patch130
-rw-r--r--recipes-devtools/gcc/gcc-4.5/gcc-vmovl-PR45805.patch27
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99351.patch20
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99352.patch11
-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-r99464.patch157
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99465.patch94
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99466.patch38
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch811
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch409
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch3346
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch4217
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99478.patch74
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99479.patch101
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99480.patch64
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99481.patch40
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99482.patch84
-rw-r--r--recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99483.patch63
-rw-r--r--recipes-devtools/gcc/gcc-4.5/more-epilogues.patch83
-rw-r--r--recipes-devtools/gcc/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch33
39 files changed, 9656 insertions, 4413 deletions
diff --git a/recipes-devtools/gcc/gcc-4.5.inc b/recipes-devtools/gcc/gcc-4.5.inc
index e0a184ff22..52fca37015 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 = "168622" 15SRCREV = "170880"
16PV = "4.5" 16PV = "4.5"
17INC_PR = "r31" 17INC_PR = "r32"
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
@@ -29,13 +29,14 @@ PR_append = "+svnr${SRCPV}"
29SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \ 29SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \
30 file://gcc-4.3.1-ARCH_FLAGS_FOR_TARGET.patch \ 30 file://gcc-4.3.1-ARCH_FLAGS_FOR_TARGET.patch \
31 file://100-uclibc-conf.patch \ 31 file://100-uclibc-conf.patch \
32 file://gcc-uclibc-locale-ctype_touplow_t.patch \ 32 file://gcc-uclibc-locale-ctype_touplow_t.patch \
33 file://cache-amnesia.patch \ 33 file://cache-amnesia.patch \
34 file://gcc-flags-for-build.patch \ 34 file://gcc-flags-for-build.patch \
35 file://libstdc++-emit-__cxa_end_cleanup-in-text.patch \ 35 file://libstdc++-emit-__cxa_end_cleanup-in-text.patch \
36 file://arm-bswapsi2.patch \
37 file://Makefile.in.patch \ 36 file://Makefile.in.patch \
38 file://gcc-armv4-pass-fix-v4bx-to-ld.patch \ 37 file://gcc-armv4-pass-fix-v4bx-to-ld.patch \
38 file://sh4-multilib.patch \
39 file://arm-lib1funcs.as-fix-mismatch-between-conditions-of-an-IT-block.patch \
39 file://linaro/gcc-4.5-linaro-r99297.patch \ 40 file://linaro/gcc-4.5-linaro-r99297.patch \
40 file://linaro/gcc-4.5-linaro-r99298.patch \ 41 file://linaro/gcc-4.5-linaro-r99298.patch \
41 file://linaro/gcc-4.5-linaro-r99299.patch \ 42 file://linaro/gcc-4.5-linaro-r99299.patch \
@@ -156,55 +157,63 @@ SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \
156 file://linaro/gcc-4.5-linaro-r99442.patch \ 157 file://linaro/gcc-4.5-linaro-r99442.patch \
157 file://linaro/gcc-4.5-linaro-r99443.patch \ 158 file://linaro/gcc-4.5-linaro-r99443.patch \
158 file://linaro/gcc-4.5-linaro-r99444.patch \ 159 file://linaro/gcc-4.5-linaro-r99444.patch \
159 file://linaro/gcc-4.5-linaro-r99448.patch \ 160 file://linaro/gcc-4.5-linaro-r99449.patch \
160 file://linaro/gcc-4.5-linaro-r99449.patch \ 161 file://linaro/gcc-4.5-linaro-r99450.patch \
161 file://linaro/gcc-4.5-linaro-r99450.patch \ 162 file://linaro/gcc-4.5-linaro-r99451.patch \
162 file://linaro/gcc-4.5-linaro-r99451.patch \ 163 file://linaro/gcc-4.5-linaro-r99452.patch \
163 file://linaro/gcc-4.5-linaro-r99452.patch \ 164 file://linaro/gcc-4.5-linaro-r99453.patch \
164 file://linaro/gcc-4.5-linaro-r99453.patch \ 165 file://linaro/gcc-4.5-linaro-r99454.patch \
165 file://linaro/gcc-4.5-linaro-r99454.patch \ 166 file://linaro/gcc-4.5-linaro-r99455.patch \
166 file://linaro/gcc-4.5-linaro-r99455.patch \ 167 file://linaro/gcc-4.5-linaro-r99464.patch \
168 file://linaro/gcc-4.5-linaro-r99465.patch \
169 file://linaro/gcc-4.5-linaro-r99466.patch \
170 file://linaro/gcc-4.5-linaro-r99468.patch \
171 file://linaro/gcc-4.5-linaro-r99473.patch \
172 file://linaro/gcc-4.5-linaro-r99474.patch \
173 file://linaro/gcc-4.5-linaro-r99475.patch \
174 file://linaro/gcc-4.5-linaro-r99478.patch \
175 file://linaro/gcc-4.5-linaro-r99479.patch \
176 file://linaro/gcc-4.5-linaro-r99480.patch \
177 file://linaro/gcc-4.5-linaro-r99481.patch \
178 file://linaro/gcc-4.5-linaro-r99482.patch \
179 file://linaro/gcc-4.5-linaro-r99483.patch \
180 file://more-epilogues.patch \
167 file://gcc-scalar-widening-pr45847.patch \ 181 file://gcc-scalar-widening-pr45847.patch \
168 file://gcc-arm-volatile-bitfield-fix.patch \ 182 file://gcc-arm-volatile-bitfield-fix.patch \
169 \ 183 \
170 file://optional_libstdc.patch \ 184 file://optional_libstdc.patch \
171 file://64bithack.patch \ 185 file://64bithack.patch \
172 file://GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch \ 186 file://GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch \
173 " 187 "
174
175SRC_URI_append_sh3 = " file://sh3-installfix-fixheaders.patch;patch=1 "
176 188
177# Language Overrides 189# Language Overrides
178FORTRAN = "" 190FORTRAN = ""
179JAVA = "" 191JAVA = ""
180 192
181rename_srcdir (){ 193S = "${WORKDIR}/${BRANCH}"
182 mv ${WORKDIR}/${BRANCH} ${WORKDIR}/gcc-${PV}
183}
184
185do_unpack_append() {
186 bb.build.exec_func('rename_srcdir', d)
187}
188 194
189#EXTRA_OECONF_BASE = " --enable-cheaders=c_std \ 195#EXTRA_OECONF_BASE = " --enable-cheaders=c_std \
190# --enable-libssp \ 196# --enable-libssp \
191# --disable-bootstrap \ 197# --disable-bootstrap \
192# --disable-libgomp \ 198# --disable-libgomp \
193# --disable-libmudflap" 199# --disable-libmudflap"
194EXTRA_OECONF_BASE = " --enable-lto \ 200EXTRA_OECONF_BASE = "--enable-lto \
195 --enable-libssp \ 201 --enable-libssp \
196 --disable-bootstrap \ 202 --disable-bootstrap \
197 --disable-libgomp \ 203 --disable-libgomp \
198 --disable-libmudflap \ 204 --disable-libmudflap \
199 --enable-cheaders=c_global " 205 --enable-cheaders=c_global "
200 206
201EXTRA_OECONF_INITIAL = "--disable-libmudflap \ 207EXTRA_OECONF_INITIAL = "--disable-libmudflap \
202 --disable-libgomp \ 208 --disable-libgomp \
203 --disable-libssp \ 209 --disable-libssp \
204 --enable-decimal-float=no" 210 --enable-decimal-float=no"
205 211
206EXTRA_OECONF_INTERMEDIATE = "--disable-libmudflap \ 212EXTRA_OECONF_INTERMEDIATE = "--disable-libmudflap \
207 --disable-libgomp \ 213 --disable-libgomp \
208 --disable-libssp" 214 --disable-libssp"
209 215
210EXTRA_OECONF_append_libc-uclibc = " --disable-decimal-float " 216EXTRA_OECONF_append_libc-uclibc = " --disable-decimal-float "
217EXTRA_OECONF_append_mips64 = " --with-arch-64=mips64 --with-tune-64=mips64"
218EXTRA_OECONF_append_mips64el = " --with-arch-64=mips64 --with-tune-64=mips64"
219
diff --git a/recipes-devtools/gcc/gcc-4.5/103-uclibc-conf-noupstream.patch b/recipes-devtools/gcc/gcc-4.5/103-uclibc-conf-noupstream.patch
deleted file mode 100644
index f9d8ad9252..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/103-uclibc-conf-noupstream.patch
+++ /dev/null
@@ -1,15 +0,0 @@
1Corrects sub machine arch corectly
2
3Index: gcc-4.5.0/gcc/config.gcc
4===================================================================
5--- gcc-4.5.0.orig/gcc/config.gcc 2010-06-25 10:17:43.809880847 -0700
6+++ gcc-4.5.0/gcc/config.gcc 2010-06-25 10:38:09.689882136 -0700
7@@ -2171,7 +2171,7 @@
8 ;;
9 sh-*-elf* | sh[12346l]*-*-elf* | \
10 sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
11- sh-*-linux* | sh[2346lbe]*-*-linux* | \
12+ sh*-*-linux* | sh[2346lbe]*-*-linux* | \
13 sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
14 sh64-*-netbsd* | sh64l*-*-netbsd*)
15 tmake_file="${tmake_file} sh/t-sh sh/t-elf"
diff --git a/recipes-devtools/gcc/gcc-4.5/200-uclibc-locale.patch b/recipes-devtools/gcc/gcc-4.5/200-uclibc-locale.patch
deleted file mode 100644
index 32de11fc74..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/200-uclibc-locale.patch
+++ /dev/null
@@ -1,2840 +0,0 @@
1Index: gcc-4.5.0/libstdc++-v3/acinclude.m4
2===================================================================
3--- gcc-4.5.0.orig/libstdc++-v3/acinclude.m4 2010-04-05 18:27:44.000000000 -0700
4+++ gcc-4.5.0/libstdc++-v3/acinclude.m4 2010-06-25 10:42:34.913881064 -0700
5@@ -1703,7 +1703,7 @@
6 AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
7 GLIBCXX_ENABLE(clocale,auto,[@<:@=MODEL@:>@],
8 [use MODEL for target locale package],
9- [permit generic|gnu|ieee_1003.1-2001|yes|no|auto])
10+ [permit generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto])
11
12 # Deal with gettext issues. Default to not using it (=no) until we detect
13 # support for it later. Let the user turn it off via --e/d, but let that
14@@ -1724,6 +1724,9 @@
15 # Default to "generic".
16 if test $enable_clocale_flag = auto; then
17 case ${target_os} in
18+ *-uclibc*)
19+ enable_clocale_flag=uclibc
20+ ;;
21 linux* | gnu* | kfreebsd*-gnu | knetbsd*-gnu)
22 enable_clocale_flag=gnu
23 ;;
24@@ -1895,6 +1898,40 @@
25 CTIME_CC=config/locale/generic/time_members.cc
26 CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
27 ;;
28+ uclibc)
29+ AC_MSG_RESULT(uclibc)
30+
31+ # Declare intention to use gettext, and add support for specific
32+ # languages.
33+ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
34+ ALL_LINGUAS="de fr"
35+
36+ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
37+ AC_CHECK_PROG(check_msgfmt, msgfmt, yes, no)
38+ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
39+ USE_NLS=yes
40+ fi
41+ # Export the build objects.
42+ for ling in $ALL_LINGUAS; do \
43+ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
44+ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
45+ done
46+ AC_SUBST(glibcxx_MOFILES)
47+ AC_SUBST(glibcxx_POFILES)
48+
49+ CLOCALE_H=config/locale/uclibc/c_locale.h
50+ CLOCALE_CC=config/locale/uclibc/c_locale.cc
51+ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
52+ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
53+ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
54+ CMESSAGES_H=config/locale/uclibc/messages_members.h
55+ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
56+ CMONEY_CC=config/locale/uclibc/monetary_members.cc
57+ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
58+ CTIME_H=config/locale/uclibc/time_members.h
59+ CTIME_CC=config/locale/uclibc/time_members.cc
60+ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
61+ ;;
62 esac
63
64 # This is where the testsuite looks for locale catalogs, using the
65Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/c++locale_internal.h
66===================================================================
67--- /dev/null 1970-01-01 00:00:00.000000000 +0000
68+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2010-06-25 10:42:34.913881064 -0700
69@@ -0,0 +1,63 @@
70+// Prototypes for GLIBC thread locale __-prefixed functions -*- C++ -*-
71+
72+// Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
73+//
74+// This file is part of the GNU ISO C++ Library. This library is free
75+// software; you can redistribute it and/or modify it under the
76+// terms of the GNU General Public License as published by the
77+// Free Software Foundation; either version 2, or (at your option)
78+// any later version.
79+
80+// This library is distributed in the hope that it will be useful,
81+// but WITHOUT ANY WARRANTY; without even the implied warranty of
82+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83+// GNU General Public License for more details.
84+
85+// You should have received a copy of the GNU General Public License along
86+// with this library; see the file COPYING. If not, write to the Free
87+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
88+// USA.
89+
90+// As a special exception, you may use this file as part of a free software
91+// library without restriction. Specifically, if other files instantiate
92+// templates or use macros or inline functions from this file, or you compile
93+// this file and link it with other files to produce an executable, this
94+// file does not by itself cause the resulting executable to be covered by
95+// the GNU General Public License. This exception does not however
96+// invalidate any other reasons why the executable file might be covered by
97+// the GNU General Public License.
98+
99+// Written by Jakub Jelinek <jakub@redhat.com>
100+
101+#include <bits/c++config.h>
102+#include <clocale>
103+
104+#ifdef __UCLIBC_MJN3_ONLY__
105+#warning clean this up
106+#endif
107+
108+#ifdef __UCLIBC_HAS_XLOCALE__
109+
110+extern "C" __typeof(nl_langinfo_l) __nl_langinfo_l;
111+extern "C" __typeof(strcoll_l) __strcoll_l;
112+extern "C" __typeof(strftime_l) __strftime_l;
113+extern "C" __typeof(strtod_l) __strtod_l;
114+extern "C" __typeof(strtof_l) __strtof_l;
115+extern "C" __typeof(strtold_l) __strtold_l;
116+extern "C" __typeof(strxfrm_l) __strxfrm_l;
117+extern "C" __typeof(newlocale) __newlocale;
118+extern "C" __typeof(freelocale) __freelocale;
119+extern "C" __typeof(duplocale) __duplocale;
120+extern "C" __typeof(uselocale) __uselocale;
121+
122+#ifdef _GLIBCXX_USE_WCHAR_T
123+extern "C" __typeof(iswctype_l) __iswctype_l;
124+extern "C" __typeof(towlower_l) __towlower_l;
125+extern "C" __typeof(towupper_l) __towupper_l;
126+extern "C" __typeof(wcscoll_l) __wcscoll_l;
127+extern "C" __typeof(wcsftime_l) __wcsftime_l;
128+extern "C" __typeof(wcsxfrm_l) __wcsxfrm_l;
129+extern "C" __typeof(wctype_l) __wctype_l;
130+#endif
131+
132+#endif // GLIBC 2.3 and later
133Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/c_locale.cc
134===================================================================
135--- /dev/null 1970-01-01 00:00:00.000000000 +0000
136+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/c_locale.cc 2010-06-25 10:42:34.913881064 -0700
137@@ -0,0 +1,160 @@
138+// Wrapper for underlying C-language localization -*- C++ -*-
139+
140+// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
141+//
142+// This file is part of the GNU ISO C++ Library. This library is free
143+// software; you can redistribute it and/or modify it under the
144+// terms of the GNU General Public License as published by the
145+// Free Software Foundation; either version 2, or (at your option)
146+// any later version.
147+
148+// This library is distributed in the hope that it will be useful,
149+// but WITHOUT ANY WARRANTY; without even the implied warranty of
150+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151+// GNU General Public License for more details.
152+
153+// You should have received a copy of the GNU General Public License along
154+// with this library; see the file COPYING. If not, write to the Free
155+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
156+// USA.
157+
158+// As a special exception, you may use this file as part of a free software
159+// library without restriction. Specifically, if other files instantiate
160+// templates or use macros or inline functions from this file, or you compile
161+// this file and link it with other files to produce an executable, this
162+// file does not by itself cause the resulting executable to be covered by
163+// the GNU General Public License. This exception does not however
164+// invalidate any other reasons why the executable file might be covered by
165+// the GNU General Public License.
166+
167+//
168+// ISO C++ 14882: 22.8 Standard locale categories.
169+//
170+
171+// Written by Benjamin Kosnik <bkoz@redhat.com>
172+
173+#include <cerrno> // For errno
174+#include <locale>
175+#include <stdexcept>
176+#include <langinfo.h>
177+#include <bits/c++locale_internal.h>
178+
179+#ifndef __UCLIBC_HAS_XLOCALE__
180+#define __strtol_l(S, E, B, L) strtol((S), (E), (B))
181+#define __strtoul_l(S, E, B, L) strtoul((S), (E), (B))
182+#define __strtoll_l(S, E, B, L) strtoll((S), (E), (B))
183+#define __strtoull_l(S, E, B, L) strtoull((S), (E), (B))
184+#define __strtof_l(S, E, L) strtof((S), (E))
185+#define __strtod_l(S, E, L) strtod((S), (E))
186+#define __strtold_l(S, E, L) strtold((S), (E))
187+#warning should dummy __newlocale check for C|POSIX ?
188+#define __newlocale(a, b, c) NULL
189+#define __freelocale(a) ((void)0)
190+#define __duplocale(a) __c_locale()
191+#endif
192+
193+namespace std
194+{
195+ template<>
196+ void
197+ __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
198+ const __c_locale& __cloc)
199+ {
200+ if (!(__err & ios_base::failbit))
201+ {
202+ char* __sanity;
203+ errno = 0;
204+ float __f = __strtof_l(__s, &__sanity, __cloc);
205+ if (__sanity != __s && errno != ERANGE)
206+ __v = __f;
207+ else
208+ __err |= ios_base::failbit;
209+ }
210+ }
211+
212+ template<>
213+ void
214+ __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
215+ const __c_locale& __cloc)
216+ {
217+ if (!(__err & ios_base::failbit))
218+ {
219+ char* __sanity;
220+ errno = 0;
221+ double __d = __strtod_l(__s, &__sanity, __cloc);
222+ if (__sanity != __s && errno != ERANGE)
223+ __v = __d;
224+ else
225+ __err |= ios_base::failbit;
226+ }
227+ }
228+
229+ template<>
230+ void
231+ __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
232+ const __c_locale& __cloc)
233+ {
234+ if (!(__err & ios_base::failbit))
235+ {
236+ char* __sanity;
237+ errno = 0;
238+ long double __ld = __strtold_l(__s, &__sanity, __cloc);
239+ if (__sanity != __s && errno != ERANGE)
240+ __v = __ld;
241+ else
242+ __err |= ios_base::failbit;
243+ }
244+ }
245+
246+ void
247+ locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
248+ __c_locale __old)
249+ {
250+ __cloc = __newlocale(1 << LC_ALL, __s, __old);
251+#ifdef __UCLIBC_HAS_XLOCALE__
252+ if (!__cloc)
253+ {
254+ // This named locale is not supported by the underlying OS.
255+ __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
256+ "name not valid"));
257+ }
258+#endif
259+ }
260+
261+ void
262+ locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
263+ {
264+ if (_S_get_c_locale() != __cloc)
265+ __freelocale(__cloc);
266+ }
267+
268+ __c_locale
269+ locale::facet::_S_clone_c_locale(__c_locale& __cloc)
270+ { return __duplocale(__cloc); }
271+} // namespace std
272+
273+namespace __gnu_cxx
274+{
275+ const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
276+ {
277+ "LC_CTYPE",
278+ "LC_NUMERIC",
279+ "LC_TIME",
280+ "LC_COLLATE",
281+ "LC_MONETARY",
282+ "LC_MESSAGES",
283+#if _GLIBCXX_NUM_CATEGORIES != 0
284+ "LC_PAPER",
285+ "LC_NAME",
286+ "LC_ADDRESS",
287+ "LC_TELEPHONE",
288+ "LC_MEASUREMENT",
289+ "LC_IDENTIFICATION"
290+#endif
291+ };
292+}
293+
294+namespace std
295+{
296+ const char* const* const locale::_S_categories = __gnu_cxx::category_names;
297+} // namespace std
298Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/c_locale.h
299===================================================================
300--- /dev/null 1970-01-01 00:00:00.000000000 +0000
301+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/c_locale.h 2010-06-25 10:42:34.913881064 -0700
302@@ -0,0 +1,117 @@
303+// Wrapper for underlying C-language localization -*- C++ -*-
304+
305+// Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
306+//
307+// This file is part of the GNU ISO C++ Library. This library is free
308+// software; you can redistribute it and/or modify it under the
309+// terms of the GNU General Public License as published by the
310+// Free Software Foundation; either version 2, or (at your option)
311+// any later version.
312+
313+// This library is distributed in the hope that it will be useful,
314+// but WITHOUT ANY WARRANTY; without even the implied warranty of
315+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
316+// GNU General Public License for more details.
317+
318+// You should have received a copy of the GNU General Public License along
319+// with this library; see the file COPYING. If not, write to the Free
320+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
321+// USA.
322+
323+// As a special exception, you may use this file as part of a free software
324+// library without restriction. Specifically, if other files instantiate
325+// templates or use macros or inline functions from this file, or you compile
326+// this file and link it with other files to produce an executable, this
327+// file does not by itself cause the resulting executable to be covered by
328+// the GNU General Public License. This exception does not however
329+// invalidate any other reasons why the executable file might be covered by
330+// the GNU General Public License.
331+
332+//
333+// ISO C++ 14882: 22.8 Standard locale categories.
334+//
335+
336+// Written by Benjamin Kosnik <bkoz@redhat.com>
337+
338+#ifndef _C_LOCALE_H
339+#define _C_LOCALE_H 1
340+
341+#pragma GCC system_header
342+
343+#include <cstring> // get std::strlen
344+#include <cstdio> // get std::snprintf or std::sprintf
345+#include <clocale>
346+#include <langinfo.h> // For codecvt
347+#ifdef __UCLIBC_MJN3_ONLY__
348+#warning fix this
349+#endif
350+#ifdef __UCLIBC_HAS_LOCALE__
351+#include <iconv.h> // For codecvt using iconv, iconv_t
352+#endif
353+#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
354+#include <libintl.h> // For messages
355+#endif
356+
357+#ifdef __UCLIBC_MJN3_ONLY__
358+#warning what is _GLIBCXX_C_LOCALE_GNU for
359+#endif
360+#define _GLIBCXX_C_LOCALE_GNU 1
361+
362+#ifdef __UCLIBC_MJN3_ONLY__
363+#warning fix categories
364+#endif
365+// #define _GLIBCXX_NUM_CATEGORIES 6
366+#define _GLIBCXX_NUM_CATEGORIES 0
367+
368+#ifdef __UCLIBC_HAS_XLOCALE__
369+namespace __gnu_cxx
370+{
371+ extern "C" __typeof(uselocale) __uselocale;
372+}
373+#endif
374+
375+namespace std
376+{
377+#ifdef __UCLIBC_HAS_XLOCALE__
378+ typedef __locale_t __c_locale;
379+#else
380+ typedef int* __c_locale;
381+#endif
382+
383+ // Convert numeric value of type _Tv to string and return length of
384+ // string. If snprintf is available use it, otherwise fall back to
385+ // the unsafe sprintf which, in general, can be dangerous and should
386+ // be avoided.
387+ template<typename _Tv>
388+ int
389+ __convert_from_v(char* __out,
390+ const int __size __attribute__ ((__unused__)),
391+ const char* __fmt,
392+#ifdef __UCLIBC_HAS_XCLOCALE__
393+ _Tv __v, const __c_locale& __cloc, int __prec)
394+ {
395+ __c_locale __old = __gnu_cxx::__uselocale(__cloc);
396+#else
397+ _Tv __v, const __c_locale&, int __prec)
398+ {
399+# ifdef __UCLIBC_HAS_LOCALE__
400+ char* __old = std::setlocale(LC_ALL, NULL);
401+ char* __sav = new char[std::strlen(__old) + 1];
402+ std::strcpy(__sav, __old);
403+ std::setlocale(LC_ALL, "C");
404+# endif
405+#endif
406+
407+ const int __ret = std::snprintf(__out, __size, __fmt, __prec, __v);
408+
409+#ifdef __UCLIBC_HAS_XCLOCALE__
410+ __gnu_cxx::__uselocale(__old);
411+#elif defined __UCLIBC_HAS_LOCALE__
412+ std::setlocale(LC_ALL, __sav);
413+ delete [] __sav;
414+#endif
415+ return __ret;
416+ }
417+}
418+
419+#endif
420Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/codecvt_members.cc
421===================================================================
422--- /dev/null 1970-01-01 00:00:00.000000000 +0000
423+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/codecvt_members.cc 2010-06-25 10:42:34.913881064 -0700
424@@ -0,0 +1,308 @@
425+// std::codecvt implementation details, GNU version -*- C++ -*-
426+
427+// Copyright (C) 2002, 2003 Free Software Foundation, Inc.
428+//
429+// This file is part of the GNU ISO C++ Library. This library is free
430+// software; you can redistribute it and/or modify it under the
431+// terms of the GNU General Public License as published by the
432+// Free Software Foundation; either version 2, or (at your option)
433+// any later version.
434+
435+// This library is distributed in the hope that it will be useful,
436+// but WITHOUT ANY WARRANTY; without even the implied warranty of
437+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
438+// GNU General Public License for more details.
439+
440+// You should have received a copy of the GNU General Public License along
441+// with this library; see the file COPYING. If not, write to the Free
442+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
443+// USA.
444+
445+// As a special exception, you may use this file as part of a free software
446+// library without restriction. Specifically, if other files instantiate
447+// templates or use macros or inline functions from this file, or you compile
448+// this file and link it with other files to produce an executable, this
449+// file does not by itself cause the resulting executable to be covered by
450+// the GNU General Public License. This exception does not however
451+// invalidate any other reasons why the executable file might be covered by
452+// the GNU General Public License.
453+
454+//
455+// ISO C++ 14882: 22.2.1.5 - Template class codecvt
456+//
457+
458+// Written by Benjamin Kosnik <bkoz@redhat.com>
459+
460+#include <locale>
461+#include <cstdlib> // For MB_CUR_MAX
462+#include <climits> // For MB_LEN_MAX
463+#include <bits/c++locale_internal.h>
464+
465+namespace std
466+{
467+ // Specializations.
468+#ifdef _GLIBCXX_USE_WCHAR_T
469+ codecvt_base::result
470+ codecvt<wchar_t, char, mbstate_t>::
471+ do_out(state_type& __state, const intern_type* __from,
472+ const intern_type* __from_end, const intern_type*& __from_next,
473+ extern_type* __to, extern_type* __to_end,
474+ extern_type*& __to_next) const
475+ {
476+ result __ret = ok;
477+ state_type __tmp_state(__state);
478+
479+#ifdef __UCLIBC_HAS_XLOCALE__
480+ __c_locale __old = __uselocale(_M_c_locale_codecvt);
481+#endif
482+
483+ // wcsnrtombs is *very* fast but stops if encounters NUL characters:
484+ // in case we fall back to wcrtomb and then continue, in a loop.
485+ // NB: wcsnrtombs is a GNU extension
486+ for (__from_next = __from, __to_next = __to;
487+ __from_next < __from_end && __to_next < __to_end
488+ && __ret == ok;)
489+ {
490+ const intern_type* __from_chunk_end = wmemchr(__from_next, L'\0',
491+ __from_end - __from_next);
492+ if (!__from_chunk_end)
493+ __from_chunk_end = __from_end;
494+
495+ __from = __from_next;
496+ const size_t __conv = wcsnrtombs(__to_next, &__from_next,
497+ __from_chunk_end - __from_next,
498+ __to_end - __to_next, &__state);
499+ if (__conv == static_cast<size_t>(-1))
500+ {
501+ // In case of error, in order to stop at the exact place we
502+ // have to start again from the beginning with a series of
503+ // wcrtomb.
504+ for (; __from < __from_next; ++__from)
505+ __to_next += wcrtomb(__to_next, *__from, &__tmp_state);
506+ __state = __tmp_state;
507+ __ret = error;
508+ }
509+ else if (__from_next && __from_next < __from_chunk_end)
510+ {
511+ __to_next += __conv;
512+ __ret = partial;
513+ }
514+ else
515+ {
516+ __from_next = __from_chunk_end;
517+ __to_next += __conv;
518+ }
519+
520+ if (__from_next < __from_end && __ret == ok)
521+ {
522+ extern_type __buf[MB_LEN_MAX];
523+ __tmp_state = __state;
524+ const size_t __conv = wcrtomb(__buf, *__from_next, &__tmp_state);
525+ if (__conv > static_cast<size_t>(__to_end - __to_next))
526+ __ret = partial;
527+ else
528+ {
529+ memcpy(__to_next, __buf, __conv);
530+ __state = __tmp_state;
531+ __to_next += __conv;
532+ ++__from_next;
533+ }
534+ }
535+ }
536+
537+#ifdef __UCLIBC_HAS_XLOCALE__
538+ __uselocale(__old);
539+#endif
540+
541+ return __ret;
542+ }
543+
544+ codecvt_base::result
545+ codecvt<wchar_t, char, mbstate_t>::
546+ do_in(state_type& __state, const extern_type* __from,
547+ const extern_type* __from_end, const extern_type*& __from_next,
548+ intern_type* __to, intern_type* __to_end,
549+ intern_type*& __to_next) const
550+ {
551+ result __ret = ok;
552+ state_type __tmp_state(__state);
553+
554+#ifdef __UCLIBC_HAS_XLOCALE__
555+ __c_locale __old = __uselocale(_M_c_locale_codecvt);
556+#endif
557+
558+ // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
559+ // in case we store a L'\0' and then continue, in a loop.
560+ // NB: mbsnrtowcs is a GNU extension
561+ for (__from_next = __from, __to_next = __to;
562+ __from_next < __from_end && __to_next < __to_end
563+ && __ret == ok;)
564+ {
565+ const extern_type* __from_chunk_end;
566+ __from_chunk_end = static_cast<const extern_type*>(memchr(__from_next, '\0',
567+ __from_end
568+ - __from_next));
569+ if (!__from_chunk_end)
570+ __from_chunk_end = __from_end;
571+
572+ __from = __from_next;
573+ size_t __conv = mbsnrtowcs(__to_next, &__from_next,
574+ __from_chunk_end - __from_next,
575+ __to_end - __to_next, &__state);
576+ if (__conv == static_cast<size_t>(-1))
577+ {
578+ // In case of error, in order to stop at the exact place we
579+ // have to start again from the beginning with a series of
580+ // mbrtowc.
581+ for (;; ++__to_next, __from += __conv)
582+ {
583+ __conv = mbrtowc(__to_next, __from, __from_end - __from,
584+ &__tmp_state);
585+ if (__conv == static_cast<size_t>(-1)
586+ || __conv == static_cast<size_t>(-2))
587+ break;
588+ }
589+ __from_next = __from;
590+ __state = __tmp_state;
591+ __ret = error;
592+ }
593+ else if (__from_next && __from_next < __from_chunk_end)
594+ {
595+ // It is unclear what to return in this case (see DR 382).
596+ __to_next += __conv;
597+ __ret = partial;
598+ }
599+ else
600+ {
601+ __from_next = __from_chunk_end;
602+ __to_next += __conv;
603+ }
604+
605+ if (__from_next < __from_end && __ret == ok)
606+ {
607+ if (__to_next < __to_end)
608+ {
609+ // XXX Probably wrong for stateful encodings
610+ __tmp_state = __state;
611+ ++__from_next;
612+ *__to_next++ = L'\0';
613+ }
614+ else
615+ __ret = partial;
616+ }
617+ }
618+
619+#ifdef __UCLIBC_HAS_XLOCALE__
620+ __uselocale(__old);
621+#endif
622+
623+ return __ret;
624+ }
625+
626+ int
627+ codecvt<wchar_t, char, mbstate_t>::
628+ do_encoding() const throw()
629+ {
630+ // XXX This implementation assumes that the encoding is
631+ // stateless and is either single-byte or variable-width.
632+ int __ret = 0;
633+#ifdef __UCLIBC_HAS_XLOCALE__
634+ __c_locale __old = __uselocale(_M_c_locale_codecvt);
635+#endif
636+ if (MB_CUR_MAX == 1)
637+ __ret = 1;
638+#ifdef __UCLIBC_HAS_XLOCALE__
639+ __uselocale(__old);
640+#endif
641+ return __ret;
642+ }
643+
644+ int
645+ codecvt<wchar_t, char, mbstate_t>::
646+ do_max_length() const throw()
647+ {
648+#ifdef __UCLIBC_HAS_XLOCALE__
649+ __c_locale __old = __uselocale(_M_c_locale_codecvt);
650+#endif
651+ // XXX Probably wrong for stateful encodings.
652+ int __ret = MB_CUR_MAX;
653+#ifdef __UCLIBC_HAS_XLOCALE__
654+ __uselocale(__old);
655+#endif
656+ return __ret;
657+ }
658+
659+ int
660+ codecvt<wchar_t, char, mbstate_t>::
661+ do_length(state_type& __state, const extern_type* __from,
662+ const extern_type* __end, size_t __max) const
663+ {
664+ int __ret = 0;
665+ state_type __tmp_state(__state);
666+
667+#ifdef __UCLIBC_HAS_XLOCALE__
668+ __c_locale __old = __uselocale(_M_c_locale_codecvt);
669+#endif
670+
671+ // mbsnrtowcs is *very* fast but stops if encounters NUL characters:
672+ // in case we advance past it and then continue, in a loop.
673+ // NB: mbsnrtowcs is a GNU extension
674+
675+ // A dummy internal buffer is needed in order for mbsnrtocws to consider
676+ // its fourth parameter (it wouldn't with NULL as first parameter).
677+ wchar_t* __to = static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t)
678+ * __max));
679+ while (__from < __end && __max)
680+ {
681+ const extern_type* __from_chunk_end;
682+ __from_chunk_end = static_cast<const extern_type*>(memchr(__from, '\0',
683+ __end
684+ - __from));
685+ if (!__from_chunk_end)
686+ __from_chunk_end = __end;
687+
688+ const extern_type* __tmp_from = __from;
689+ size_t __conv = mbsnrtowcs(__to, &__from,
690+ __from_chunk_end - __from,
691+ __max, &__state);
692+ if (__conv == static_cast<size_t>(-1))
693+ {
694+ // In case of error, in order to stop at the exact place we
695+ // have to start again from the beginning with a series of
696+ // mbrtowc.
697+ for (__from = __tmp_from;; __from += __conv)
698+ {
699+ __conv = mbrtowc(NULL, __from, __end - __from,
700+ &__tmp_state);
701+ if (__conv == static_cast<size_t>(-1)
702+ || __conv == static_cast<size_t>(-2))
703+ break;
704+ }
705+ __state = __tmp_state;
706+ __ret += __from - __tmp_from;
707+ break;
708+ }
709+ if (!__from)
710+ __from = __from_chunk_end;
711+
712+ __ret += __from - __tmp_from;
713+ __max -= __conv;
714+
715+ if (__from < __end && __max)
716+ {
717+ // XXX Probably wrong for stateful encodings
718+ __tmp_state = __state;
719+ ++__from;
720+ ++__ret;
721+ --__max;
722+ }
723+ }
724+
725+#ifdef __UCLIBC_HAS_XLOCALE__
726+ __uselocale(__old);
727+#endif
728+
729+ return __ret;
730+ }
731+#endif
732+}
733Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/collate_members.cc
734===================================================================
735--- /dev/null 1970-01-01 00:00:00.000000000 +0000
736+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/collate_members.cc 2010-06-25 10:42:34.913881064 -0700
737@@ -0,0 +1,80 @@
738+// std::collate implementation details, GNU version -*- C++ -*-
739+
740+// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
741+//
742+// This file is part of the GNU ISO C++ Library. This library is free
743+// software; you can redistribute it and/or modify it under the
744+// terms of the GNU General Public License as published by the
745+// Free Software Foundation; either version 2, or (at your option)
746+// any later version.
747+
748+// This library is distributed in the hope that it will be useful,
749+// but WITHOUT ANY WARRANTY; without even the implied warranty of
750+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
751+// GNU General Public License for more details.
752+
753+// You should have received a copy of the GNU General Public License along
754+// with this library; see the file COPYING. If not, write to the Free
755+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
756+// USA.
757+
758+// As a special exception, you may use this file as part of a free software
759+// library without restriction. Specifically, if other files instantiate
760+// templates or use macros or inline functions from this file, or you compile
761+// this file and link it with other files to produce an executable, this
762+// file does not by itself cause the resulting executable to be covered by
763+// the GNU General Public License. This exception does not however
764+// invalidate any other reasons why the executable file might be covered by
765+// the GNU General Public License.
766+
767+//
768+// ISO C++ 14882: 22.2.4.1.2 collate virtual functions
769+//
770+
771+// Written by Benjamin Kosnik <bkoz@redhat.com>
772+
773+#include <locale>
774+#include <bits/c++locale_internal.h>
775+
776+#ifndef __UCLIBC_HAS_XLOCALE__
777+#define __strcoll_l(S1, S2, L) strcoll((S1), (S2))
778+#define __strxfrm_l(S1, S2, N, L) strxfrm((S1), (S2), (N))
779+#define __wcscoll_l(S1, S2, L) wcscoll((S1), (S2))
780+#define __wcsxfrm_l(S1, S2, N, L) wcsxfrm((S1), (S2), (N))
781+#endif
782+
783+namespace std
784+{
785+ // These are basically extensions to char_traits, and perhaps should
786+ // be put there instead of here.
787+ template<>
788+ int
789+ collate<char>::_M_compare(const char* __one, const char* __two) const
790+ {
791+ int __cmp = __strcoll_l(__one, __two, _M_c_locale_collate);
792+ return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
793+ }
794+
795+ template<>
796+ size_t
797+ collate<char>::_M_transform(char* __to, const char* __from,
798+ size_t __n) const
799+ { return __strxfrm_l(__to, __from, __n, _M_c_locale_collate); }
800+
801+#ifdef _GLIBCXX_USE_WCHAR_T
802+ template<>
803+ int
804+ collate<wchar_t>::_M_compare(const wchar_t* __one,
805+ const wchar_t* __two) const
806+ {
807+ int __cmp = __wcscoll_l(__one, __two, _M_c_locale_collate);
808+ return (__cmp >> (8 * sizeof (int) - 2)) | (__cmp != 0);
809+ }
810+
811+ template<>
812+ size_t
813+ collate<wchar_t>::_M_transform(wchar_t* __to, const wchar_t* __from,
814+ size_t __n) const
815+ { return __wcsxfrm_l(__to, __from, __n, _M_c_locale_collate); }
816+#endif
817+}
818Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/ctype_members.cc
819===================================================================
820--- /dev/null 1970-01-01 00:00:00.000000000 +0000
821+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/ctype_members.cc 2010-06-25 10:42:34.913881064 -0700
822@@ -0,0 +1,300 @@
823+// std::ctype implementation details, GNU version -*- C++ -*-
824+
825+// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
826+//
827+// This file is part of the GNU ISO C++ Library. This library is free
828+// software; you can redistribute it and/or modify it under the
829+// terms of the GNU General Public License as published by the
830+// Free Software Foundation; either version 2, or (at your option)
831+// any later version.
832+
833+// This library is distributed in the hope that it will be useful,
834+// but WITHOUT ANY WARRANTY; without even the implied warranty of
835+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
836+// GNU General Public License for more details.
837+
838+// You should have received a copy of the GNU General Public License along
839+// with this library; see the file COPYING. If not, write to the Free
840+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
841+// USA.
842+
843+// As a special exception, you may use this file as part of a free software
844+// library without restriction. Specifically, if other files instantiate
845+// templates or use macros or inline functions from this file, or you compile
846+// this file and link it with other files to produce an executable, this
847+// file does not by itself cause the resulting executable to be covered by
848+// the GNU General Public License. This exception does not however
849+// invalidate any other reasons why the executable file might be covered by
850+// the GNU General Public License.
851+
852+//
853+// ISO C++ 14882: 22.2.1.1.2 ctype virtual functions.
854+//
855+
856+// Written by Benjamin Kosnik <bkoz@redhat.com>
857+
858+#define _LIBC
859+#include <locale>
860+#undef _LIBC
861+#include <bits/c++locale_internal.h>
862+
863+#ifndef __UCLIBC_HAS_XLOCALE__
864+#define __wctype_l(S, L) wctype((S))
865+#define __towupper_l(C, L) towupper((C))
866+#define __towlower_l(C, L) towlower((C))
867+#define __iswctype_l(C, M, L) iswctype((C), (M))
868+#endif
869+
870+namespace std
871+{
872+ // NB: The other ctype<char> specializations are in src/locale.cc and
873+ // various /config/os/* files.
874+ template<>
875+ ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
876+ : ctype<char>(0, false, __refs)
877+ {
878+ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
879+ {
880+ this->_S_destroy_c_locale(this->_M_c_locale_ctype);
881+ this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
882+#ifdef __UCLIBC_HAS_XLOCALE__
883+ this->_M_toupper = this->_M_c_locale_ctype->__ctype_toupper;
884+ this->_M_tolower = this->_M_c_locale_ctype->__ctype_tolower;
885+ this->_M_table = this->_M_c_locale_ctype->__ctype_b;
886+#endif
887+ }
888+ }
889+
890+#ifdef _GLIBCXX_USE_WCHAR_T
891+ ctype<wchar_t>::__wmask_type
892+ ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const
893+ {
894+ __wmask_type __ret;
895+ switch (__m)
896+ {
897+ case space:
898+ __ret = __wctype_l("space", _M_c_locale_ctype);
899+ break;
900+ case print:
901+ __ret = __wctype_l("print", _M_c_locale_ctype);
902+ break;
903+ case cntrl:
904+ __ret = __wctype_l("cntrl", _M_c_locale_ctype);
905+ break;
906+ case upper:
907+ __ret = __wctype_l("upper", _M_c_locale_ctype);
908+ break;
909+ case lower:
910+ __ret = __wctype_l("lower", _M_c_locale_ctype);
911+ break;
912+ case alpha:
913+ __ret = __wctype_l("alpha", _M_c_locale_ctype);
914+ break;
915+ case digit:
916+ __ret = __wctype_l("digit", _M_c_locale_ctype);
917+ break;
918+ case punct:
919+ __ret = __wctype_l("punct", _M_c_locale_ctype);
920+ break;
921+ case xdigit:
922+ __ret = __wctype_l("xdigit", _M_c_locale_ctype);
923+ break;
924+ case alnum:
925+ __ret = __wctype_l("alnum", _M_c_locale_ctype);
926+ break;
927+ case graph:
928+ __ret = __wctype_l("graph", _M_c_locale_ctype);
929+ break;
930+ default:
931+ __ret = __wmask_type();
932+ }
933+ return __ret;
934+ }
935+
936+ wchar_t
937+ ctype<wchar_t>::do_toupper(wchar_t __c) const
938+ { return __towupper_l(__c, _M_c_locale_ctype); }
939+
940+ const wchar_t*
941+ ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
942+ {
943+ while (__lo < __hi)
944+ {
945+ *__lo = __towupper_l(*__lo, _M_c_locale_ctype);
946+ ++__lo;
947+ }
948+ return __hi;
949+ }
950+
951+ wchar_t
952+ ctype<wchar_t>::do_tolower(wchar_t __c) const
953+ { return __towlower_l(__c, _M_c_locale_ctype); }
954+
955+ const wchar_t*
956+ ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
957+ {
958+ while (__lo < __hi)
959+ {
960+ *__lo = __towlower_l(*__lo, _M_c_locale_ctype);
961+ ++__lo;
962+ }
963+ return __hi;
964+ }
965+
966+ bool
967+ ctype<wchar_t>::
968+ do_is(mask __m, wchar_t __c) const
969+ {
970+ // Highest bitmask in ctype_base == 10, but extra in "C"
971+ // library for blank.
972+ bool __ret = false;
973+ const size_t __bitmasksize = 11;
974+ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
975+ if (__m & _M_bit[__bitcur]
976+ && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
977+ {
978+ __ret = true;
979+ break;
980+ }
981+ return __ret;
982+ }
983+
984+ const wchar_t*
985+ ctype<wchar_t>::
986+ do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
987+ {
988+ for (; __lo < __hi; ++__vec, ++__lo)
989+ {
990+ // Highest bitmask in ctype_base == 10, but extra in "C"
991+ // library for blank.
992+ const size_t __bitmasksize = 11;
993+ mask __m = 0;
994+ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
995+ if (__iswctype_l(*__lo, _M_wmask[__bitcur], _M_c_locale_ctype))
996+ __m |= _M_bit[__bitcur];
997+ *__vec = __m;
998+ }
999+ return __hi;
1000+ }
1001+
1002+ const wchar_t*
1003+ ctype<wchar_t>::
1004+ do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
1005+ {
1006+ while (__lo < __hi && !this->do_is(__m, *__lo))
1007+ ++__lo;
1008+ return __lo;
1009+ }
1010+
1011+ const wchar_t*
1012+ ctype<wchar_t>::
1013+ do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
1014+ {
1015+ while (__lo < __hi && this->do_is(__m, *__lo) != 0)
1016+ ++__lo;
1017+ return __lo;
1018+ }
1019+
1020+ wchar_t
1021+ ctype<wchar_t>::
1022+ do_widen(char __c) const
1023+ { return _M_widen[static_cast<unsigned char>(__c)]; }
1024+
1025+ const char*
1026+ ctype<wchar_t>::
1027+ do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
1028+ {
1029+ while (__lo < __hi)
1030+ {
1031+ *__dest = _M_widen[static_cast<unsigned char>(*__lo)];
1032+ ++__lo;
1033+ ++__dest;
1034+ }
1035+ return __hi;
1036+ }
1037+
1038+ char
1039+ ctype<wchar_t>::
1040+ do_narrow(wchar_t __wc, char __dfault) const
1041+ {
1042+ if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
1043+ return _M_narrow[__wc];
1044+#ifdef __UCLIBC_HAS_XLOCALE__
1045+ __c_locale __old = __uselocale(_M_c_locale_ctype);
1046+#endif
1047+ const int __c = wctob(__wc);
1048+#ifdef __UCLIBC_HAS_XLOCALE__
1049+ __uselocale(__old);
1050+#endif
1051+ return (__c == EOF ? __dfault : static_cast<char>(__c));
1052+ }
1053+
1054+ const wchar_t*
1055+ ctype<wchar_t>::
1056+ do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
1057+ char* __dest) const
1058+ {
1059+#ifdef __UCLIBC_HAS_XLOCALE__
1060+ __c_locale __old = __uselocale(_M_c_locale_ctype);
1061+#endif
1062+ if (_M_narrow_ok)
1063+ while (__lo < __hi)
1064+ {
1065+ if (*__lo >= 0 && *__lo < 128)
1066+ *__dest = _M_narrow[*__lo];
1067+ else
1068+ {
1069+ const int __c = wctob(*__lo);
1070+ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
1071+ }
1072+ ++__lo;
1073+ ++__dest;
1074+ }
1075+ else
1076+ while (__lo < __hi)
1077+ {
1078+ const int __c = wctob(*__lo);
1079+ *__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
1080+ ++__lo;
1081+ ++__dest;
1082+ }
1083+#ifdef __UCLIBC_HAS_XLOCALE__
1084+ __uselocale(__old);
1085+#endif
1086+ return __hi;
1087+ }
1088+
1089+ void
1090+ ctype<wchar_t>::_M_initialize_ctype()
1091+ {
1092+#ifdef __UCLIBC_HAS_XLOCALE__
1093+ __c_locale __old = __uselocale(_M_c_locale_ctype);
1094+#endif
1095+ wint_t __i;
1096+ for (__i = 0; __i < 128; ++__i)
1097+ {
1098+ const int __c = wctob(__i);
1099+ if (__c == EOF)
1100+ break;
1101+ else
1102+ _M_narrow[__i] = static_cast<char>(__c);
1103+ }
1104+ if (__i == 128)
1105+ _M_narrow_ok = true;
1106+ else
1107+ _M_narrow_ok = false;
1108+ for (size_t __j = 0;
1109+ __j < sizeof(_M_widen) / sizeof(wint_t); ++__j)
1110+ _M_widen[__j] = btowc(__j);
1111+
1112+ for (size_t __k = 0; __k <= 11; ++__k)
1113+ {
1114+ _M_bit[__k] = static_cast<mask>(_ISbit(__k));
1115+ _M_wmask[__k] = _M_convert_to_wmask(_M_bit[__k]);
1116+ }
1117+#ifdef __UCLIBC_HAS_XLOCALE__
1118+ __uselocale(__old);
1119+#endif
1120+ }
1121+#endif // _GLIBCXX_USE_WCHAR_T
1122+}
1123Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/messages_members.cc
1124===================================================================
1125--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1126+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/messages_members.cc 2010-06-25 10:42:34.913881064 -0700
1127@@ -0,0 +1,100 @@
1128+// std::messages implementation details, GNU version -*- C++ -*-
1129+
1130+// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
1131+//
1132+// This file is part of the GNU ISO C++ Library. This library is free
1133+// software; you can redistribute it and/or modify it under the
1134+// terms of the GNU General Public License as published by the
1135+// Free Software Foundation; either version 2, or (at your option)
1136+// any later version.
1137+
1138+// This library is distributed in the hope that it will be useful,
1139+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1140+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1141+// GNU General Public License for more details.
1142+
1143+// You should have received a copy of the GNU General Public License along
1144+// with this library; see the file COPYING. If not, write to the Free
1145+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
1146+// USA.
1147+
1148+// As a special exception, you may use this file as part of a free software
1149+// library without restriction. Specifically, if other files instantiate
1150+// templates or use macros or inline functions from this file, or you compile
1151+// this file and link it with other files to produce an executable, this
1152+// file does not by itself cause the resulting executable to be covered by
1153+// the GNU General Public License. This exception does not however
1154+// invalidate any other reasons why the executable file might be covered by
1155+// the GNU General Public License.
1156+
1157+//
1158+// ISO C++ 14882: 22.2.7.1.2 messages virtual functions
1159+//
1160+
1161+// Written by Benjamin Kosnik <bkoz@redhat.com>
1162+
1163+#include <locale>
1164+#include <bits/c++locale_internal.h>
1165+
1166+#ifdef __UCLIBC_MJN3_ONLY__
1167+#warning fix gettext stuff
1168+#endif
1169+#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
1170+extern "C" char *__dcgettext(const char *domainname,
1171+ const char *msgid, int category);
1172+#undef gettext
1173+#define gettext(msgid) __dcgettext(NULL, msgid, LC_MESSAGES)
1174+#else
1175+#undef gettext
1176+#define gettext(msgid) (msgid)
1177+#endif
1178+
1179+namespace std
1180+{
1181+ // Specializations.
1182+ template<>
1183+ string
1184+ messages<char>::do_get(catalog, int, int, const string& __dfault) const
1185+ {
1186+#ifdef __UCLIBC_HAS_XLOCALE__
1187+ __c_locale __old = __uselocale(_M_c_locale_messages);
1188+ const char* __msg = const_cast<const char*>(gettext(__dfault.c_str()));
1189+ __uselocale(__old);
1190+ return string(__msg);
1191+#elif defined __UCLIBC_HAS_LOCALE__
1192+ char* __old = strdup(setlocale(LC_ALL, NULL));
1193+ setlocale(LC_ALL, _M_name_messages);
1194+ const char* __msg = gettext(__dfault.c_str());
1195+ setlocale(LC_ALL, __old);
1196+ free(__old);
1197+ return string(__msg);
1198+#else
1199+ const char* __msg = gettext(__dfault.c_str());
1200+ return string(__msg);
1201+#endif
1202+ }
1203+
1204+#ifdef _GLIBCXX_USE_WCHAR_T
1205+ template<>
1206+ wstring
1207+ messages<wchar_t>::do_get(catalog, int, int, const wstring& __dfault) const
1208+ {
1209+# ifdef __UCLIBC_HAS_XLOCALE__
1210+ __c_locale __old = __uselocale(_M_c_locale_messages);
1211+ char* __msg = gettext(_M_convert_to_char(__dfault));
1212+ __uselocale(__old);
1213+ return _M_convert_from_char(__msg);
1214+# elif defined __UCLIBC_HAS_LOCALE__
1215+ char* __old = strdup(setlocale(LC_ALL, NULL));
1216+ setlocale(LC_ALL, _M_name_messages);
1217+ char* __msg = gettext(_M_convert_to_char(__dfault));
1218+ setlocale(LC_ALL, __old);
1219+ free(__old);
1220+ return _M_convert_from_char(__msg);
1221+# else
1222+ char* __msg = gettext(_M_convert_to_char(__dfault));
1223+ return _M_convert_from_char(__msg);
1224+# endif
1225+ }
1226+#endif
1227+}
1228Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/messages_members.h
1229===================================================================
1230--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1231+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/messages_members.h 2010-06-25 10:42:34.913881064 -0700
1232@@ -0,0 +1,118 @@
1233+// std::messages implementation details, GNU version -*- C++ -*-
1234+
1235+// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
1236+//
1237+// This file is part of the GNU ISO C++ Library. This library is free
1238+// software; you can redistribute it and/or modify it under the
1239+// terms of the GNU General Public License as published by the
1240+// Free Software Foundation; either version 2, or (at your option)
1241+// any later version.
1242+
1243+// This library is distributed in the hope that it will be useful,
1244+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1245+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1246+// GNU General Public License for more details.
1247+
1248+// You should have received a copy of the GNU General Public License along
1249+// with this library; see the file COPYING. If not, write to the Free
1250+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
1251+// USA.
1252+
1253+// As a special exception, you may use this file as part of a free software
1254+// library without restriction. Specifically, if other files instantiate
1255+// templates or use macros or inline functions from this file, or you compile
1256+// this file and link it with other files to produce an executable, this
1257+// file does not by itself cause the resulting executable to be covered by
1258+// the GNU General Public License. This exception does not however
1259+// invalidate any other reasons why the executable file might be covered by
1260+// the GNU General Public License.
1261+
1262+//
1263+// ISO C++ 14882: 22.2.7.1.2 messages functions
1264+//
1265+
1266+// Written by Benjamin Kosnik <bkoz@redhat.com>
1267+
1268+#ifdef __UCLIBC_MJN3_ONLY__
1269+#warning fix prototypes for *textdomain funcs
1270+#endif
1271+#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
1272+extern "C" char *__textdomain(const char *domainname);
1273+extern "C" char *__bindtextdomain(const char *domainname,
1274+ const char *dirname);
1275+#else
1276+#undef __textdomain
1277+#undef __bindtextdomain
1278+#define __textdomain(D) ((void)0)
1279+#define __bindtextdomain(D,P) ((void)0)
1280+#endif
1281+
1282+ // Non-virtual member functions.
1283+ template<typename _CharT>
1284+ messages<_CharT>::messages(size_t __refs)
1285+ : facet(__refs), _M_c_locale_messages(_S_get_c_locale()),
1286+ _M_name_messages(_S_get_c_name())
1287+ { }
1288+
1289+ template<typename _CharT>
1290+ messages<_CharT>::messages(__c_locale __cloc, const char* __s,
1291+ size_t __refs)
1292+ : facet(__refs), _M_c_locale_messages(_S_clone_c_locale(__cloc)),
1293+ _M_name_messages(__s)
1294+ {
1295+ char* __tmp = new char[std::strlen(__s) + 1];
1296+ std::strcpy(__tmp, __s);
1297+ _M_name_messages = __tmp;
1298+ }
1299+
1300+ template<typename _CharT>
1301+ typename messages<_CharT>::catalog
1302+ messages<_CharT>::open(const basic_string<char>& __s, const locale& __loc,
1303+ const char* __dir) const
1304+ {
1305+ __bindtextdomain(__s.c_str(), __dir);
1306+ return this->do_open(__s, __loc);
1307+ }
1308+
1309+ // Virtual member functions.
1310+ template<typename _CharT>
1311+ messages<_CharT>::~messages()
1312+ {
1313+ if (_M_name_messages != _S_get_c_name())
1314+ delete [] _M_name_messages;
1315+ _S_destroy_c_locale(_M_c_locale_messages);
1316+ }
1317+
1318+ template<typename _CharT>
1319+ typename messages<_CharT>::catalog
1320+ messages<_CharT>::do_open(const basic_string<char>& __s,
1321+ const locale&) const
1322+ {
1323+ // No error checking is done, assume the catalog exists and can
1324+ // be used.
1325+ __textdomain(__s.c_str());
1326+ return 0;
1327+ }
1328+
1329+ template<typename _CharT>
1330+ void
1331+ messages<_CharT>::do_close(catalog) const
1332+ { }
1333+
1334+ // messages_byname
1335+ template<typename _CharT>
1336+ messages_byname<_CharT>::messages_byname(const char* __s, size_t __refs)
1337+ : messages<_CharT>(__refs)
1338+ {
1339+ if (this->_M_name_messages != locale::facet::_S_get_c_name())
1340+ delete [] this->_M_name_messages;
1341+ char* __tmp = new char[std::strlen(__s) + 1];
1342+ std::strcpy(__tmp, __s);
1343+ this->_M_name_messages = __tmp;
1344+
1345+ if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
1346+ {
1347+ this->_S_destroy_c_locale(this->_M_c_locale_messages);
1348+ this->_S_create_c_locale(this->_M_c_locale_messages, __s);
1349+ }
1350+ }
1351Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/monetary_members.cc
1352===================================================================
1353--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1354+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2010-06-25 10:42:34.913881064 -0700
1355@@ -0,0 +1,692 @@
1356+// std::moneypunct implementation details, GNU version -*- C++ -*-
1357+
1358+// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
1359+//
1360+// This file is part of the GNU ISO C++ Library. This library is free
1361+// software; you can redistribute it and/or modify it under the
1362+// terms of the GNU General Public License as published by the
1363+// Free Software Foundation; either version 2, or (at your option)
1364+// any later version.
1365+
1366+// This library is distributed in the hope that it will be useful,
1367+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1368+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1369+// GNU General Public License for more details.
1370+
1371+// You should have received a copy of the GNU General Public License along
1372+// with this library; see the file COPYING. If not, write to the Free
1373+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
1374+// USA.
1375+
1376+// As a special exception, you may use this file as part of a free software
1377+// library without restriction. Specifically, if other files instantiate
1378+// templates or use macros or inline functions from this file, or you compile
1379+// this file and link it with other files to produce an executable, this
1380+// file does not by itself cause the resulting executable to be covered by
1381+// the GNU General Public License. This exception does not however
1382+// invalidate any other reasons why the executable file might be covered by
1383+// the GNU General Public License.
1384+
1385+//
1386+// ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions
1387+//
1388+
1389+// Written by Benjamin Kosnik <bkoz@redhat.com>
1390+
1391+#define _LIBC
1392+#include <locale>
1393+#undef _LIBC
1394+#include <bits/c++locale_internal.h>
1395+
1396+#ifdef __UCLIBC_MJN3_ONLY__
1397+#warning optimize this for uclibc
1398+#warning tailor for stub locale support
1399+#endif
1400+
1401+#ifndef __UCLIBC_HAS_XLOCALE__
1402+#define __nl_langinfo_l(N, L) nl_langinfo((N))
1403+#endif
1404+
1405+namespace std
1406+{
1407+ // Construct and return valid pattern consisting of some combination of:
1408+ // space none symbol sign value
1409+ money_base::pattern
1410+ money_base::_S_construct_pattern(char __precedes, char __space, char __posn)
1411+ {
1412+ pattern __ret;
1413+
1414+ // This insanely complicated routine attempts to construct a valid
1415+ // pattern for use with monyepunct. A couple of invariants:
1416+
1417+ // if (__precedes) symbol -> value
1418+ // else value -> symbol
1419+
1420+ // if (__space) space
1421+ // else none
1422+
1423+ // none == never first
1424+ // space never first or last
1425+
1426+ // Any elegant implementations of this are welcome.
1427+ switch (__posn)
1428+ {
1429+ case 0:
1430+ case 1:
1431+ // 1 The sign precedes the value and symbol.
1432+ __ret.field[0] = sign;
1433+ if (__space)
1434+ {
1435+ // Pattern starts with sign.
1436+ if (__precedes)
1437+ {
1438+ __ret.field[1] = symbol;
1439+ __ret.field[3] = value;
1440+ }
1441+ else
1442+ {
1443+ __ret.field[1] = value;
1444+ __ret.field[3] = symbol;
1445+ }
1446+ __ret.field[2] = space;
1447+ }
1448+ else
1449+ {
1450+ // Pattern starts with sign and ends with none.
1451+ if (__precedes)
1452+ {
1453+ __ret.field[1] = symbol;
1454+ __ret.field[2] = value;
1455+ }
1456+ else
1457+ {
1458+ __ret.field[1] = value;
1459+ __ret.field[2] = symbol;
1460+ }
1461+ __ret.field[3] = none;
1462+ }
1463+ break;
1464+ case 2:
1465+ // 2 The sign follows the value and symbol.
1466+ if (__space)
1467+ {
1468+ // Pattern either ends with sign.
1469+ if (__precedes)
1470+ {
1471+ __ret.field[0] = symbol;
1472+ __ret.field[2] = value;
1473+ }
1474+ else
1475+ {
1476+ __ret.field[0] = value;
1477+ __ret.field[2] = symbol;
1478+ }
1479+ __ret.field[1] = space;
1480+ __ret.field[3] = sign;
1481+ }
1482+ else
1483+ {
1484+ // Pattern ends with sign then none.
1485+ if (__precedes)
1486+ {
1487+ __ret.field[0] = symbol;
1488+ __ret.field[1] = value;
1489+ }
1490+ else
1491+ {
1492+ __ret.field[0] = value;
1493+ __ret.field[1] = symbol;
1494+ }
1495+ __ret.field[2] = sign;
1496+ __ret.field[3] = none;
1497+ }
1498+ break;
1499+ case 3:
1500+ // 3 The sign immediately precedes the symbol.
1501+ if (__precedes)
1502+ {
1503+ __ret.field[0] = sign;
1504+ __ret.field[1] = symbol;
1505+ if (__space)
1506+ {
1507+ __ret.field[2] = space;
1508+ __ret.field[3] = value;
1509+ }
1510+ else
1511+ {
1512+ __ret.field[2] = value;
1513+ __ret.field[3] = none;
1514+ }
1515+ }
1516+ else
1517+ {
1518+ __ret.field[0] = value;
1519+ if (__space)
1520+ {
1521+ __ret.field[1] = space;
1522+ __ret.field[2] = sign;
1523+ __ret.field[3] = symbol;
1524+ }
1525+ else
1526+ {
1527+ __ret.field[1] = sign;
1528+ __ret.field[2] = symbol;
1529+ __ret.field[3] = none;
1530+ }
1531+ }
1532+ break;
1533+ case 4:
1534+ // 4 The sign immediately follows the symbol.
1535+ if (__precedes)
1536+ {
1537+ __ret.field[0] = symbol;
1538+ __ret.field[1] = sign;
1539+ if (__space)
1540+ {
1541+ __ret.field[2] = space;
1542+ __ret.field[3] = value;
1543+ }
1544+ else
1545+ {
1546+ __ret.field[2] = value;
1547+ __ret.field[3] = none;
1548+ }
1549+ }
1550+ else
1551+ {
1552+ __ret.field[0] = value;
1553+ if (__space)
1554+ {
1555+ __ret.field[1] = space;
1556+ __ret.field[2] = symbol;
1557+ __ret.field[3] = sign;
1558+ }
1559+ else
1560+ {
1561+ __ret.field[1] = symbol;
1562+ __ret.field[2] = sign;
1563+ __ret.field[3] = none;
1564+ }
1565+ }
1566+ break;
1567+ default:
1568+ ;
1569+ }
1570+ return __ret;
1571+ }
1572+
1573+ template<>
1574+ void
1575+ moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc,
1576+ const char*)
1577+ {
1578+ if (!_M_data)
1579+ _M_data = new __moneypunct_cache<char, true>;
1580+
1581+ if (!__cloc)
1582+ {
1583+ // "C" locale
1584+ _M_data->_M_decimal_point = '.';
1585+ _M_data->_M_thousands_sep = ',';
1586+ _M_data->_M_grouping = "";
1587+ _M_data->_M_grouping_size = 0;
1588+ _M_data->_M_curr_symbol = "";
1589+ _M_data->_M_curr_symbol_size = 0;
1590+ _M_data->_M_positive_sign = "";
1591+ _M_data->_M_positive_sign_size = 0;
1592+ _M_data->_M_negative_sign = "";
1593+ _M_data->_M_negative_sign_size = 0;
1594+ _M_data->_M_frac_digits = 0;
1595+ _M_data->_M_pos_format = money_base::_S_default_pattern;
1596+ _M_data->_M_neg_format = money_base::_S_default_pattern;
1597+
1598+ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
1599+ _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
1600+ }
1601+ else
1602+ {
1603+ // Named locale.
1604+ _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
1605+ __cloc));
1606+ _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
1607+ __cloc));
1608+ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
1609+ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
1610+ _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
1611+ _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
1612+
1613+ char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
1614+ if (!__nposn)
1615+ _M_data->_M_negative_sign = "()";
1616+ else
1617+ _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
1618+ __cloc);
1619+ _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
1620+
1621+ // _Intl == true
1622+ _M_data->_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
1623+ _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
1624+ _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
1625+ __cloc));
1626+ char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
1627+ char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
1628+ char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
1629+ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
1630+ __pposn);
1631+ char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
1632+ char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
1633+ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
1634+ __nposn);
1635+ }
1636+ }
1637+
1638+ template<>
1639+ void
1640+ moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc,
1641+ const char*)
1642+ {
1643+ if (!_M_data)
1644+ _M_data = new __moneypunct_cache<char, false>;
1645+
1646+ if (!__cloc)
1647+ {
1648+ // "C" locale
1649+ _M_data->_M_decimal_point = '.';
1650+ _M_data->_M_thousands_sep = ',';
1651+ _M_data->_M_grouping = "";
1652+ _M_data->_M_grouping_size = 0;
1653+ _M_data->_M_curr_symbol = "";
1654+ _M_data->_M_curr_symbol_size = 0;
1655+ _M_data->_M_positive_sign = "";
1656+ _M_data->_M_positive_sign_size = 0;
1657+ _M_data->_M_negative_sign = "";
1658+ _M_data->_M_negative_sign_size = 0;
1659+ _M_data->_M_frac_digits = 0;
1660+ _M_data->_M_pos_format = money_base::_S_default_pattern;
1661+ _M_data->_M_neg_format = money_base::_S_default_pattern;
1662+
1663+ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
1664+ _M_data->_M_atoms[__i] = money_base::_S_atoms[__i];
1665+ }
1666+ else
1667+ {
1668+ // Named locale.
1669+ _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT,
1670+ __cloc));
1671+ _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP,
1672+ __cloc));
1673+ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
1674+ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
1675+ _M_data->_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
1676+ _M_data->_M_positive_sign_size = strlen(_M_data->_M_positive_sign);
1677+
1678+ char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
1679+ if (!__nposn)
1680+ _M_data->_M_negative_sign = "()";
1681+ else
1682+ _M_data->_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN,
1683+ __cloc);
1684+ _M_data->_M_negative_sign_size = strlen(_M_data->_M_negative_sign);
1685+
1686+ // _Intl == false
1687+ _M_data->_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
1688+ _M_data->_M_curr_symbol_size = strlen(_M_data->_M_curr_symbol);
1689+ _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
1690+ char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
1691+ char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
1692+ char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
1693+ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
1694+ __pposn);
1695+ char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
1696+ char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
1697+ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
1698+ __nposn);
1699+ }
1700+ }
1701+
1702+ template<>
1703+ moneypunct<char, true>::~moneypunct()
1704+ { delete _M_data; }
1705+
1706+ template<>
1707+ moneypunct<char, false>::~moneypunct()
1708+ { delete _M_data; }
1709+
1710+#ifdef _GLIBCXX_USE_WCHAR_T
1711+ template<>
1712+ void
1713+ moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc,
1714+#ifdef __UCLIBC_HAS_XLOCALE__
1715+ const char*)
1716+#else
1717+ const char* __name)
1718+#endif
1719+ {
1720+ if (!_M_data)
1721+ _M_data = new __moneypunct_cache<wchar_t, true>;
1722+
1723+ if (!__cloc)
1724+ {
1725+ // "C" locale
1726+ _M_data->_M_decimal_point = L'.';
1727+ _M_data->_M_thousands_sep = L',';
1728+ _M_data->_M_grouping = "";
1729+ _M_data->_M_grouping_size = 0;
1730+ _M_data->_M_curr_symbol = L"";
1731+ _M_data->_M_curr_symbol_size = 0;
1732+ _M_data->_M_positive_sign = L"";
1733+ _M_data->_M_positive_sign_size = 0;
1734+ _M_data->_M_negative_sign = L"";
1735+ _M_data->_M_negative_sign_size = 0;
1736+ _M_data->_M_frac_digits = 0;
1737+ _M_data->_M_pos_format = money_base::_S_default_pattern;
1738+ _M_data->_M_neg_format = money_base::_S_default_pattern;
1739+
1740+ // Use ctype::widen code without the facet...
1741+ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
1742+ _M_data->_M_atoms[__i] =
1743+ static_cast<wchar_t>(money_base::_S_atoms[__i]);
1744+ }
1745+ else
1746+ {
1747+ // Named locale.
1748+#ifdef __UCLIBC_HAS_XLOCALE__
1749+ __c_locale __old = __uselocale(__cloc);
1750+#else
1751+ // Switch to named locale so that mbsrtowcs will work.
1752+ char* __old = strdup(setlocale(LC_ALL, NULL));
1753+ setlocale(LC_ALL, __name);
1754+#endif
1755+
1756+#ifdef __UCLIBC_MJN3_ONLY__
1757+#warning fix this... should be monetary
1758+#endif
1759+#ifdef __UCLIBC__
1760+# ifdef __UCLIBC_HAS_XLOCALE__
1761+ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
1762+ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
1763+# else
1764+ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
1765+ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
1766+# endif
1767+#else
1768+ union { char *__s; wchar_t __w; } __u;
1769+ __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
1770+ _M_data->_M_decimal_point = __u.__w;
1771+
1772+ __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
1773+ _M_data->_M_thousands_sep = __u.__w;
1774+#endif
1775+ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
1776+ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
1777+
1778+ const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
1779+ const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
1780+ const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
1781+
1782+ wchar_t* __wcs_ps = 0;
1783+ wchar_t* __wcs_ns = 0;
1784+ const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
1785+ try
1786+ {
1787+ mbstate_t __state;
1788+ size_t __len = strlen(__cpossign);
1789+ if (__len)
1790+ {
1791+ ++__len;
1792+ memset(&__state, 0, sizeof(mbstate_t));
1793+ __wcs_ps = new wchar_t[__len];
1794+ mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
1795+ _M_data->_M_positive_sign = __wcs_ps;
1796+ }
1797+ else
1798+ _M_data->_M_positive_sign = L"";
1799+ _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
1800+
1801+ __len = strlen(__cnegsign);
1802+ if (!__nposn)
1803+ _M_data->_M_negative_sign = L"()";
1804+ else if (__len)
1805+ {
1806+ ++__len;
1807+ memset(&__state, 0, sizeof(mbstate_t));
1808+ __wcs_ns = new wchar_t[__len];
1809+ mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
1810+ _M_data->_M_negative_sign = __wcs_ns;
1811+ }
1812+ else
1813+ _M_data->_M_negative_sign = L"";
1814+ _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
1815+
1816+ // _Intl == true.
1817+ __len = strlen(__ccurr);
1818+ if (__len)
1819+ {
1820+ ++__len;
1821+ memset(&__state, 0, sizeof(mbstate_t));
1822+ wchar_t* __wcs = new wchar_t[__len];
1823+ mbsrtowcs(__wcs, &__ccurr, __len, &__state);
1824+ _M_data->_M_curr_symbol = __wcs;
1825+ }
1826+ else
1827+ _M_data->_M_curr_symbol = L"";
1828+ _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
1829+ }
1830+ catch (...)
1831+ {
1832+ delete _M_data;
1833+ _M_data = 0;
1834+ delete __wcs_ps;
1835+ delete __wcs_ns;
1836+#ifdef __UCLIBC_HAS_XLOCALE__
1837+ __uselocale(__old);
1838+#else
1839+ setlocale(LC_ALL, __old);
1840+ free(__old);
1841+#endif
1842+ __throw_exception_again;
1843+ }
1844+
1845+ _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
1846+ __cloc));
1847+ char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
1848+ char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
1849+ char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
1850+ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
1851+ __pposn);
1852+ char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
1853+ char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
1854+ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
1855+ __nposn);
1856+
1857+#ifdef __UCLIBC_HAS_XLOCALE__
1858+ __uselocale(__old);
1859+#else
1860+ setlocale(LC_ALL, __old);
1861+ free(__old);
1862+#endif
1863+ }
1864+ }
1865+
1866+ template<>
1867+ void
1868+ moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
1869+#ifdef __UCLIBC_HAS_XLOCALE__
1870+ const char*)
1871+#else
1872+ const char* __name)
1873+#endif
1874+ {
1875+ if (!_M_data)
1876+ _M_data = new __moneypunct_cache<wchar_t, false>;
1877+
1878+ if (!__cloc)
1879+ {
1880+ // "C" locale
1881+ _M_data->_M_decimal_point = L'.';
1882+ _M_data->_M_thousands_sep = L',';
1883+ _M_data->_M_grouping = "";
1884+ _M_data->_M_grouping_size = 0;
1885+ _M_data->_M_curr_symbol = L"";
1886+ _M_data->_M_curr_symbol_size = 0;
1887+ _M_data->_M_positive_sign = L"";
1888+ _M_data->_M_positive_sign_size = 0;
1889+ _M_data->_M_negative_sign = L"";
1890+ _M_data->_M_negative_sign_size = 0;
1891+ _M_data->_M_frac_digits = 0;
1892+ _M_data->_M_pos_format = money_base::_S_default_pattern;
1893+ _M_data->_M_neg_format = money_base::_S_default_pattern;
1894+
1895+ // Use ctype::widen code without the facet...
1896+ for (size_t __i = 0; __i < money_base::_S_end; ++__i)
1897+ _M_data->_M_atoms[__i] =
1898+ static_cast<wchar_t>(money_base::_S_atoms[__i]);
1899+ }
1900+ else
1901+ {
1902+ // Named locale.
1903+#ifdef __UCLIBC_HAS_XLOCALE__
1904+ __c_locale __old = __uselocale(__cloc);
1905+#else
1906+ // Switch to named locale so that mbsrtowcs will work.
1907+ char* __old = strdup(setlocale(LC_ALL, NULL));
1908+ setlocale(LC_ALL, __name);
1909+#endif
1910+
1911+#ifdef __UCLIBC_MJN3_ONLY__
1912+#warning fix this... should be monetary
1913+#endif
1914+#ifdef __UCLIBC__
1915+# ifdef __UCLIBC_HAS_XLOCALE__
1916+ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
1917+ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
1918+# else
1919+ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
1920+ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
1921+# endif
1922+#else
1923+ union { char *__s; wchar_t __w; } __u;
1924+ __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc);
1925+ _M_data->_M_decimal_point = __u.__w;
1926+
1927+ __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc);
1928+ _M_data->_M_thousands_sep = __u.__w;
1929+#endif
1930+ _M_data->_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
1931+ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
1932+
1933+ const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
1934+ const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
1935+ const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
1936+
1937+ wchar_t* __wcs_ps = 0;
1938+ wchar_t* __wcs_ns = 0;
1939+ const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
1940+ try
1941+ {
1942+ mbstate_t __state;
1943+ size_t __len;
1944+ __len = strlen(__cpossign);
1945+ if (__len)
1946+ {
1947+ ++__len;
1948+ memset(&__state, 0, sizeof(mbstate_t));
1949+ __wcs_ps = new wchar_t[__len];
1950+ mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
1951+ _M_data->_M_positive_sign = __wcs_ps;
1952+ }
1953+ else
1954+ _M_data->_M_positive_sign = L"";
1955+ _M_data->_M_positive_sign_size = wcslen(_M_data->_M_positive_sign);
1956+
1957+ __len = strlen(__cnegsign);
1958+ if (!__nposn)
1959+ _M_data->_M_negative_sign = L"()";
1960+ else if (__len)
1961+ {
1962+ ++__len;
1963+ memset(&__state, 0, sizeof(mbstate_t));
1964+ __wcs_ns = new wchar_t[__len];
1965+ mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
1966+ _M_data->_M_negative_sign = __wcs_ns;
1967+ }
1968+ else
1969+ _M_data->_M_negative_sign = L"";
1970+ _M_data->_M_negative_sign_size = wcslen(_M_data->_M_negative_sign);
1971+
1972+ // _Intl == true.
1973+ __len = strlen(__ccurr);
1974+ if (__len)
1975+ {
1976+ ++__len;
1977+ memset(&__state, 0, sizeof(mbstate_t));
1978+ wchar_t* __wcs = new wchar_t[__len];
1979+ mbsrtowcs(__wcs, &__ccurr, __len, &__state);
1980+ _M_data->_M_curr_symbol = __wcs;
1981+ }
1982+ else
1983+ _M_data->_M_curr_symbol = L"";
1984+ _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol);
1985+ }
1986+ catch (...)
1987+ {
1988+ delete _M_data;
1989+ _M_data = 0;
1990+ delete __wcs_ps;
1991+ delete __wcs_ns;
1992+#ifdef __UCLIBC_HAS_XLOCALE__
1993+ __uselocale(__old);
1994+#else
1995+ setlocale(LC_ALL, __old);
1996+ free(__old);
1997+#endif
1998+ __throw_exception_again;
1999+ }
2000+
2001+ _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
2002+ char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
2003+ char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
2004+ char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
2005+ _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace,
2006+ __pposn);
2007+ char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
2008+ char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
2009+ _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace,
2010+ __nposn);
2011+
2012+#ifdef __UCLIBC_HAS_XLOCALE__
2013+ __uselocale(__old);
2014+#else
2015+ setlocale(LC_ALL, __old);
2016+ free(__old);
2017+#endif
2018+ }
2019+ }
2020+
2021+ template<>
2022+ moneypunct<wchar_t, true>::~moneypunct()
2023+ {
2024+ if (_M_data->_M_positive_sign_size)
2025+ delete [] _M_data->_M_positive_sign;
2026+ if (_M_data->_M_negative_sign_size
2027+ && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
2028+ delete [] _M_data->_M_negative_sign;
2029+ if (_M_data->_M_curr_symbol_size)
2030+ delete [] _M_data->_M_curr_symbol;
2031+ delete _M_data;
2032+ }
2033+
2034+ template<>
2035+ moneypunct<wchar_t, false>::~moneypunct()
2036+ {
2037+ if (_M_data->_M_positive_sign_size)
2038+ delete [] _M_data->_M_positive_sign;
2039+ if (_M_data->_M_negative_sign_size
2040+ && wcscmp(_M_data->_M_negative_sign, L"()") != 0)
2041+ delete [] _M_data->_M_negative_sign;
2042+ if (_M_data->_M_curr_symbol_size)
2043+ delete [] _M_data->_M_curr_symbol;
2044+ delete _M_data;
2045+ }
2046+#endif
2047+}
2048Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/numeric_members.cc
2049===================================================================
2050--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2051+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2010-06-25 10:42:34.913881064 -0700
2052@@ -0,0 +1,160 @@
2053+// std::numpunct implementation details, GNU version -*- C++ -*-
2054+
2055+// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
2056+//
2057+// This file is part of the GNU ISO C++ Library. This library is free
2058+// software; you can redistribute it and/or modify it under the
2059+// terms of the GNU General Public License as published by the
2060+// Free Software Foundation; either version 2, or (at your option)
2061+// any later version.
2062+
2063+// This library is distributed in the hope that it will be useful,
2064+// but WITHOUT ANY WARRANTY; without even the implied warranty of
2065+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2066+// GNU General Public License for more details.
2067+
2068+// You should have received a copy of the GNU General Public License along
2069+// with this library; see the file COPYING. If not, write to the Free
2070+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2071+// USA.
2072+
2073+// As a special exception, you may use this file as part of a free software
2074+// library without restriction. Specifically, if other files instantiate
2075+// templates or use macros or inline functions from this file, or you compile
2076+// this file and link it with other files to produce an executable, this
2077+// file does not by itself cause the resulting executable to be covered by
2078+// the GNU General Public License. This exception does not however
2079+// invalidate any other reasons why the executable file might be covered by
2080+// the GNU General Public License.
2081+
2082+//
2083+// ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions
2084+//
2085+
2086+// Written by Benjamin Kosnik <bkoz@redhat.com>
2087+
2088+#define _LIBC
2089+#include <locale>
2090+#undef _LIBC
2091+#include <bits/c++locale_internal.h>
2092+
2093+#ifdef __UCLIBC_MJN3_ONLY__
2094+#warning tailor for stub locale support
2095+#endif
2096+#ifndef __UCLIBC_HAS_XLOCALE__
2097+#define __nl_langinfo_l(N, L) nl_langinfo((N))
2098+#endif
2099+
2100+namespace std
2101+{
2102+ template<>
2103+ void
2104+ numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
2105+ {
2106+ if (!_M_data)
2107+ _M_data = new __numpunct_cache<char>;
2108+
2109+ if (!__cloc)
2110+ {
2111+ // "C" locale
2112+ _M_data->_M_grouping = "";
2113+ _M_data->_M_grouping_size = 0;
2114+ _M_data->_M_use_grouping = false;
2115+
2116+ _M_data->_M_decimal_point = '.';
2117+ _M_data->_M_thousands_sep = ',';
2118+
2119+ for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
2120+ _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i];
2121+
2122+ for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
2123+ _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j];
2124+ }
2125+ else
2126+ {
2127+ // Named locale.
2128+ _M_data->_M_decimal_point = *(__nl_langinfo_l(DECIMAL_POINT,
2129+ __cloc));
2130+ _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSANDS_SEP,
2131+ __cloc));
2132+
2133+ // Check for NULL, which implies no grouping.
2134+ if (_M_data->_M_thousands_sep == '\0')
2135+ _M_data->_M_grouping = "";
2136+ else
2137+ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
2138+ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
2139+ }
2140+
2141+ // NB: There is no way to extact this info from posix locales.
2142+ // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
2143+ _M_data->_M_truename = "true";
2144+ _M_data->_M_truename_size = 4;
2145+ // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
2146+ _M_data->_M_falsename = "false";
2147+ _M_data->_M_falsename_size = 5;
2148+ }
2149+
2150+ template<>
2151+ numpunct<char>::~numpunct()
2152+ { delete _M_data; }
2153+
2154+#ifdef _GLIBCXX_USE_WCHAR_T
2155+ template<>
2156+ void
2157+ numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
2158+ {
2159+ if (!_M_data)
2160+ _M_data = new __numpunct_cache<wchar_t>;
2161+
2162+ if (!__cloc)
2163+ {
2164+ // "C" locale
2165+ _M_data->_M_grouping = "";
2166+ _M_data->_M_grouping_size = 0;
2167+ _M_data->_M_use_grouping = false;
2168+
2169+ _M_data->_M_decimal_point = L'.';
2170+ _M_data->_M_thousands_sep = L',';
2171+
2172+ // Use ctype::widen code without the facet...
2173+ for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
2174+ _M_data->_M_atoms_out[__i] =
2175+ static_cast<wchar_t>(__num_base::_S_atoms_out[__i]);
2176+
2177+ for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
2178+ _M_data->_M_atoms_in[__j] =
2179+ static_cast<wchar_t>(__num_base::_S_atoms_in[__j]);
2180+ }
2181+ else
2182+ {
2183+ // Named locale.
2184+ // NB: In the GNU model wchar_t is always 32 bit wide.
2185+ union { char *__s; wchar_t __w; } __u;
2186+ __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
2187+ _M_data->_M_decimal_point = __u.__w;
2188+
2189+ __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
2190+ _M_data->_M_thousands_sep = __u.__w;
2191+
2192+ if (_M_data->_M_thousands_sep == L'\0')
2193+ _M_data->_M_grouping = "";
2194+ else
2195+ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
2196+ _M_data->_M_grouping_size = strlen(_M_data->_M_grouping);
2197+ }
2198+
2199+ // NB: There is no way to extact this info from posix locales.
2200+ // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
2201+ _M_data->_M_truename = L"true";
2202+ _M_data->_M_truename_size = 4;
2203+ // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
2204+ _M_data->_M_falsename = L"false";
2205+ _M_data->_M_falsename_size = 5;
2206+ }
2207+
2208+ template<>
2209+ numpunct<wchar_t>::~numpunct()
2210+ { delete _M_data; }
2211+ #endif
2212+}
2213Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/time_members.cc
2214===================================================================
2215--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2216+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/time_members.cc 2010-06-25 10:42:34.913881064 -0700
2217@@ -0,0 +1,406 @@
2218+// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
2219+
2220+// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
2221+//
2222+// This file is part of the GNU ISO C++ Library. This library is free
2223+// software; you can redistribute it and/or modify it under the
2224+// terms of the GNU General Public License as published by the
2225+// Free Software Foundation; either version 2, or (at your option)
2226+// any later version.
2227+
2228+// This library is distributed in the hope that it will be useful,
2229+// but WITHOUT ANY WARRANTY; without even the implied warranty of
2230+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2231+// GNU General Public License for more details.
2232+
2233+// You should have received a copy of the GNU General Public License along
2234+// with this library; see the file COPYING. If not, write to the Free
2235+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2236+// USA.
2237+
2238+// As a special exception, you may use this file as part of a free software
2239+// library without restriction. Specifically, if other files instantiate
2240+// templates or use macros or inline functions from this file, or you compile
2241+// this file and link it with other files to produce an executable, this
2242+// file does not by itself cause the resulting executable to be covered by
2243+// the GNU General Public License. This exception does not however
2244+// invalidate any other reasons why the executable file might be covered by
2245+// the GNU General Public License.
2246+
2247+//
2248+// ISO C++ 14882: 22.2.5.1.2 - time_get virtual functions
2249+// ISO C++ 14882: 22.2.5.3.2 - time_put virtual functions
2250+//
2251+
2252+// Written by Benjamin Kosnik <bkoz@redhat.com>
2253+
2254+#include <locale>
2255+#include <bits/c++locale_internal.h>
2256+
2257+#ifdef __UCLIBC_MJN3_ONLY__
2258+#warning tailor for stub locale support
2259+#endif
2260+#ifndef __UCLIBC_HAS_XLOCALE__
2261+#define __nl_langinfo_l(N, L) nl_langinfo((N))
2262+#endif
2263+
2264+namespace std
2265+{
2266+ template<>
2267+ void
2268+ __timepunct<char>::
2269+ _M_put(char* __s, size_t __maxlen, const char* __format,
2270+ const tm* __tm) const
2271+ {
2272+#ifdef __UCLIBC_HAS_XLOCALE__
2273+ const size_t __len = __strftime_l(__s, __maxlen, __format, __tm,
2274+ _M_c_locale_timepunct);
2275+#else
2276+ char* __old = strdup(setlocale(LC_ALL, NULL));
2277+ setlocale(LC_ALL, _M_name_timepunct);
2278+ const size_t __len = strftime(__s, __maxlen, __format, __tm);
2279+ setlocale(LC_ALL, __old);
2280+ free(__old);
2281+#endif
2282+ // Make sure __s is null terminated.
2283+ if (__len == 0)
2284+ __s[0] = '\0';
2285+ }
2286+
2287+ template<>
2288+ void
2289+ __timepunct<char>::_M_initialize_timepunct(__c_locale __cloc)
2290+ {
2291+ if (!_M_data)
2292+ _M_data = new __timepunct_cache<char>;
2293+
2294+ if (!__cloc)
2295+ {
2296+ // "C" locale
2297+ _M_c_locale_timepunct = _S_get_c_locale();
2298+
2299+ _M_data->_M_date_format = "%m/%d/%y";
2300+ _M_data->_M_date_era_format = "%m/%d/%y";
2301+ _M_data->_M_time_format = "%H:%M:%S";
2302+ _M_data->_M_time_era_format = "%H:%M:%S";
2303+ _M_data->_M_date_time_format = "";
2304+ _M_data->_M_date_time_era_format = "";
2305+ _M_data->_M_am = "AM";
2306+ _M_data->_M_pm = "PM";
2307+ _M_data->_M_am_pm_format = "";
2308+
2309+ // Day names, starting with "C"'s Sunday.
2310+ _M_data->_M_day1 = "Sunday";
2311+ _M_data->_M_day2 = "Monday";
2312+ _M_data->_M_day3 = "Tuesday";
2313+ _M_data->_M_day4 = "Wednesday";
2314+ _M_data->_M_day5 = "Thursday";
2315+ _M_data->_M_day6 = "Friday";
2316+ _M_data->_M_day7 = "Saturday";
2317+
2318+ // Abbreviated day names, starting with "C"'s Sun.
2319+ _M_data->_M_aday1 = "Sun";
2320+ _M_data->_M_aday2 = "Mon";
2321+ _M_data->_M_aday3 = "Tue";
2322+ _M_data->_M_aday4 = "Wed";
2323+ _M_data->_M_aday5 = "Thu";
2324+ _M_data->_M_aday6 = "Fri";
2325+ _M_data->_M_aday7 = "Sat";
2326+
2327+ // Month names, starting with "C"'s January.
2328+ _M_data->_M_month01 = "January";
2329+ _M_data->_M_month02 = "February";
2330+ _M_data->_M_month03 = "March";
2331+ _M_data->_M_month04 = "April";
2332+ _M_data->_M_month05 = "May";
2333+ _M_data->_M_month06 = "June";
2334+ _M_data->_M_month07 = "July";
2335+ _M_data->_M_month08 = "August";
2336+ _M_data->_M_month09 = "September";
2337+ _M_data->_M_month10 = "October";
2338+ _M_data->_M_month11 = "November";
2339+ _M_data->_M_month12 = "December";
2340+
2341+ // Abbreviated month names, starting with "C"'s Jan.
2342+ _M_data->_M_amonth01 = "Jan";
2343+ _M_data->_M_amonth02 = "Feb";
2344+ _M_data->_M_amonth03 = "Mar";
2345+ _M_data->_M_amonth04 = "Apr";
2346+ _M_data->_M_amonth05 = "May";
2347+ _M_data->_M_amonth06 = "Jun";
2348+ _M_data->_M_amonth07 = "Jul";
2349+ _M_data->_M_amonth08 = "Aug";
2350+ _M_data->_M_amonth09 = "Sep";
2351+ _M_data->_M_amonth10 = "Oct";
2352+ _M_data->_M_amonth11 = "Nov";
2353+ _M_data->_M_amonth12 = "Dec";
2354+ }
2355+ else
2356+ {
2357+ _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
2358+
2359+ _M_data->_M_date_format = __nl_langinfo_l(D_FMT, __cloc);
2360+ _M_data->_M_date_era_format = __nl_langinfo_l(ERA_D_FMT, __cloc);
2361+ _M_data->_M_time_format = __nl_langinfo_l(T_FMT, __cloc);
2362+ _M_data->_M_time_era_format = __nl_langinfo_l(ERA_T_FMT, __cloc);
2363+ _M_data->_M_date_time_format = __nl_langinfo_l(D_T_FMT, __cloc);
2364+ _M_data->_M_date_time_era_format = __nl_langinfo_l(ERA_D_T_FMT,
2365+ __cloc);
2366+ _M_data->_M_am = __nl_langinfo_l(AM_STR, __cloc);
2367+ _M_data->_M_pm = __nl_langinfo_l(PM_STR, __cloc);
2368+ _M_data->_M_am_pm_format = __nl_langinfo_l(T_FMT_AMPM, __cloc);
2369+
2370+ // Day names, starting with "C"'s Sunday.
2371+ _M_data->_M_day1 = __nl_langinfo_l(DAY_1, __cloc);
2372+ _M_data->_M_day2 = __nl_langinfo_l(DAY_2, __cloc);
2373+ _M_data->_M_day3 = __nl_langinfo_l(DAY_3, __cloc);
2374+ _M_data->_M_day4 = __nl_langinfo_l(DAY_4, __cloc);
2375+ _M_data->_M_day5 = __nl_langinfo_l(DAY_5, __cloc);
2376+ _M_data->_M_day6 = __nl_langinfo_l(DAY_6, __cloc);
2377+ _M_data->_M_day7 = __nl_langinfo_l(DAY_7, __cloc);
2378+
2379+ // Abbreviated day names, starting with "C"'s Sun.
2380+ _M_data->_M_aday1 = __nl_langinfo_l(ABDAY_1, __cloc);
2381+ _M_data->_M_aday2 = __nl_langinfo_l(ABDAY_2, __cloc);
2382+ _M_data->_M_aday3 = __nl_langinfo_l(ABDAY_3, __cloc);
2383+ _M_data->_M_aday4 = __nl_langinfo_l(ABDAY_4, __cloc);
2384+ _M_data->_M_aday5 = __nl_langinfo_l(ABDAY_5, __cloc);
2385+ _M_data->_M_aday6 = __nl_langinfo_l(ABDAY_6, __cloc);
2386+ _M_data->_M_aday7 = __nl_langinfo_l(ABDAY_7, __cloc);
2387+
2388+ // Month names, starting with "C"'s January.
2389+ _M_data->_M_month01 = __nl_langinfo_l(MON_1, __cloc);
2390+ _M_data->_M_month02 = __nl_langinfo_l(MON_2, __cloc);
2391+ _M_data->_M_month03 = __nl_langinfo_l(MON_3, __cloc);
2392+ _M_data->_M_month04 = __nl_langinfo_l(MON_4, __cloc);
2393+ _M_data->_M_month05 = __nl_langinfo_l(MON_5, __cloc);
2394+ _M_data->_M_month06 = __nl_langinfo_l(MON_6, __cloc);
2395+ _M_data->_M_month07 = __nl_langinfo_l(MON_7, __cloc);
2396+ _M_data->_M_month08 = __nl_langinfo_l(MON_8, __cloc);
2397+ _M_data->_M_month09 = __nl_langinfo_l(MON_9, __cloc);
2398+ _M_data->_M_month10 = __nl_langinfo_l(MON_10, __cloc);
2399+ _M_data->_M_month11 = __nl_langinfo_l(MON_11, __cloc);
2400+ _M_data->_M_month12 = __nl_langinfo_l(MON_12, __cloc);
2401+
2402+ // Abbreviated month names, starting with "C"'s Jan.
2403+ _M_data->_M_amonth01 = __nl_langinfo_l(ABMON_1, __cloc);
2404+ _M_data->_M_amonth02 = __nl_langinfo_l(ABMON_2, __cloc);
2405+ _M_data->_M_amonth03 = __nl_langinfo_l(ABMON_3, __cloc);
2406+ _M_data->_M_amonth04 = __nl_langinfo_l(ABMON_4, __cloc);
2407+ _M_data->_M_amonth05 = __nl_langinfo_l(ABMON_5, __cloc);
2408+ _M_data->_M_amonth06 = __nl_langinfo_l(ABMON_6, __cloc);
2409+ _M_data->_M_amonth07 = __nl_langinfo_l(ABMON_7, __cloc);
2410+ _M_data->_M_amonth08 = __nl_langinfo_l(ABMON_8, __cloc);
2411+ _M_data->_M_amonth09 = __nl_langinfo_l(ABMON_9, __cloc);
2412+ _M_data->_M_amonth10 = __nl_langinfo_l(ABMON_10, __cloc);
2413+ _M_data->_M_amonth11 = __nl_langinfo_l(ABMON_11, __cloc);
2414+ _M_data->_M_amonth12 = __nl_langinfo_l(ABMON_12, __cloc);
2415+ }
2416+ }
2417+
2418+#ifdef _GLIBCXX_USE_WCHAR_T
2419+ template<>
2420+ void
2421+ __timepunct<wchar_t>::
2422+ _M_put(wchar_t* __s, size_t __maxlen, const wchar_t* __format,
2423+ const tm* __tm) const
2424+ {
2425+#ifdef __UCLIBC_HAS_XLOCALE__
2426+ __wcsftime_l(__s, __maxlen, __format, __tm, _M_c_locale_timepunct);
2427+ const size_t __len = __wcsftime_l(__s, __maxlen, __format, __tm,
2428+ _M_c_locale_timepunct);
2429+#else
2430+ char* __old = strdup(setlocale(LC_ALL, NULL));
2431+ setlocale(LC_ALL, _M_name_timepunct);
2432+ const size_t __len = wcsftime(__s, __maxlen, __format, __tm);
2433+ setlocale(LC_ALL, __old);
2434+ free(__old);
2435+#endif
2436+ // Make sure __s is null terminated.
2437+ if (__len == 0)
2438+ __s[0] = L'\0';
2439+ }
2440+
2441+ template<>
2442+ void
2443+ __timepunct<wchar_t>::_M_initialize_timepunct(__c_locale __cloc)
2444+ {
2445+ if (!_M_data)
2446+ _M_data = new __timepunct_cache<wchar_t>;
2447+
2448+#warning wide time stuff
2449+// if (!__cloc)
2450+ {
2451+ // "C" locale
2452+ _M_c_locale_timepunct = _S_get_c_locale();
2453+
2454+ _M_data->_M_date_format = L"%m/%d/%y";
2455+ _M_data->_M_date_era_format = L"%m/%d/%y";
2456+ _M_data->_M_time_format = L"%H:%M:%S";
2457+ _M_data->_M_time_era_format = L"%H:%M:%S";
2458+ _M_data->_M_date_time_format = L"";
2459+ _M_data->_M_date_time_era_format = L"";
2460+ _M_data->_M_am = L"AM";
2461+ _M_data->_M_pm = L"PM";
2462+ _M_data->_M_am_pm_format = L"";
2463+
2464+ // Day names, starting with "C"'s Sunday.
2465+ _M_data->_M_day1 = L"Sunday";
2466+ _M_data->_M_day2 = L"Monday";
2467+ _M_data->_M_day3 = L"Tuesday";
2468+ _M_data->_M_day4 = L"Wednesday";
2469+ _M_data->_M_day5 = L"Thursday";
2470+ _M_data->_M_day6 = L"Friday";
2471+ _M_data->_M_day7 = L"Saturday";
2472+
2473+ // Abbreviated day names, starting with "C"'s Sun.
2474+ _M_data->_M_aday1 = L"Sun";
2475+ _M_data->_M_aday2 = L"Mon";
2476+ _M_data->_M_aday3 = L"Tue";
2477+ _M_data->_M_aday4 = L"Wed";
2478+ _M_data->_M_aday5 = L"Thu";
2479+ _M_data->_M_aday6 = L"Fri";
2480+ _M_data->_M_aday7 = L"Sat";
2481+
2482+ // Month names, starting with "C"'s January.
2483+ _M_data->_M_month01 = L"January";
2484+ _M_data->_M_month02 = L"February";
2485+ _M_data->_M_month03 = L"March";
2486+ _M_data->_M_month04 = L"April";
2487+ _M_data->_M_month05 = L"May";
2488+ _M_data->_M_month06 = L"June";
2489+ _M_data->_M_month07 = L"July";
2490+ _M_data->_M_month08 = L"August";
2491+ _M_data->_M_month09 = L"September";
2492+ _M_data->_M_month10 = L"October";
2493+ _M_data->_M_month11 = L"November";
2494+ _M_data->_M_month12 = L"December";
2495+
2496+ // Abbreviated month names, starting with "C"'s Jan.
2497+ _M_data->_M_amonth01 = L"Jan";
2498+ _M_data->_M_amonth02 = L"Feb";
2499+ _M_data->_M_amonth03 = L"Mar";
2500+ _M_data->_M_amonth04 = L"Apr";
2501+ _M_data->_M_amonth05 = L"May";
2502+ _M_data->_M_amonth06 = L"Jun";
2503+ _M_data->_M_amonth07 = L"Jul";
2504+ _M_data->_M_amonth08 = L"Aug";
2505+ _M_data->_M_amonth09 = L"Sep";
2506+ _M_data->_M_amonth10 = L"Oct";
2507+ _M_data->_M_amonth11 = L"Nov";
2508+ _M_data->_M_amonth12 = L"Dec";
2509+ }
2510+#if 0
2511+ else
2512+ {
2513+ _M_c_locale_timepunct = _S_clone_c_locale(__cloc);
2514+
2515+ union { char *__s; wchar_t *__w; } __u;
2516+
2517+ __u.__s = __nl_langinfo_l(_NL_WD_FMT, __cloc);
2518+ _M_data->_M_date_format = __u.__w;
2519+ __u.__s = __nl_langinfo_l(_NL_WERA_D_FMT, __cloc);
2520+ _M_data->_M_date_era_format = __u.__w;
2521+ __u.__s = __nl_langinfo_l(_NL_WT_FMT, __cloc);
2522+ _M_data->_M_time_format = __u.__w;
2523+ __u.__s = __nl_langinfo_l(_NL_WERA_T_FMT, __cloc);
2524+ _M_data->_M_time_era_format = __u.__w;
2525+ __u.__s = __nl_langinfo_l(_NL_WD_T_FMT, __cloc);
2526+ _M_data->_M_date_time_format = __u.__w;
2527+ __u.__s = __nl_langinfo_l(_NL_WERA_D_T_FMT, __cloc);
2528+ _M_data->_M_date_time_era_format = __u.__w;
2529+ __u.__s = __nl_langinfo_l(_NL_WAM_STR, __cloc);
2530+ _M_data->_M_am = __u.__w;
2531+ __u.__s = __nl_langinfo_l(_NL_WPM_STR, __cloc);
2532+ _M_data->_M_pm = __u.__w;
2533+ __u.__s = __nl_langinfo_l(_NL_WT_FMT_AMPM, __cloc);
2534+ _M_data->_M_am_pm_format = __u.__w;
2535+
2536+ // Day names, starting with "C"'s Sunday.
2537+ __u.__s = __nl_langinfo_l(_NL_WDAY_1, __cloc);
2538+ _M_data->_M_day1 = __u.__w;
2539+ __u.__s = __nl_langinfo_l(_NL_WDAY_2, __cloc);
2540+ _M_data->_M_day2 = __u.__w;
2541+ __u.__s = __nl_langinfo_l(_NL_WDAY_3, __cloc);
2542+ _M_data->_M_day3 = __u.__w;
2543+ __u.__s = __nl_langinfo_l(_NL_WDAY_4, __cloc);
2544+ _M_data->_M_day4 = __u.__w;
2545+ __u.__s = __nl_langinfo_l(_NL_WDAY_5, __cloc);
2546+ _M_data->_M_day5 = __u.__w;
2547+ __u.__s = __nl_langinfo_l(_NL_WDAY_6, __cloc);
2548+ _M_data->_M_day6 = __u.__w;
2549+ __u.__s = __nl_langinfo_l(_NL_WDAY_7, __cloc);
2550+ _M_data->_M_day7 = __u.__w;
2551+
2552+ // Abbreviated day names, starting with "C"'s Sun.
2553+ __u.__s = __nl_langinfo_l(_NL_WABDAY_1, __cloc);
2554+ _M_data->_M_aday1 = __u.__w;
2555+ __u.__s = __nl_langinfo_l(_NL_WABDAY_2, __cloc);
2556+ _M_data->_M_aday2 = __u.__w;
2557+ __u.__s = __nl_langinfo_l(_NL_WABDAY_3, __cloc);
2558+ _M_data->_M_aday3 = __u.__w;
2559+ __u.__s = __nl_langinfo_l(_NL_WABDAY_4, __cloc);
2560+ _M_data->_M_aday4 = __u.__w;
2561+ __u.__s = __nl_langinfo_l(_NL_WABDAY_5, __cloc);
2562+ _M_data->_M_aday5 = __u.__w;
2563+ __u.__s = __nl_langinfo_l(_NL_WABDAY_6, __cloc);
2564+ _M_data->_M_aday6 = __u.__w;
2565+ __u.__s = __nl_langinfo_l(_NL_WABDAY_7, __cloc);
2566+ _M_data->_M_aday7 = __u.__w;
2567+
2568+ // Month names, starting with "C"'s January.
2569+ __u.__s = __nl_langinfo_l(_NL_WMON_1, __cloc);
2570+ _M_data->_M_month01 = __u.__w;
2571+ __u.__s = __nl_langinfo_l(_NL_WMON_2, __cloc);
2572+ _M_data->_M_month02 = __u.__w;
2573+ __u.__s = __nl_langinfo_l(_NL_WMON_3, __cloc);
2574+ _M_data->_M_month03 = __u.__w;
2575+ __u.__s = __nl_langinfo_l(_NL_WMON_4, __cloc);
2576+ _M_data->_M_month04 = __u.__w;
2577+ __u.__s = __nl_langinfo_l(_NL_WMON_5, __cloc);
2578+ _M_data->_M_month05 = __u.__w;
2579+ __u.__s = __nl_langinfo_l(_NL_WMON_6, __cloc);
2580+ _M_data->_M_month06 = __u.__w;
2581+ __u.__s = __nl_langinfo_l(_NL_WMON_7, __cloc);
2582+ _M_data->_M_month07 = __u.__w;
2583+ __u.__s = __nl_langinfo_l(_NL_WMON_8, __cloc);
2584+ _M_data->_M_month08 = __u.__w;
2585+ __u.__s = __nl_langinfo_l(_NL_WMON_9, __cloc);
2586+ _M_data->_M_month09 = __u.__w;
2587+ __u.__s = __nl_langinfo_l(_NL_WMON_10, __cloc);
2588+ _M_data->_M_month10 = __u.__w;
2589+ __u.__s = __nl_langinfo_l(_NL_WMON_11, __cloc);
2590+ _M_data->_M_month11 = __u.__w;
2591+ __u.__s = __nl_langinfo_l(_NL_WMON_12, __cloc);
2592+ _M_data->_M_month12 = __u.__w;
2593+
2594+ // Abbreviated month names, starting with "C"'s Jan.
2595+ __u.__s = __nl_langinfo_l(_NL_WABMON_1, __cloc);
2596+ _M_data->_M_amonth01 = __u.__w;
2597+ __u.__s = __nl_langinfo_l(_NL_WABMON_2, __cloc);
2598+ _M_data->_M_amonth02 = __u.__w;
2599+ __u.__s = __nl_langinfo_l(_NL_WABMON_3, __cloc);
2600+ _M_data->_M_amonth03 = __u.__w;
2601+ __u.__s = __nl_langinfo_l(_NL_WABMON_4, __cloc);
2602+ _M_data->_M_amonth04 = __u.__w;
2603+ __u.__s = __nl_langinfo_l(_NL_WABMON_5, __cloc);
2604+ _M_data->_M_amonth05 = __u.__w;
2605+ __u.__s = __nl_langinfo_l(_NL_WABMON_6, __cloc);
2606+ _M_data->_M_amonth06 = __u.__w;
2607+ __u.__s = __nl_langinfo_l(_NL_WABMON_7, __cloc);
2608+ _M_data->_M_amonth07 = __u.__w;
2609+ __u.__s = __nl_langinfo_l(_NL_WABMON_8, __cloc);
2610+ _M_data->_M_amonth08 = __u.__w;
2611+ __u.__s = __nl_langinfo_l(_NL_WABMON_9, __cloc);
2612+ _M_data->_M_amonth09 = __u.__w;
2613+ __u.__s = __nl_langinfo_l(_NL_WABMON_10, __cloc);
2614+ _M_data->_M_amonth10 = __u.__w;
2615+ __u.__s = __nl_langinfo_l(_NL_WABMON_11, __cloc);
2616+ _M_data->_M_amonth11 = __u.__w;
2617+ __u.__s = __nl_langinfo_l(_NL_WABMON_12, __cloc);
2618+ _M_data->_M_amonth12 = __u.__w;
2619+ }
2620+#endif // 0
2621+ }
2622+#endif
2623+}
2624Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/time_members.h
2625===================================================================
2626--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2627+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/time_members.h 2010-06-25 10:42:34.913881064 -0700
2628@@ -0,0 +1,68 @@
2629+// std::time_get, std::time_put implementation, GNU version -*- C++ -*-
2630+
2631+// Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
2632+//
2633+// This file is part of the GNU ISO C++ Library. This library is free
2634+// software; you can redistribute it and/or modify it under the
2635+// terms of the GNU General Public License as published by the
2636+// Free Software Foundation; either version 2, or (at your option)
2637+// any later version.
2638+
2639+// This library is distributed in the hope that it will be useful,
2640+// but WITHOUT ANY WARRANTY; without even the implied warranty of
2641+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2642+// GNU General Public License for more details.
2643+
2644+// You should have received a copy of the GNU General Public License along
2645+// with this library; see the file COPYING. If not, write to the Free
2646+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2647+// USA.
2648+
2649+// As a special exception, you may use this file as part of a free software
2650+// library without restriction. Specifically, if other files instantiate
2651+// templates or use macros or inline functions from this file, or you compile
2652+// this file and link it with other files to produce an executable, this
2653+// file does not by itself cause the resulting executable to be covered by
2654+// the GNU General Public License. This exception does not however
2655+// invalidate any other reasons why the executable file might be covered by
2656+// the GNU General Public License.
2657+
2658+//
2659+// ISO C++ 14882: 22.2.5.1.2 - time_get functions
2660+// ISO C++ 14882: 22.2.5.3.2 - time_put functions
2661+//
2662+
2663+// Written by Benjamin Kosnik <bkoz@redhat.com>
2664+
2665+ template<typename _CharT>
2666+ __timepunct<_CharT>::__timepunct(size_t __refs)
2667+ : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
2668+ _M_name_timepunct(_S_get_c_name())
2669+ { _M_initialize_timepunct(); }
2670+
2671+ template<typename _CharT>
2672+ __timepunct<_CharT>::__timepunct(__cache_type* __cache, size_t __refs)
2673+ : facet(__refs), _M_data(__cache), _M_c_locale_timepunct(NULL),
2674+ _M_name_timepunct(_S_get_c_name())
2675+ { _M_initialize_timepunct(); }
2676+
2677+ template<typename _CharT>
2678+ __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s,
2679+ size_t __refs)
2680+ : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
2681+ _M_name_timepunct(__s)
2682+ {
2683+ char* __tmp = new char[std::strlen(__s) + 1];
2684+ std::strcpy(__tmp, __s);
2685+ _M_name_timepunct = __tmp;
2686+ _M_initialize_timepunct(__cloc);
2687+ }
2688+
2689+ template<typename _CharT>
2690+ __timepunct<_CharT>::~__timepunct()
2691+ {
2692+ if (_M_name_timepunct != _S_get_c_name())
2693+ delete [] _M_name_timepunct;
2694+ delete _M_data;
2695+ _S_destroy_c_locale(_M_c_locale_timepunct);
2696+ }
2697Index: gcc-4.5.0/libstdc++-v3/configure
2698===================================================================
2699--- gcc-4.5.0.orig/libstdc++-v3/configure 2010-04-05 18:27:44.000000000 -0700
2700+++ gcc-4.5.0/libstdc++-v3/configure 2010-06-25 10:48:10.124633072 -0700
2701@@ -15577,7 +15577,7 @@
2702 if test "${enable_clocale+set}" = set; then :
2703 enableval=$enable_clocale;
2704 case "$enableval" in
2705- generic|gnu|ieee_1003.1-2001|yes|no|auto) ;;
2706+ generic|gnu|ieee_1003.1-2001|uclibc|yes|no|auto) ;;
2707 *) as_fn_error "Unknown argument to enable/disable clocale" "$LINENO" 5 ;;
2708 esac
2709
2710@@ -15609,6 +15609,9 @@
2711 # Default to "generic".
2712 if test $enable_clocale_flag = auto; then
2713 case ${target_os} in
2714+ *-uclibc*)
2715+ enable_clocale_flag=uclibc
2716+ ;;
2717 linux* | gnu* | kfreebsd*-gnu | knetbsd*-gnu)
2718 enable_clocale_flag=gnu
2719 ;;
2720@@ -15885,6 +15888,76 @@
2721 CTIME_CC=config/locale/generic/time_members.cc
2722 CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
2723 ;;
2724+ uclibc)
2725+ echo "$as_me:$LINENO: result: uclibc" >&5
2726+echo "${ECHO_T}uclibc" >&6
2727+
2728+ # Declare intention to use gettext, and add support for specific
2729+ # languages.
2730+ # For some reason, ALL_LINGUAS has to be before AM-GNU-GETTEXT
2731+ ALL_LINGUAS="de fr"
2732+
2733+ # Don't call AM-GNU-GETTEXT here. Instead, assume glibc.
2734+ # Extract the first word of "msgfmt", so it can be a program name with args.
2735+set dummy msgfmt; ac_word=$2
2736+echo "$as_me:$LINENO: checking for $ac_word" >&5
2737+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
2738+if test "${ac_cv_prog_check_msgfmt+set}" = set; then
2739+ echo $ECHO_N "(cached) $ECHO_C" >&6
2740+else
2741+ if test -n "$check_msgfmt"; then
2742+ ac_cv_prog_check_msgfmt="$check_msgfmt" # Let the user override the test.
2743+else
2744+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
2745+for as_dir in $PATH
2746+do
2747+ IFS=$as_save_IFS
2748+ test -z "$as_dir" && as_dir=.
2749+ for ac_exec_ext in '' $ac_executable_extensions; do
2750+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
2751+ ac_cv_prog_check_msgfmt="yes"
2752+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
2753+ break 2
2754+ fi
2755+done
2756+done
2757+
2758+ test -z "$ac_cv_prog_check_msgfmt" && ac_cv_prog_check_msgfmt="no"
2759+fi
2760+fi
2761+check_msgfmt=$ac_cv_prog_check_msgfmt
2762+if test -n "$check_msgfmt"; then
2763+ echo "$as_me:$LINENO: result: $check_msgfmt" >&5
2764+echo "${ECHO_T}$check_msgfmt" >&6
2765+else
2766+ echo "$as_me:$LINENO: result: no" >&5
2767+echo "${ECHO_T}no" >&6
2768+fi
2769+
2770+ if test x"$check_msgfmt" = x"yes" && test x"$enable_nls" = x"yes"; then
2771+ USE_NLS=yes
2772+ fi
2773+ # Export the build objects.
2774+ for ling in $ALL_LINGUAS; do \
2775+ glibcxx_MOFILES="$glibcxx_MOFILES $ling.mo"; \
2776+ glibcxx_POFILES="$glibcxx_POFILES $ling.po"; \
2777+ done
2778+
2779+
2780+
2781+ CLOCALE_H=config/locale/uclibc/c_locale.h
2782+ CLOCALE_CC=config/locale/uclibc/c_locale.cc
2783+ CCODECVT_CC=config/locale/uclibc/codecvt_members.cc
2784+ CCOLLATE_CC=config/locale/uclibc/collate_members.cc
2785+ CCTYPE_CC=config/locale/uclibc/ctype_members.cc
2786+ CMESSAGES_H=config/locale/uclibc/messages_members.h
2787+ CMESSAGES_CC=config/locale/uclibc/messages_members.cc
2788+ CMONEY_CC=config/locale/uclibc/monetary_members.cc
2789+ CNUMERIC_CC=config/locale/uclibc/numeric_members.cc
2790+ CTIME_H=config/locale/uclibc/time_members.h
2791+ CTIME_CC=config/locale/uclibc/time_members.cc
2792+ CLOCALE_INTERNAL_H=config/locale/uclibc/c++locale_internal.h
2793+ ;;
2794 esac
2795
2796 # This is where the testsuite looks for locale catalogs, using the
2797@@ -16940,6 +17013,7 @@
2798
2799 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2800 /* end confdefs.h. */
2801+#line 17016 "configure"
2802 #include <wctype.h>
2803 int
2804 main ()
2805@@ -58165,7 +58239,6 @@
2806 fi
2807 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
2808 /* end confdefs.h. */
2809-
2810 int
2811 main ()
2812 {
2813Index: gcc-4.5.0/libstdc++-v3/include/c_compatibility/wchar.h
2814===================================================================
2815--- gcc-4.5.0.orig/libstdc++-v3/include/c_compatibility/wchar.h 2009-04-09 08:00:19.000000000 -0700
2816+++ gcc-4.5.0/libstdc++-v3/include/c_compatibility/wchar.h 2010-06-25 10:42:34.949880937 -0700
2817@@ -101,7 +101,9 @@
2818 using std::wmemcpy;
2819 using std::wmemmove;
2820 using std::wmemset;
2821+#if _GLIBCXX_HAVE_WCSFTIME
2822 using std::wcsftime;
2823+#endif
2824
2825 #if _GLIBCXX_USE_C99
2826 using std::wcstold;
2827Index: gcc-4.5.0/libstdc++-v3/include/c_std/cwchar
2828===================================================================
2829--- gcc-4.5.0.orig/libstdc++-v3/include/c_std/cwchar 2010-02-04 10:20:34.000000000 -0800
2830+++ gcc-4.5.0/libstdc++-v3/include/c_std/cwchar 2010-06-25 10:42:34.949880937 -0700
2831@@ -177,7 +177,9 @@
2832 using ::wcscoll;
2833 using ::wcscpy;
2834 using ::wcscspn;
2835+#if _GLIBCXX_HAVE_WCSFTIME
2836 using ::wcsftime;
2837+#endif
2838 using ::wcslen;
2839 using ::wcsncat;
2840 using ::wcsncmp;
diff --git a/recipes-devtools/gcc/gcc-4.5/203-uclibc-locale-no__x.patch b/recipes-devtools/gcc/gcc-4.5/203-uclibc-locale-no__x.patch
deleted file mode 100644
index f39e65220c..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/203-uclibc-locale-no__x.patch
+++ /dev/null
@@ -1,233 +0,0 @@
1Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/c++locale_internal.h
2===================================================================
3--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2008-08-16 01:29:20.000000000 -0700
4+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2008-08-16 01:33:23.000000000 -0700
5@@ -60,4 +60,49 @@
6 extern "C" __typeof(wctype_l) __wctype_l;
7 #endif
8
9+# define __nl_langinfo_l nl_langinfo_l
10+# define __strcoll_l strcoll_l
11+# define __strftime_l strftime_l
12+# define __strtod_l strtod_l
13+# define __strtof_l strtof_l
14+# define __strtold_l strtold_l
15+# define __strxfrm_l strxfrm_l
16+# define __newlocale newlocale
17+# define __freelocale freelocale
18+# define __duplocale duplocale
19+# define __uselocale uselocale
20+
21+# ifdef _GLIBCXX_USE_WCHAR_T
22+# define __iswctype_l iswctype_l
23+# define __towlower_l towlower_l
24+# define __towupper_l towupper_l
25+# define __wcscoll_l wcscoll_l
26+# define __wcsftime_l wcsftime_l
27+# define __wcsxfrm_l wcsxfrm_l
28+# define __wctype_l wctype_l
29+# endif
30+
31+#else
32+# define __nl_langinfo_l(N, L) nl_langinfo((N))
33+# define __strcoll_l(S1, S2, L) strcoll((S1), (S2))
34+# define __strtod_l(S, E, L) strtod((S), (E))
35+# define __strtof_l(S, E, L) strtof((S), (E))
36+# define __strtold_l(S, E, L) strtold((S), (E))
37+# define __strxfrm_l(S1, S2, N, L) strxfrm((S1), (S2), (N))
38+# warning should dummy __newlocale check for C|POSIX ?
39+# define __newlocale(a, b, c) NULL
40+# define __freelocale(a) ((void)0)
41+# define __duplocale(a) __c_locale()
42+//# define __uselocale ?
43+//
44+# ifdef _GLIBCXX_USE_WCHAR_T
45+# define __iswctype_l(C, M, L) iswctype((C), (M))
46+# define __towlower_l(C, L) towlower((C))
47+# define __towupper_l(C, L) towupper((C))
48+# define __wcscoll_l(S1, S2, L) wcscoll((S1), (S2))
49+//# define __wcsftime_l(S, M, F, T, L) wcsftime((S), (M), (F), (T))
50+# define __wcsxfrm_l(S1, S2, N, L) wcsxfrm((S1), (S2), (N))
51+# define __wctype_l(S, L) wctype((S))
52+# endif
53+
54 #endif // GLIBC 2.3 and later
55Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/c_locale.cc
56===================================================================
57--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/c_locale.cc 2008-08-16 01:29:20.000000000 -0700
58+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/c_locale.cc 2008-08-16 01:33:00.000000000 -0700
59@@ -39,20 +39,6 @@
60 #include <langinfo.h>
61 #include <bits/c++locale_internal.h>
62
63-#ifndef __UCLIBC_HAS_XLOCALE__
64-#define __strtol_l(S, E, B, L) strtol((S), (E), (B))
65-#define __strtoul_l(S, E, B, L) strtoul((S), (E), (B))
66-#define __strtoll_l(S, E, B, L) strtoll((S), (E), (B))
67-#define __strtoull_l(S, E, B, L) strtoull((S), (E), (B))
68-#define __strtof_l(S, E, L) strtof((S), (E))
69-#define __strtod_l(S, E, L) strtod((S), (E))
70-#define __strtold_l(S, E, L) strtold((S), (E))
71-#warning should dummy __newlocale check for C|POSIX ?
72-#define __newlocale(a, b, c) NULL
73-#define __freelocale(a) ((void)0)
74-#define __duplocale(a) __c_locale()
75-#endif
76-
77 namespace std
78 {
79 template<>
80Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/collate_members.cc
81===================================================================
82--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/collate_members.cc 2008-08-16 01:29:20.000000000 -0700
83+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/collate_members.cc 2008-08-16 01:30:31.000000000 -0700
84@@ -36,13 +36,6 @@
85 #include <locale>
86 #include <bits/c++locale_internal.h>
87
88-#ifndef __UCLIBC_HAS_XLOCALE__
89-#define __strcoll_l(S1, S2, L) strcoll((S1), (S2))
90-#define __strxfrm_l(S1, S2, N, L) strxfrm((S1), (S2), (N))
91-#define __wcscoll_l(S1, S2, L) wcscoll((S1), (S2))
92-#define __wcsxfrm_l(S1, S2, N, L) wcsxfrm((S1), (S2), (N))
93-#endif
94-
95 namespace std
96 {
97 // These are basically extensions to char_traits, and perhaps should
98Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/monetary_members.cc
99===================================================================
100--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2008-08-16 01:29:20.000000000 -0700
101+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2008-08-16 01:30:31.000000000 -0700
102@@ -43,10 +43,6 @@
103 #warning tailor for stub locale support
104 #endif
105
106-#ifndef __UCLIBC_HAS_XLOCALE__
107-#define __nl_langinfo_l(N, L) nl_langinfo((N))
108-#endif
109-
110 namespace std
111 {
112 // Construct and return valid pattern consisting of some combination of:
113Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/numeric_members.cc
114===================================================================
115--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2008-08-16 01:29:20.000000000 -0700
116+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2008-08-16 01:30:31.000000000 -0700
117@@ -41,9 +41,6 @@
118 #ifdef __UCLIBC_MJN3_ONLY__
119 #warning tailor for stub locale support
120 #endif
121-#ifndef __UCLIBC_HAS_XLOCALE__
122-#define __nl_langinfo_l(N, L) nl_langinfo((N))
123-#endif
124
125 namespace std
126 {
127Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/time_members.cc
128===================================================================
129--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/time_members.cc 2008-08-16 01:29:20.000000000 -0700
130+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/time_members.cc 2008-08-16 01:30:31.000000000 -0700
131@@ -40,9 +40,6 @@
132 #ifdef __UCLIBC_MJN3_ONLY__
133 #warning tailor for stub locale support
134 #endif
135-#ifndef __UCLIBC_HAS_XLOCALE__
136-#define __nl_langinfo_l(N, L) nl_langinfo((N))
137-#endif
138
139 namespace std
140 {
141Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/ctype_members.cc
142===================================================================
143--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/ctype_members.cc 2008-08-16 01:29:20.000000000 -0700
144+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/ctype_members.cc 2008-08-16 01:30:31.000000000 -0700
145@@ -38,13 +38,6 @@
146 #undef _LIBC
147 #include <bits/c++locale_internal.h>
148
149-#ifndef __UCLIBC_HAS_XLOCALE__
150-#define __wctype_l(S, L) wctype((S))
151-#define __towupper_l(C, L) towupper((C))
152-#define __towlower_l(C, L) towlower((C))
153-#define __iswctype_l(C, M, L) iswctype((C), (M))
154-#endif
155-
156 namespace std
157 {
158 // NB: The other ctype<char> specializations are in src/locale.cc and
159Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/messages_members.cc
160===================================================================
161--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/messages_members.cc 2008-08-16 01:27:18.000000000 -0700
162+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/messages_members.cc 2008-08-16 01:30:31.000000000 -0700
163@@ -39,13 +39,10 @@
164 #ifdef __UCLIBC_MJN3_ONLY__
165 #warning fix gettext stuff
166 #endif
167-#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
168-extern "C" char *__dcgettext(const char *domainname,
169- const char *msgid, int category);
170 #undef gettext
171-#define gettext(msgid) __dcgettext(NULL, msgid, LC_MESSAGES)
172+#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
173+#define gettext(msgid) dcgettext(NULL, msgid, LC_MESSAGES)
174 #else
175-#undef gettext
176 #define gettext(msgid) (msgid)
177 #endif
178
179Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/messages_members.h
180===================================================================
181--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/messages_members.h 2008-08-16 01:29:20.000000000 -0700
182+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/messages_members.h 2008-08-16 01:31:43.000000000 -0700
183@@ -36,15 +36,11 @@
184 #ifdef __UCLIBC_MJN3_ONLY__
185 #warning fix prototypes for *textdomain funcs
186 #endif
187-#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
188-extern "C" char *__textdomain(const char *domainname);
189-extern "C" char *__bindtextdomain(const char *domainname,
190- const char *dirname);
191-#else
192-#undef __textdomain
193-#undef __bindtextdomain
194-#define __textdomain(D) ((void)0)
195-#define __bindtextdomain(D,P) ((void)0)
196+#ifndef __UCLIBC_HAS_GETTEXT_AWARENESS__
197+#undef textdomain
198+#undef bindtextdomain
199+#define textdomain(D) ((void)0)
200+#define bindtextdomain(D,P) ((void)0)
201 #endif
202
203 // Non-virtual member functions.
204@@ -70,7 +66,7 @@
205 messages<_CharT>::open(const basic_string<char>& __s, const locale& __loc,
206 const char* __dir) const
207 {
208- __bindtextdomain(__s.c_str(), __dir);
209+ bindtextdomain(__s.c_str(), __dir);
210 return this->do_open(__s, __loc);
211 }
212
213@@ -90,7 +86,7 @@
214 {
215 // No error checking is done, assume the catalog exists and can
216 // be used.
217- __textdomain(__s.c_str());
218+ textdomain(__s.c_str());
219 return 0;
220 }
221
222Index: gcc-4.3.1/libstdc++-v3/config/locale/uclibc/c_locale.h
223===================================================================
224--- gcc-4.3.1.orig/libstdc++-v3/config/locale/uclibc/c_locale.h 2008-08-16 01:29:20.000000000 -0700
225+++ gcc-4.3.1/libstdc++-v3/config/locale/uclibc/c_locale.h 2008-08-16 01:30:31.000000000 -0700
226@@ -68,6 +68,7 @@
227 {
228 extern "C" __typeof(uselocale) __uselocale;
229 }
230+#define __uselocale uselocale
231 #endif
232
233 namespace std
diff --git a/recipes-devtools/gcc/gcc-4.5/204-uclibc-locale-wchar_fix.patch b/recipes-devtools/gcc/gcc-4.5/204-uclibc-locale-wchar_fix.patch
deleted file mode 100644
index 160ab35bb3..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/204-uclibc-locale-wchar_fix.patch
+++ /dev/null
@@ -1,48 +0,0 @@
1--- gcc/libstdc++-v3/config/locale/uclibc/monetary_members.cc.uclibc200_wchar~ 2006-03-10 15:32:37 +0100
2+++ gcc/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2006-03-10 15:37:27 +0100
3@@ -401,7 +401,7 @@
4 # ifdef __UCLIBC_HAS_XLOCALE__
5 _M_data->_M_decimal_point = __cloc->decimal_point_wc;
6 _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
7-# else
8+# elif defined __UCLIBC_HAS_LOCALE__
9 _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
10 _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
11 # endif
12@@ -556,7 +556,7 @@
13 # ifdef __UCLIBC_HAS_XLOCALE__
14 _M_data->_M_decimal_point = __cloc->decimal_point_wc;
15 _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
16-# else
17+# elif defined __UCLIBC_HAS_LOCALE__
18 _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
19 _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
20 # endif
21--- gcc/libstdc++-v3/config/locale/uclibc/numeric_members.cc.uclibc200_wchar~ 2006-03-10 15:32:37 +0100
22+++ gcc/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2006-03-10 15:37:27 +0100
23@@ -127,12 +127,25 @@
24 {
25 // Named locale.
26 // NB: In the GNU model wchar_t is always 32 bit wide.
27+#ifdef __UCLIBC_MJN3_ONLY__
28+#warning fix this... should be numeric
29+#endif
30+#ifdef __UCLIBC__
31+# ifdef __UCLIBC_HAS_XLOCALE__
32+ _M_data->_M_decimal_point = __cloc->decimal_point_wc;
33+ _M_data->_M_thousands_sep = __cloc->thousands_sep_wc;
34+# elif defined __UCLIBC_HAS_LOCALE__
35+ _M_data->_M_decimal_point = __global_locale->decimal_point_wc;
36+ _M_data->_M_thousands_sep = __global_locale->thousands_sep_wc;
37+# endif
38+#else
39 union { char *__s; wchar_t __w; } __u;
40 __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
41 _M_data->_M_decimal_point = __u.__w;
42
43 __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
44 _M_data->_M_thousands_sep = __u.__w;
45+#endif
46
47 if (_M_data->_M_thousands_sep == L'\0')
48 _M_data->_M_grouping = "";
diff --git a/recipes-devtools/gcc/gcc-4.5/205-uclibc-locale-update.patch b/recipes-devtools/gcc/gcc-4.5/205-uclibc-locale-update.patch
deleted file mode 100644
index 48eaa1d442..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/205-uclibc-locale-update.patch
+++ /dev/null
@@ -1,519 +0,0 @@
1Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/c_locale.cc
2===================================================================
3--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/c_locale.cc 2008-09-17 22:35:28.000000000 -0700
4+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/c_locale.cc 2008-09-17 22:35:29.000000000 -0700
5@@ -39,23 +39,20 @@
6 #include <langinfo.h>
7 #include <bits/c++locale_internal.h>
8
9-namespace std
10-{
11+_GLIBCXX_BEGIN_NAMESPACE(std)
12+
13 template<>
14 void
15 __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err,
16 const __c_locale& __cloc)
17 {
18- if (!(__err & ios_base::failbit))
19- {
20- char* __sanity;
21- errno = 0;
22- float __f = __strtof_l(__s, &__sanity, __cloc);
23- if (__sanity != __s && errno != ERANGE)
24- __v = __f;
25- else
26- __err |= ios_base::failbit;
27- }
28+ char* __sanity;
29+ errno = 0;
30+ float __f = __strtof_l(__s, &__sanity, __cloc);
31+ if (__sanity != __s && errno != ERANGE)
32+ __v = __f;
33+ else
34+ __err |= ios_base::failbit;
35 }
36
37 template<>
38@@ -63,16 +60,13 @@
39 __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err,
40 const __c_locale& __cloc)
41 {
42- if (!(__err & ios_base::failbit))
43- {
44- char* __sanity;
45- errno = 0;
46- double __d = __strtod_l(__s, &__sanity, __cloc);
47- if (__sanity != __s && errno != ERANGE)
48- __v = __d;
49- else
50- __err |= ios_base::failbit;
51- }
52+ char* __sanity;
53+ errno = 0;
54+ double __d = __strtod_l(__s, &__sanity, __cloc);
55+ if (__sanity != __s && errno != ERANGE)
56+ __v = __d;
57+ else
58+ __err |= ios_base::failbit;
59 }
60
61 template<>
62@@ -80,16 +74,13 @@
63 __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err,
64 const __c_locale& __cloc)
65 {
66- if (!(__err & ios_base::failbit))
67- {
68- char* __sanity;
69- errno = 0;
70- long double __ld = __strtold_l(__s, &__sanity, __cloc);
71- if (__sanity != __s && errno != ERANGE)
72- __v = __ld;
73- else
74- __err |= ios_base::failbit;
75- }
76+ char* __sanity;
77+ errno = 0;
78+ long double __ld = __strtold_l(__s, &__sanity, __cloc);
79+ if (__sanity != __s && errno != ERANGE)
80+ __v = __ld;
81+ else
82+ __err |= ios_base::failbit;
83 }
84
85 void
86@@ -110,17 +101,18 @@
87 void
88 locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
89 {
90- if (_S_get_c_locale() != __cloc)
91+ if (__cloc && _S_get_c_locale() != __cloc)
92 __freelocale(__cloc);
93 }
94
95 __c_locale
96 locale::facet::_S_clone_c_locale(__c_locale& __cloc)
97 { return __duplocale(__cloc); }
98-} // namespace std
99
100-namespace __gnu_cxx
101-{
102+_GLIBCXX_END_NAMESPACE
103+
104+_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
105+
106 const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] =
107 {
108 "LC_CTYPE",
109@@ -138,9 +130,11 @@
110 "LC_IDENTIFICATION"
111 #endif
112 };
113-}
114
115-namespace std
116-{
117+_GLIBCXX_END_NAMESPACE
118+
119+_GLIBCXX_BEGIN_NAMESPACE(std)
120+
121 const char* const* const locale::_S_categories = __gnu_cxx::category_names;
122-} // namespace std
123+
124+_GLIBCXX_END_NAMESPACE
125Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc
126===================================================================
127--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/ctype_members.cc 2008-09-17 22:35:28.000000000 -0700
128+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/ctype_members.cc 2008-09-17 23:09:49.000000000 -0700
129@@ -33,16 +33,20 @@
130
131 // Written by Benjamin Kosnik <bkoz@redhat.com>
132
133+#include <features.h>
134+#ifdef __UCLIBC_HAS_LOCALE__
135 #define _LIBC
136 #include <locale>
137 #undef _LIBC
138+#else
139+#include <locale>
140+#endif
141 #include <bits/c++locale_internal.h>
142
143-namespace std
144-{
145+_GLIBCXX_BEGIN_NAMESPACE(std)
146+
147 // NB: The other ctype<char> specializations are in src/locale.cc and
148 // various /config/os/* files.
149- template<>
150 ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
151 : ctype<char>(0, false, __refs)
152 {
153@@ -57,6 +61,8 @@
154 #endif
155 }
156 }
157+ ctype_byname<char>::~ctype_byname()
158+ { }
159
160 #ifdef _GLIBCXX_USE_WCHAR_T
161 ctype<wchar_t>::__wmask_type
162@@ -138,17 +144,33 @@
163 ctype<wchar_t>::
164 do_is(mask __m, wchar_t __c) const
165 {
166- // Highest bitmask in ctype_base == 10, but extra in "C"
167- // library for blank.
168+ // The case of __m == ctype_base::space is particularly important,
169+ // due to its use in many istream functions. Therefore we deal with
170+ // it first, exploiting the knowledge that on GNU systems _M_bit[5]
171+ // is the mask corresponding to ctype_base::space. NB: an encoding
172+ // change would not affect correctness!
173+
174 bool __ret = false;
175- const size_t __bitmasksize = 11;
176- for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
177- if (__m & _M_bit[__bitcur]
178- && __iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
179- {
180- __ret = true;
181- break;
182- }
183+ if (__m == _M_bit[5])
184+ __ret = __iswctype_l(__c, _M_wmask[5], _M_c_locale_ctype);
185+ else
186+ {
187+ // Highest bitmask in ctype_base == 10, but extra in "C"
188+ // library for blank.
189+ const size_t __bitmasksize = 11;
190+ for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
191+ if (__m & _M_bit[__bitcur])
192+ {
193+ if (__iswctype_l(__c, _M_wmask[__bitcur], _M_c_locale_ctype))
194+ {
195+ __ret = true;
196+ break;
197+ }
198+ else if (__m == _M_bit[__bitcur])
199+ break;
200+ }
201+ }
202+
203 return __ret;
204 }
205
206@@ -290,4 +312,5 @@
207 #endif
208 }
209 #endif // _GLIBCXX_USE_WCHAR_T
210-}
211+
212+_GLIBCXX_END_NAMESPACE
213Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/messages_members.h
214===================================================================
215--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/messages_members.h 2008-09-17 22:35:28.000000000 -0700
216+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/messages_members.h 2008-09-17 23:13:34.000000000 -0700
217@@ -53,12 +53,16 @@
218 template<typename _CharT>
219 messages<_CharT>::messages(__c_locale __cloc, const char* __s,
220 size_t __refs)
221- : facet(__refs), _M_c_locale_messages(_S_clone_c_locale(__cloc)),
222- _M_name_messages(__s)
223+ : facet(__refs), _M_c_locale_messages(NULL),
224+ _M_name_messages(NULL)
225 {
226- char* __tmp = new char[std::strlen(__s) + 1];
227- std::strcpy(__tmp, __s);
228+ const size_t __len = std::strlen(__s) + 1;
229+ char* __tmp = new char[__len];
230+ std::memcpy(__tmp, __s, __len);
231 _M_name_messages = __tmp;
232+
233+ // Last to avoid leaking memory if new throws.
234+ _M_c_locale_messages = _S_clone_c_locale(__cloc);
235 }
236
237 template<typename _CharT>
238Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc
239===================================================================
240--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2008-09-17 22:35:28.000000000 -0700
241+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/monetary_members.cc 2008-09-17 22:35:29.000000000 -0700
242@@ -33,9 +33,14 @@
243
244 // Written by Benjamin Kosnik <bkoz@redhat.com>
245
246+#include <features.h>
247+#ifdef __UCLIBC_HAS_LOCALE__
248 #define _LIBC
249 #include <locale>
250 #undef _LIBC
251+#else
252+#include <locale>
253+#endif
254 #include <bits/c++locale_internal.h>
255
256 #ifdef __UCLIBC_MJN3_ONLY__
257@@ -206,7 +211,7 @@
258 }
259 break;
260 default:
261- ;
262+ __ret = pattern();
263 }
264 return __ret;
265 }
266@@ -390,7 +395,9 @@
267 __c_locale __old = __uselocale(__cloc);
268 #else
269 // Switch to named locale so that mbsrtowcs will work.
270- char* __old = strdup(setlocale(LC_ALL, NULL));
271+ char* __old = setlocale(LC_ALL, NULL);
272+ const size_t __llen = strlen(__old) + 1;
273+ char* __sav = new char[__llen];
274 setlocale(LC_ALL, __name);
275 #endif
276
277@@ -477,8 +484,8 @@
278 #ifdef __UCLIBC_HAS_XLOCALE__
279 __uselocale(__old);
280 #else
281- setlocale(LC_ALL, __old);
282- free(__old);
283+ setlocale(LC_ALL, __sav);
284+ delete [] __sav;
285 #endif
286 __throw_exception_again;
287 }
288@@ -498,8 +505,8 @@
289 #ifdef __UCLIBC_HAS_XLOCALE__
290 __uselocale(__old);
291 #else
292- setlocale(LC_ALL, __old);
293- free(__old);
294+ setlocale(LC_ALL, __sav);
295+ delete [] __sav;
296 #endif
297 }
298 }
299@@ -545,8 +552,11 @@
300 __c_locale __old = __uselocale(__cloc);
301 #else
302 // Switch to named locale so that mbsrtowcs will work.
303- char* __old = strdup(setlocale(LC_ALL, NULL));
304- setlocale(LC_ALL, __name);
305+ char* __old = setlocale(LC_ALL, NULL);
306+ const size_t __llen = strlen(__old) + 1;
307+ char* __sav = new char[__llen];
308+ memcpy(__sav, __old, __llen);
309+ setlocale(LC_ALL, __name);
310 #endif
311
312 #ifdef __UCLIBC_MJN3_ONLY__
313@@ -633,8 +643,8 @@
314 #ifdef __UCLIBC_HAS_XLOCALE__
315 __uselocale(__old);
316 #else
317- setlocale(LC_ALL, __old);
318- free(__old);
319+ setlocale(LC_ALL, __sav);
320+ delete [] __sav;
321 #endif
322 __throw_exception_again;
323 }
324@@ -653,8 +663,8 @@
325 #ifdef __UCLIBC_HAS_XLOCALE__
326 __uselocale(__old);
327 #else
328- setlocale(LC_ALL, __old);
329- free(__old);
330+ setlocale(LC_ALL, __sav);
331+ delete [] __sav;
332 #endif
333 }
334 }
335Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc
336===================================================================
337--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2008-09-17 22:35:28.000000000 -0700
338+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/numeric_members.cc 2008-09-17 22:35:29.000000000 -0700
339@@ -33,9 +33,14 @@
340
341 // Written by Benjamin Kosnik <bkoz@redhat.com>
342
343+#include <features.h>
344+#ifdef __UCLIBC_HAS_LOCALE__
345 #define _LIBC
346 #include <locale>
347 #undef _LIBC
348+#else
349+#include <locale>
350+#endif
351 #include <bits/c++locale_internal.h>
352
353 #ifdef __UCLIBC_MJN3_ONLY__
354Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/time_members.h
355===================================================================
356--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/time_members.h 2008-09-17 22:35:27.000000000 -0700
357+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/time_members.h 2008-09-17 23:13:34.000000000 -0700
358@@ -50,12 +50,21 @@
359 __timepunct<_CharT>::__timepunct(__c_locale __cloc, const char* __s,
360 size_t __refs)
361 : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
362- _M_name_timepunct(__s)
363+ _M_name_timepunct(NULL)
364 {
365- char* __tmp = new char[std::strlen(__s) + 1];
366- std::strcpy(__tmp, __s);
367+ const size_t __len = std::strlen(__s) + 1;
368+ char* __tmp = new char[__len];
369+ std::memcpy(__tmp, __s, __len);
370 _M_name_timepunct = __tmp;
371- _M_initialize_timepunct(__cloc);
372+
373+ try
374+ { _M_initialize_timepunct(__cloc); }
375+ catch(...)
376+ {
377+ delete [] _M_name_timepunct;
378+ __throw_exception_again;
379+ }
380+
381 }
382
383 template<typename _CharT>
384Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/c_locale.h
385===================================================================
386--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/c_locale.h 2008-09-17 22:35:28.000000000 -0700
387+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/c_locale.h 2008-09-17 22:35:29.000000000 -0700
388@@ -39,21 +39,23 @@
389 #pragma GCC system_header
390
391 #include <cstring> // get std::strlen
392-#include <cstdio> // get std::snprintf or std::sprintf
393+#include <cstdio> // get std::vsnprintf or std::vsprintf
394 #include <clocale>
395 #include <langinfo.h> // For codecvt
396 #ifdef __UCLIBC_MJN3_ONLY__
397 #warning fix this
398 #endif
399-#ifdef __UCLIBC_HAS_LOCALE__
400+#ifdef _GLIBCXX_USE_ICONV
401 #include <iconv.h> // For codecvt using iconv, iconv_t
402 #endif
403-#ifdef __UCLIBC_HAS_GETTEXT_AWARENESS__
404-#include <libintl.h> // For messages
405+#ifdef HAVE_LIBINTL_H
406+#include <libintl.h> // For messages
407 #endif
408+#include <cstdarg>
409
410 #ifdef __UCLIBC_MJN3_ONLY__
411 #warning what is _GLIBCXX_C_LOCALE_GNU for
412+// psm: used in os/gnu-linux/ctype_noninline.h
413 #endif
414 #define _GLIBCXX_C_LOCALE_GNU 1
415
416@@ -78,23 +80,25 @@
417 #else
418 typedef int* __c_locale;
419 #endif
420-
421- // Convert numeric value of type _Tv to string and return length of
422- // string. If snprintf is available use it, otherwise fall back to
423- // the unsafe sprintf which, in general, can be dangerous and should
424+ // Convert numeric value of type double to string and return length of
425+ // string. If vsnprintf is available use it, otherwise fall back to
426+ // the unsafe vsprintf which, in general, can be dangerous and should
427 // be avoided.
428- template<typename _Tv>
429- int
430- __convert_from_v(char* __out,
431- const int __size __attribute__ ((__unused__)),
432- const char* __fmt,
433-#ifdef __UCLIBC_HAS_XCLOCALE__
434- _Tv __v, const __c_locale& __cloc, int __prec)
435+ inline int
436+ __convert_from_v(const __c_locale&
437+#ifndef __UCLIBC_HAS_XCLOCALE__
438+ __cloc __attribute__ ((__unused__))
439+#endif
440+ ,
441+ char* __out,
442+ const int __size,
443+ const char* __fmt, ...)
444 {
445+ va_list __args;
446+#ifdef __UCLIBC_HAS_XCLOCALE__
447+
448 __c_locale __old = __gnu_cxx::__uselocale(__cloc);
449 #else
450- _Tv __v, const __c_locale&, int __prec)
451- {
452 # ifdef __UCLIBC_HAS_LOCALE__
453 char* __old = std::setlocale(LC_ALL, NULL);
454 char* __sav = new char[std::strlen(__old) + 1];
455@@ -103,7 +107,9 @@
456 # endif
457 #endif
458
459- const int __ret = std::snprintf(__out, __size, __fmt, __prec, __v);
460+ va_start(__args, __fmt);
461+ const int __ret = std::vsnprintf(__out, __size, __fmt, __args);
462+ va_end(__args);
463
464 #ifdef __UCLIBC_HAS_XCLOCALE__
465 __gnu_cxx::__uselocale(__old);
466Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/time_members.cc
467===================================================================
468--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/time_members.cc 2008-09-17 22:35:28.000000000 -0700
469+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/time_members.cc 2008-09-17 22:35:29.000000000 -0700
470@@ -53,11 +53,14 @@
471 const size_t __len = __strftime_l(__s, __maxlen, __format, __tm,
472 _M_c_locale_timepunct);
473 #else
474- char* __old = strdup(setlocale(LC_ALL, NULL));
475+ char* __old = setlocale(LC_ALL, NULL);
476+ const size_t __llen = strlen(__old) + 1;
477+ char* __sav = new char[__llen];
478+ memcpy(__sav, __old, __llen);
479 setlocale(LC_ALL, _M_name_timepunct);
480 const size_t __len = strftime(__s, __maxlen, __format, __tm);
481- setlocale(LC_ALL, __old);
482- free(__old);
483+ setlocale(LC_ALL, __sav);
484+ delete [] __sav;
485 #endif
486 // Make sure __s is null terminated.
487 if (__len == 0)
488@@ -207,11 +210,14 @@
489 const size_t __len = __wcsftime_l(__s, __maxlen, __format, __tm,
490 _M_c_locale_timepunct);
491 #else
492- char* __old = strdup(setlocale(LC_ALL, NULL));
493+ char* __old = setlocale(LC_ALL, NULL);
494+ const size_t __llen = strlen(__old) + 1;
495+ char* __sav = new char[__llen];
496+ memcpy(__sav, __old, __llen);
497 setlocale(LC_ALL, _M_name_timepunct);
498 const size_t __len = wcsftime(__s, __maxlen, __format, __tm);
499- setlocale(LC_ALL, __old);
500- free(__old);
501+ setlocale(LC_ALL, __sav);
502+ delete [] __sav;
503 #endif
504 // Make sure __s is null terminated.
505 if (__len == 0)
506Index: gcc-4.3.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h
507===================================================================
508--- gcc-4.3.2.orig/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2008-09-17 22:35:28.000000000 -0700
509+++ gcc-4.3.2/libstdc++-v3/config/locale/uclibc/c++locale_internal.h 2008-09-17 22:35:29.000000000 -0700
510@@ -31,6 +31,9 @@
511
512 #include <bits/c++config.h>
513 #include <clocale>
514+#include <cstdlib>
515+#include <cstring>
516+#include <cstddef>
517
518 #ifdef __UCLIBC_MJN3_ONLY__
519 #warning clean this up
diff --git a/recipes-devtools/gcc/gcc-4.5/301-missing-execinfo_h.patch b/recipes-devtools/gcc/gcc-4.5/301-missing-execinfo_h.patch
deleted file mode 100644
index aaa5cee8c8..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/301-missing-execinfo_h.patch
+++ /dev/null
@@ -1,13 +0,0 @@
1Index: gcc-4.5.0/boehm-gc/include/gc.h
2===================================================================
3--- gcc-4.5.0.orig/boehm-gc/include/gc.h 2007-04-23 14:10:09.000000000 -0700
4+++ gcc-4.5.0/boehm-gc/include/gc.h 2010-06-25 10:49:12.768883509 -0700
5@@ -503,7 +503,7 @@
6 #if defined(__linux__) || defined(__GLIBC__)
7 # include <features.h>
8 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
9- && !defined(__ia64__)
10+ && !defined(__ia64__) && !defined(__UCLIBC__)
11 # ifndef GC_HAVE_BUILTIN_BACKTRACE
12 # define GC_HAVE_BUILTIN_BACKTRACE
13 # endif
diff --git a/recipes-devtools/gcc/gcc-4.5/302-c99-snprintf.patch b/recipes-devtools/gcc/gcc-4.5/302-c99-snprintf.patch
deleted file mode 100644
index 12be2da79c..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/302-c99-snprintf.patch
+++ /dev/null
@@ -1,13 +0,0 @@
1Index: gcc-4.5.0/libstdc++-v3/include/c_std/cstdio
2===================================================================
3--- gcc-4.5.0.orig/libstdc++-v3/include/c_std/cstdio 2010-02-04 10:20:34.000000000 -0800
4+++ gcc-4.5.0/libstdc++-v3/include/c_std/cstdio 2010-06-25 10:51:12.712631679 -0700
5@@ -139,7 +139,7 @@
6
7 _GLIBCXX_END_NAMESPACE
8
9-#if _GLIBCXX_USE_C99
10+#if _GLIBCXX_USE_C99 || defined(__UCLIBC__)
11
12 #undef snprintf
13 #undef vfscanf
diff --git a/recipes-devtools/gcc/gcc-4.5/303-c99-complex-ugly-hack.patch b/recipes-devtools/gcc/gcc-4.5/303-c99-complex-ugly-hack.patch
deleted file mode 100644
index 56aa78cdd2..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/303-c99-complex-ugly-hack.patch
+++ /dev/null
@@ -1,14 +0,0 @@
1Index: gcc-4.5.0/libstdc++-v3/configure
2===================================================================
3--- gcc-4.5.0.orig/libstdc++-v3/configure 2010-06-25 10:48:37.488384191 -0700
4+++ gcc-4.5.0/libstdc++-v3/configure 2010-06-25 10:51:23.804380413 -0700
5@@ -18262,6 +18262,9 @@
6 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
7 /* end confdefs.h. */
8 #include <complex.h>
9+#ifdef __UCLIBC__
10+#error ugly hack to make sure configure test fails here for cross until uClibc supports the complex funcs
11+#endif
12 int
13 main ()
14 {
diff --git a/recipes-devtools/gcc/gcc-4.5/304-index_macro.patch b/recipes-devtools/gcc/gcc-4.5/304-index_macro.patch
deleted file mode 100644
index bbb6563513..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/304-index_macro.patch
+++ /dev/null
@@ -1,28 +0,0 @@
1Index: gcc-4.5.0/libstdc++-v3/include/ext/rope
2===================================================================
3--- gcc-4.5.0.orig/libstdc++-v3/include/ext/rope 2009-04-09 08:00:19.000000000 -0700
4+++ gcc-4.5.0/libstdc++-v3/include/ext/rope 2010-06-25 10:51:33.613383077 -0700
5@@ -54,6 +54,9 @@
6 #include <bits/gthr.h>
7 #include <tr1/functional>
8
9+/* cope w/ index defined as macro, SuSv3 proposal */
10+#undef index
11+
12 # ifdef __GC
13 # define __GC_CONST const
14 # else
15Index: gcc-4.5.0/libstdc++-v3/include/ext/ropeimpl.h
16===================================================================
17--- gcc-4.5.0.orig/libstdc++-v3/include/ext/ropeimpl.h 2009-04-09 08:00:19.000000000 -0700
18+++ gcc-4.5.0/libstdc++-v3/include/ext/ropeimpl.h 2010-06-25 10:51:33.621381669 -0700
19@@ -49,6 +49,9 @@
20 #include <ext/memory> // For uninitialized_copy_n
21 #include <ext/numeric> // For power
22
23+/* cope w/ index defined as macro, SuSv3 proposal */
24+#undef index
25+
26 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
27
28 using std::size_t;
diff --git a/recipes-devtools/gcc/gcc-4.5/305-libmudflap-susv3-legacy.patch b/recipes-devtools/gcc/gcc-4.5/305-libmudflap-susv3-legacy.patch
deleted file mode 100644
index f890acb813..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/305-libmudflap-susv3-legacy.patch
+++ /dev/null
@@ -1,49 +0,0 @@
1Index: gcc-4.5.0/libmudflap/mf-hooks2.c
2===================================================================
3--- gcc-4.5.0.orig/libmudflap/mf-hooks2.c 2009-04-09 08:00:19.000000000 -0700
4+++ gcc-4.5.0/libmudflap/mf-hooks2.c 2010-06-25 10:52:13.937636901 -0700
5@@ -421,7 +421,7 @@
6 {
7 TRACE ("%s\n", __PRETTY_FUNCTION__);
8 MF_VALIDATE_EXTENT(s, n, __MF_CHECK_WRITE, "bzero region");
9- bzero (s, n);
10+ memset (s, 0, n);
11 }
12
13
14@@ -431,7 +431,7 @@
15 TRACE ("%s\n", __PRETTY_FUNCTION__);
16 MF_VALIDATE_EXTENT(src, n, __MF_CHECK_READ, "bcopy src");
17 MF_VALIDATE_EXTENT(dest, n, __MF_CHECK_WRITE, "bcopy dest");
18- bcopy (src, dest, n);
19+ memmove (dest, src, n);
20 }
21
22
23@@ -441,7 +441,7 @@
24 TRACE ("%s\n", __PRETTY_FUNCTION__);
25 MF_VALIDATE_EXTENT(s1, n, __MF_CHECK_READ, "bcmp 1st arg");
26 MF_VALIDATE_EXTENT(s2, n, __MF_CHECK_READ, "bcmp 2nd arg");
27- return bcmp (s1, s2, n);
28+ return n == 0 ? 0 : memcmp (s1, s2, n);
29 }
30
31
32@@ -450,7 +450,7 @@
33 size_t n = strlen (s);
34 TRACE ("%s\n", __PRETTY_FUNCTION__);
35 MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "index region");
36- return index (s, c);
37+ return strchr (s, c);
38 }
39
40
41@@ -459,7 +459,7 @@
42 size_t n = strlen (s);
43 TRACE ("%s\n", __PRETTY_FUNCTION__);
44 MF_VALIDATE_EXTENT(s, CLAMPADD(n, 1), __MF_CHECK_READ, "rindex region");
45- return rindex (s, c);
46+ return strrchr (s, c);
47 }
48
49 /* XXX: stpcpy, memccpy */
diff --git a/recipes-devtools/gcc/gcc-4.5/306-libstdc++-namespace.patch b/recipes-devtools/gcc/gcc-4.5/306-libstdc++-namespace.patch
deleted file mode 100644
index 75c7401373..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/306-libstdc++-namespace.patch
+++ /dev/null
@@ -1,38 +0,0 @@
1Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/messages_members.h
2===================================================================
3--- gcc-4.5.0.orig/libstdc++-v3/config/locale/uclibc/messages_members.h 2010-06-25 10:49:07.024632961 -0700
4+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/messages_members.h 2010-06-25 10:52:33.980632645 -0700
5@@ -32,7 +32,8 @@
6 //
7
8 // Written by Benjamin Kosnik <bkoz@redhat.com>
9-
10+namespace std
11+{
12 #ifdef __UCLIBC_MJN3_ONLY__
13 #warning fix prototypes for *textdomain funcs
14 #endif
15@@ -116,3 +117,4 @@
16 this->_S_create_c_locale(this->_M_c_locale_messages, __s);
17 }
18 }
19+}
20Index: gcc-4.5.0/libstdc++-v3/config/locale/uclibc/time_members.h
21===================================================================
22--- gcc-4.5.0.orig/libstdc++-v3/config/locale/uclibc/time_members.h 2010-06-25 10:49:07.024632961 -0700
23+++ gcc-4.5.0/libstdc++-v3/config/locale/uclibc/time_members.h 2010-06-25 10:52:33.980632645 -0700
24@@ -33,7 +33,8 @@
25 //
26
27 // Written by Benjamin Kosnik <bkoz@redhat.com>
28-
29+namespace std
30+{
31 template<typename _CharT>
32 __timepunct<_CharT>::__timepunct(size_t __refs)
33 : facet(__refs), _M_data(NULL), _M_c_locale_timepunct(NULL),
34@@ -75,3 +76,4 @@
35 delete _M_data;
36 _S_destroy_c_locale(_M_c_locale_timepunct);
37 }
38+}
diff --git a/recipes-devtools/gcc/gcc-4.5/307-locale_facets.patch b/recipes-devtools/gcc/gcc-4.5/307-locale_facets.patch
deleted file mode 100644
index 774fcfa2ca..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/307-locale_facets.patch
+++ /dev/null
@@ -1,19 +0,0 @@
1This patch fixes a bug into ostream::operator<<(double) due to the wrong size
2passed into the __convert_from_v method. The wrong size is then passed to
3std::snprintf function, that, on uClibc, doens't handle sized 0 buffer.
4
5Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
6
7Index: gcc-4.3.1/libstdc++-v3/include/bits/locale_facets.tcc
8===================================================================
9--- gcc-4.3.1.orig/libstdc++-v3/include/bits/locale_facets.tcc 2007-11-26 17:59:41.000000000 -0800
10+++ gcc-4.3.1/libstdc++-v3/include/bits/locale_facets.tcc 2008-08-16 02:14:48.000000000 -0700
11@@ -1004,7 +1004,7 @@
12 const int __cs_size = __fixed ? __max_exp + __prec + 4
13 : __max_digits * 2 + __prec;
14 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
15- __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf,
16+ __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, __fbuf,
17 __prec, __v);
18 #endif
19
diff --git a/recipes-devtools/gcc/gcc-4.5/arm-bswapsi2.patch b/recipes-devtools/gcc/gcc-4.5/arm-bswapsi2.patch
deleted file mode 100644
index 7ac61a6d63..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/arm-bswapsi2.patch
+++ /dev/null
@@ -1,13 +0,0 @@
1Index: gcc-4.5/gcc/config/arm/arm.md
2===================================================================
3--- gcc-4.5.orig/gcc/config/arm/arm.md 2010-06-17 09:13:07.000000000 -0700
4+++ gcc-4.5/gcc/config/arm/arm.md 2010-06-22 08:08:45.397212002 -0700
5@@ -11267,7 +11267,7 @@
6 (define_expand "bswapsi2"
7 [(set (match_operand:SI 0 "s_register_operand" "=r")
8 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
9-"TARGET_EITHER"
10+"TARGET_EITHER && (arm_arch6 && !optimize_size)"
11 "
12 if (!arm_arch6)
13 {
diff --git a/recipes-devtools/gcc/gcc-4.5/arm-lib1funcs.as-fix-mismatch-between-conditions-of-an-IT-block.patch b/recipes-devtools/gcc/gcc-4.5/arm-lib1funcs.as-fix-mismatch-between-conditions-of-an-IT-block.patch
new file mode 100644
index 0000000000..39c90e7e74
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/arm-lib1funcs.as-fix-mismatch-between-conditions-of-an-IT-block.patch
@@ -0,0 +1,18 @@
1Fix for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43999
2
3http://patchwork.ozlabs.org/patch/72260/ is the patch that made into
4upstream gcc
5
6diff --git a/gcc/config/arm/lib1funcs.asm b/gcc/config/arm/lib1funcs.asm
7index 085e690..2e76c01 100644
8--- a/gcc/config/arm/lib1funcs.asm
9+++ b/gcc/config/arm/lib1funcs.asm
10@@ -641,7 +641,7 @@ pc .req r15
11 subhs \dividend, \dividend, \divisor, lsr #3
12 orrhs \result, \result, \curbit, lsr #3
13 cmp \dividend, #0 @ Early termination?
14- do_it hs, t
15+ do_it ne, t
16 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
17 movne \divisor, \divisor, lsr #4
18 bne 1b
diff --git a/recipes-devtools/gcc/gcc-4.5/arm-nolibfloat.patch b/recipes-devtools/gcc/gcc-4.5/arm-nolibfloat.patch
deleted file mode 100644
index 99f2b20d50..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/arm-nolibfloat.patch
+++ /dev/null
@@ -1,24 +0,0 @@
1# Dimitry Andric <dimitry@andric.com>, 2004-05-01
2#
3# * Removed the extra -lfloat option from LIBGCC_SPEC, since it isn't needed
4# anymore. (The required functions are now in libgcc.)
5#
6# Fixes errors like
7# arm-softfloat-linux-gnu/3.4.0/../../../../arm-softfloat-linux-gnu/bin/ld: cannot find -lfloat
8# collect2: ld returned 1 exit status
9# make[2]: *** [arm-softfloat-linux-gnu/gcc-3.4.0-glibc-2.3.2/build-glibc/iconvdata/ISO8859-1.so] Error 1
10# when building glibc-2.3.3 with gcc-3.4.0 for arm-softfloat
11
12Index: gcc-4.5.0/gcc/config/arm/linux-elf.h
13===================================================================
14--- gcc-4.5.0.orig/gcc/config/arm/linux-elf.h 2010-06-25 11:04:49.572437901 -0700
15+++ gcc-4.5.0/gcc/config/arm/linux-elf.h 2010-06-25 11:06:12.273162283 -0700
16@@ -60,7 +60,7 @@
17 %{shared:-lc} \
18 %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
19
20-#define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc"
21+#define LIBGCC_SPEC "-lgcc"
22
23 #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
24
diff --git a/recipes-devtools/gcc/gcc-4.5/arm-softfloat.patch b/recipes-devtools/gcc/gcc-4.5/arm-softfloat.patch
deleted file mode 100644
index 181d4fbf5a..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/arm-softfloat.patch
+++ /dev/null
@@ -1,16 +0,0 @@
1Index: gcc-4.5.0/gcc/config/arm/t-linux
2===================================================================
3--- gcc-4.5.0.orig/gcc/config/arm/t-linux 2009-04-21 12:03:23.000000000 -0700
4+++ gcc-4.5.0/gcc/config/arm/t-linux 2010-06-25 11:11:06.836381365 -0700
5@@ -23,7 +23,10 @@
6
7 LIB1ASMSRC = arm/lib1funcs.asm
8 LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \
9- _arm_addsubdf3 _arm_addsubsf3
10+ _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
11+ _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
12+ _fixsfsi _fixunssfsi _floatdidf _floatdisf _floatundisf _floatundidf
13+# _arm_addsubdf3 _arm_addsubsf3
14
15 # MULTILIB_OPTIONS = mhard-float/msoft-float
16 # MULTILIB_DIRNAMES = hard-float soft-float
diff --git a/recipes-devtools/gcc/gcc-4.5/gcc-4.3.3-SYSROOT_CFLAGS_FOR_TARGET.patch b/recipes-devtools/gcc/gcc-4.5/gcc-4.3.3-SYSROOT_CFLAGS_FOR_TARGET.patch
deleted file mode 100644
index af0b81ba4c..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/gcc-4.3.3-SYSROOT_CFLAGS_FOR_TARGET.patch
+++ /dev/null
@@ -1,114 +0,0 @@
1Before committing, I noticed that PR/32161 was marked as a dup of PR/32009, but my previous patch did not fix it.
2
3This alternative patch is better because it lets you just use CFLAGS_FOR_TARGET to set the compilation flags for libgcc. Since bootstrapped target libraries are never compiled with the native compiler, it makes little sense to use different flags for stage1 and later stages. And it also makes little sense to use a different variable than CFLAGS_FOR_TARGET.
4
5Other changes I had to do include:
6
7- moving the creation of default CFLAGS_FOR_TARGET from Makefile.am to configure.ac, because otherwise the BOOT_CFLAGS are substituted into CFLAGS_FOR_TARGET (which is "-O2 -g $(CFLAGS)") via $(CFLAGS). It is also cleaner this way though.
8
9- passing the right CFLAGS to configure scripts as exported environment variables
10
11I also stopped passing LIBCFLAGS to configure scripts since they are unused in the whole src tree. And I updated the documentation as H-P reminded me to do.
12
13Bootstrapped/regtested i686-pc-linux-gnu, will commit to 4.4 shortly. Ok for 4.3?
14
15Paolo
16
172008-02-19 Paolo Bonzini <bonzini@gnu.org>
18
19 PR bootstrap/32009
20 PR bootstrap/32161
21
22 * configure.ac (CFLAGS_FOR_TARGET, CXXFLAGS_FOR_TARGET): Compute here.
23 * configure: Regenerate.
24
25 * Makefile.def: Define stage_libcflags for all bootstrap stages.
26 * Makefile.tpl (BOOT_LIBCFLAGS, STAGE2_LIBCFLAGS, STAGE3_LIBCFLAGS,
27 STAGE4_LIBCFLAGS): New.
28 (CFLAGS_FOR_TARGET, CXXFLAGS_FOR_TARGET): Subst from autoconf, without
29 $(SYSROOT_CFLAGS_FOR_TARGET) and $(DEBUG_PREFIX_CFLAGS_FOR_TARGET).
30 (BASE_TARGET_EXPORTS): Append them here to C{,XX}FLAGS.
31 (EXTRA_TARGET_FLAGS): Append them here to {LIB,}C{,XX}FLAGS.
32 (configure-stage[+id+]-[+prefix+][+module+]): Pass stage_libcflags
33 for target modules. Don't export LIBCFLAGS.
34 (all-stage[+id+]-[+prefix+][+module+]): Pass stage_libcflags; pass
35 $(BASE_FLAGS_TO_PASS) where [+args+] was passed, and [+args+] after
36 the overridden CFLAGS_FOR_TARGET and CXXFLAGS_FOR_TARGET.
37 (invocations of `all'): Replace $(TARGET_FLAGS_TO_PASS) with
38 $(EXTRA_TARGET_FLAGS), $(FLAGS_TO_PASS) with $(EXTRA_HOST_FLAGS).
39 * Makefile.in: Regenerate.
40
41config:
422008-02-19 Paolo Bonzini <bonzini@gnu.org>
43
44 PR bootstrap/32009
45 * mh-ppc-darwin (BOOT_CFLAGS): Reenable.
46
47gcc:
482008-02-19 Paolo Bonzini <bonzini@gnu.org>
49
50 PR bootstrap/32009
51 * doc/install.texi: Correct references to CFLAGS, replacing them
52 with BOOT_CFLAGS. Document flags used during bootstrap for
53 target libraries.
54
55
56---
57 Makefile.def | 25
58 Makefile.in | 1845 ++++++++++++++++++++++++++++++-------------------
59 Makefile.tpl | 91 +-
60 config/mh-ppc-darwin | 3
61 configure | 36
62 configure.ac | 32
63 gcc/Makefile.in | 2
64 gcc/configure | 6
65 gcc/configure.ac | 3
66 gcc/doc/install.texi | 56 -
67 libiberty/Makefile.in | 162 ++--
68 libiberty/configure | 46 -
69 libiberty/configure.ac | 43 -
70 13 files changed, 1454 insertions(+), 896 deletions(-)
71
72Index: gcc-4.5.0/configure
73===================================================================
74--- gcc-4.5.0.orig/configure 2010-06-25 14:51:59.409382073 -0700
75+++ gcc-4.5.0/configure 2010-06-25 14:52:35.157132702 -0700
76@@ -7130,6 +7130,38 @@
77 fi
78
79
80+# During gcc bootstrap, if we use some random cc for stage1 then CFLAGS
81+# might be empty or "-g". We don't require a C++ compiler, so CXXFLAGS
82+# might also be empty (or "-g", if a non-GCC C++ compiler is in the path).
83+# We want to ensure that TARGET libraries (which we know are built with
84+# gcc) are built with "-O2 -g", so include those options when setting
85+# CFLAGS_FOR_TARGET and CXXFLAGS_FOR_TARGET.
86+if test "x$CFLAGS_FOR_TARGET" = x; then
87+ CFLAGS_FOR_TARGET=$CFLAGS
88+ case " $CFLAGS " in
89+ *" -O2 "*) ;;
90+ *) CFLAGS_FOR_TARGET="-O2 $CFLAGS" ;;
91+ esac
92+ case " $CFLAGS " in
93+ *" -g "* | *" -g3 "*) ;;
94+ *) CFLAGS_FOR_TARGET="-g $CFLAGS" ;;
95+ esac
96+fi
97+
98+
99+if test "x$CXXFLAGS_FOR_TARGET" = x; then
100+ CXXFLAGS_FOR_TARGET=$CXXFLAGS
101+ case " $CXXFLAGS " in
102+ *" -O2 "*) ;;
103+ *) CXXFLAGS_FOR_TARGET="-O2 $CXXFLAGS" ;;
104+ esac
105+ case " $CXXFLAGS " in
106+ *" -g "* | *" -g3 "*) ;;
107+ *) CXXFLAGS_FOR_TARGET="-g $CXXFLAGS" ;;
108+ esac
109+fi
110+
111+
112 # Handle --with-headers=XXX. If the value is not "yes", the contents of
113 # the named directory are copied to $(tooldir)/sys-include.
114 if test x"${with_headers}" != x && test x"${with_headers}" != xno ; then
diff --git a/recipes-devtools/gcc/gcc-4.5/gcc-arm-frename-registers.patch b/recipes-devtools/gcc/gcc-4.5/gcc-arm-frename-registers.patch
deleted file mode 100644
index 280b90358e..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/gcc-arm-frename-registers.patch
+++ /dev/null
@@ -1,25 +0,0 @@
1http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35964
2Index: gcc-4.3.0/gcc/regrename.c
3===================================================================
4--- gcc-4.3.0.orig/gcc/regrename.c 2008-05-28 08:31:15.000000000 -0700
5+++ gcc-4.3.0/gcc/regrename.c 2008-05-28 08:34:00.000000000 -0700
6@@ -782,6 +782,10 @@
7 || (predicated && recog_data.operand_type[i] == OP_OUT))
8 recog_data.operand_type[i] = OP_INOUT;
9 }
10+ /* Unshare dup_loc RTL */
11+ for (i = 0; i < recog_data.n_dups; i++)
12+ *recog_data.dup_loc[i] = copy_rtx(*recog_data.dup_loc[i]);
13+
14
15 /* Step 1: Close chains for which we have overlapping reads. */
16 for (i = 0; i < n_ops; i++)
17@@ -813,7 +817,7 @@
18 OP_IN, 0);
19
20 for (i = 0; i < recog_data.n_dups; i++)
21- *recog_data.dup_loc[i] = copy_rtx (old_dups[i]);
22+ *recog_data.dup_loc[i] = old_dups[i];
23 for (i = 0; i < n_ops; i++)
24 *recog_data.operand_loc[i] = old_operands[i];
25 if (recog_data.n_dups)
diff --git a/recipes-devtools/gcc/gcc-4.5/gcc-linaro-fix-lp-653316.patch b/recipes-devtools/gcc/gcc-4.5/gcc-linaro-fix-lp-653316.patch
deleted file mode 100644
index 72a221b1d2..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/gcc-linaro-fix-lp-653316.patch
+++ /dev/null
@@ -1,130 +0,0 @@
12010-10-15 Chung-Lin Tang <cltang@codesourcery.com>
2
3 Backport from mainline:
4
5 2010-10-15 Chung-Lin Tang <cltang@codesourcery.com>
6
7 gcc/
8 * ifcvt.c (find_active_insn_before): New function.
9 (find_active_insn_after): New function.
10 (cond_exec_process_if_block): Use new functions to replace
11 prev_active_insn() and next_active_insn().
12
13 gcc/testsuite/
14 * gcc.dg/20101010-1.c: New testcase.
15
16=== modified file 'gcc/ifcvt.c'
17Index: gcc-4.5/gcc/ifcvt.c
18===================================================================
19--- gcc-4.5.orig/gcc/ifcvt.c
20+++ gcc-4.5/gcc/ifcvt.c
21@@ -88,6 +88,8 @@ static int count_bb_insns (const_basic_b
22 static bool cheap_bb_rtx_cost_p (const_basic_block, int);
23 static rtx first_active_insn (basic_block);
24 static rtx last_active_insn (basic_block, int);
25+static rtx find_active_insn_before (basic_block, rtx);
26+static rtx find_active_insn_after (basic_block, rtx);
27 static basic_block block_fallthru (basic_block);
28 static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
29 static rtx cond_exec_get_condition (rtx);
30@@ -230,6 +232,48 @@ last_active_insn (basic_block bb, int sk
31 return insn;
32 }
33
34+/* Return the active insn before INSN inside basic block CURR_BB. */
35+
36+static rtx
37+find_active_insn_before (basic_block curr_bb, rtx insn)
38+{
39+ if (!insn || insn == BB_HEAD (curr_bb))
40+ return NULL_RTX;
41+
42+ while ((insn = PREV_INSN (insn)) != NULL_RTX)
43+ {
44+ if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
45+ break;
46+
47+ /* No other active insn all the way to the start of the basic block. */
48+ if (insn == BB_HEAD (curr_bb))
49+ return NULL_RTX;
50+ }
51+
52+ return insn;
53+}
54+
55+/* Return the active insn after INSN inside basic block CURR_BB. */
56+
57+static rtx
58+find_active_insn_after (basic_block curr_bb, rtx insn)
59+{
60+ if (!insn || insn == BB_END (curr_bb))
61+ return NULL_RTX;
62+
63+ while ((insn = NEXT_INSN (insn)) != NULL_RTX)
64+ {
65+ if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
66+ break;
67+
68+ /* No other active insn all the way to the end of the basic block. */
69+ if (insn == BB_END (curr_bb))
70+ return NULL_RTX;
71+ }
72+
73+ return insn;
74+}
75+
76 /* Return the basic block reached by falling though the basic block BB. */
77
78 static basic_block
79@@ -448,9 +492,9 @@ cond_exec_process_if_block (ce_if_block_
80 if (n_matching > 0)
81 {
82 if (then_end)
83- then_end = prev_active_insn (then_first_tail);
84+ then_end = find_active_insn_before (then_bb, then_first_tail);
85 if (else_end)
86- else_end = prev_active_insn (else_first_tail);
87+ else_end = find_active_insn_before (else_bb, else_first_tail);
88 n_insns -= 2 * n_matching;
89 }
90
91@@ -488,9 +532,9 @@ cond_exec_process_if_block (ce_if_block_
92 if (n_matching > 0)
93 {
94 if (then_start)
95- then_start = next_active_insn (then_last_head);
96+ then_start = find_active_insn_after (then_bb, then_last_head);
97 if (else_start)
98- else_start = next_active_insn (else_last_head);
99+ else_start = find_active_insn_after (else_bb, else_last_head);
100 n_insns -= 2 * n_matching;
101 }
102 }
103@@ -646,7 +690,7 @@ cond_exec_process_if_block (ce_if_block_
104 {
105 rtx from = then_first_tail;
106 if (!INSN_P (from))
107- from = next_active_insn (from);
108+ from = find_active_insn_after (then_bb, from);
109 delete_insn_chain (from, BB_END (then_bb), false);
110 }
111 if (else_last_head)
112Index: gcc-4.5/gcc/testsuite/gcc.dg/20101010-1.c
113===================================================================
114--- /dev/null
115+++ gcc-4.5/gcc/testsuite/gcc.dg/20101010-1.c
116@@ -0,0 +1,14 @@
117+/* { dg-do compile } */
118+/* { dg-options "-O2 -fno-crossjumping" } */
119+
120+int foo (void)
121+{
122+ int len;
123+ if (bar1 (&len))
124+ {
125+ char devpath [len];
126+ if (bar2 (devpath) == len)
127+ return len;
128+ }
129+ return -1;
130+}
diff --git a/recipes-devtools/gcc/gcc-4.5/gcc-vmovl-PR45805.patch b/recipes-devtools/gcc/gcc-4.5/gcc-vmovl-PR45805.patch
deleted file mode 100644
index e228cb754c..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/gcc-vmovl-PR45805.patch
+++ /dev/null
@@ -1,27 +0,0 @@
1Source: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45805
2
3Index: gcc-4.5/gcc/config/arm/neon.md
4===================================================================
5--- gcc-4.5.orig/gcc/config/arm/neon.md 2010-09-28 12:04:38.000000000 -0700
6+++ gcc-4.5/gcc/config/arm/neon.md 2010-09-28 12:07:28.026227000 -0700
7@@ -5682,9 +5682,9 @@
8 ;; Vectorize for non-neon-quad case
9 (define_insn "neon_unpack<US>_<mode>"
10 [(set (match_operand:<V_widen> 0 "register_operand" "=w")
11- (SE:<V_widen> (match_operand:VDI 1 "register_operand" "")))]
12+ (SE:<V_widen> (match_operand:VDI 1 "register_operand" "w")))]
13 "TARGET_NEON"
14- "vmovl.<US><V_sz_elem> %q0, %1"
15+ "vmovl.<US><V_sz_elem> %q0, %P1"
16 [(set_attr "neon_type" "neon_shift_1")]
17 )
18
19@@ -5721,7 +5721,7 @@
20 (SE:<V_widen>
21 (match_operand:VDI 2 "register_operand" "w"))))]
22 "TARGET_NEON"
23- "vmull.<US><V_sz_elem> %q0, %1, %2"
24+ "vmull.<US><V_sz_elem> %q0, %P1, %P2"
25 [(set_attr "neon_type" "neon_shift_1")]
26 )
27
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99351.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99351.patch
index a1a2c2ad81..aa3b3eb85f 100644
--- a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99351.patch
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99351.patch
@@ -1,3 +1,11 @@
12010-07-26 Julian Brown <julian@codesourcery.com>
2
3 Merge from Sourcery G++ 4.4:
4
5 Jie Zhang <jie@codesourcery.com>
6 Issue #7122
7
8 gcc/
1 * config/arm/arm.c (arm_rtx_costs_1): Adjust cost for 9 * config/arm/arm.c (arm_rtx_costs_1): Adjust cost for
2 CONST_VECTOR. 10 CONST_VECTOR.
3 (arm_size_rtx_costs): Likewise. 11 (arm_size_rtx_costs): Likewise.
@@ -25,18 +33,6 @@
25 * gcc.target/arm/neon-vdup-18.c: New test case. 33 * gcc.target/arm/neon-vdup-18.c: New test case.
26 * gcc.target/arm/neon-vdup-19.c: New test case. 34 * gcc.target/arm/neon-vdup-19.c: New test case.
27 35
282010-07-26 Julian Brown <julian@codesourcery.com>
29
30 Merge from Sourcery G++ 4.4:
31
32 Jie Zhang <jie@codesourcery.com>
33
34 Issue #7122
35
36 gcc/
37 * config/arm/vfp.md (movdf_vfp): Add load double 0.0 case.
38 (thumb2_movdf_vfp): Likewise. Require that one of the operands be a
39 register.
40 36
41=== modified file 'gcc/config/arm/arm.c' 37=== modified file 'gcc/config/arm/arm.c'
42--- old/gcc/config/arm/arm.c 2010-08-13 10:55:28 +0000 38--- old/gcc/config/arm/arm.c 2010-08-13 10:55:28 +0000
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99352.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99352.patch
index 675c2f3ceb..8d48ada2fd 100644
--- a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99352.patch
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99352.patch
@@ -1,3 +1,7 @@
12010-07-26 Julian Brown <julian@codesourcery.com>
2
3 Merge from Sourcery G++ 4.4:
4
1 2010-04-07 Thomas Schwinge <thomas@codesourcery.com> 5 2010-04-07 Thomas Schwinge <thomas@codesourcery.com>
2 Daniel Jacobowitz <dan@codesourcery.com> 6 Daniel Jacobowitz <dan@codesourcery.com>
3 7
@@ -13,13 +17,6 @@
13 * config/arm/arm.h (DWARF2_UNWIND_INFO): Remove definition. 17 * config/arm/arm.h (DWARF2_UNWIND_INFO): Remove definition.
14 * config/arm/bpabi.h (DWARF2_UNWIND_INFO): Define to zero. 18 * config/arm/bpabi.h (DWARF2_UNWIND_INFO): Define to zero.
15 19
162010-07-26 Julian Brown <julian@codesourcery.com>
17
18 Merge from Sourcery G++ 4.4:
19
20 Jie Zhang <jie@codesourcery.com>
21
22 Issue #7122
23 20
24=== modified file 'gcc/config/arm/arm.h' 21=== modified file 'gcc/config/arm/arm.h'
25--- old/gcc/config/arm/arm.h 2010-08-13 10:30:35 +0000 22--- old/gcc/config/arm/arm.h 2010-08-13 10:30:35 +0000
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
deleted file mode 100644
index 9f3d47f38b..0000000000
--- a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99448.patch
+++ /dev/null
@@ -1,147 +0,0 @@
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-r99464.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99464.patch
new file mode 100644
index 0000000000..e8c8e63883
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99464.patch
@@ -0,0 +1,157 @@
1 LP: #681138
2 Backport from mainline:
3
4 gcc/
5 * config/arm/sync.md (sync_clobber, sync_t2_reqd): New code attribute.
6 (arm_sync_old_<sync_optab>si, arm_sync_old_<sync_optab><mode>): Use
7 the sync_clobber and sync_t2_reqd code attributes.
8 * config/arm/arm.c (arm_output_sync_loop): Reverse the operation if
9 the t2 argument is NULL.
10
11=== modified file 'gcc/config/arm/arm.c'
12Index: gcc-4_5-branch/gcc/config/arm/arm.c
13===================================================================
14--- gcc-4_5-branch.orig/gcc/config/arm/arm.c
15+++ gcc-4_5-branch/gcc/config/arm/arm.c
16@@ -23098,10 +23098,46 @@ arm_output_sync_loop (emit_f emit,
17 break;
18 }
19
20- arm_output_strex (emit, mode, "", t2, t1, memory);
21- operands[0] = t2;
22- arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
23- arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=", LOCAL_LABEL_PREFIX);
24+ if (t2)
25+ {
26+ arm_output_strex (emit, mode, "", t2, t1, memory);
27+ operands[0] = t2;
28+ arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
29+ arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
30+ LOCAL_LABEL_PREFIX);
31+ }
32+ else
33+ {
34+ /* Use old_value for the return value because for some operations
35+ the old_value can easily be restored. This saves one register. */
36+ arm_output_strex (emit, mode, "", old_value, t1, memory);
37+ operands[0] = old_value;
38+ arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
39+ arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
40+ LOCAL_LABEL_PREFIX);
41+
42+ switch (sync_op)
43+ {
44+ case SYNC_OP_ADD:
45+ arm_output_op3 (emit, "sub", old_value, t1, new_value);
46+ break;
47+
48+ case SYNC_OP_SUB:
49+ arm_output_op3 (emit, "add", old_value, t1, new_value);
50+ break;
51+
52+ case SYNC_OP_XOR:
53+ arm_output_op3 (emit, "eor", old_value, t1, new_value);
54+ break;
55+
56+ case SYNC_OP_NONE:
57+ arm_output_op2 (emit, "mov", old_value, required_value);
58+ break;
59+
60+ default:
61+ gcc_unreachable ();
62+ }
63+ }
64
65 arm_process_output_memory_barrier (emit, NULL);
66 arm_output_asm_insn (emit, 1, operands, "%sLSYB%%=:", LOCAL_LABEL_PREFIX);
67Index: gcc-4_5-branch/gcc/config/arm/sync.md
68===================================================================
69--- gcc-4_5-branch.orig/gcc/config/arm/sync.md
70+++ gcc-4_5-branch/gcc/config/arm/sync.md
71@@ -103,6 +103,18 @@
72 (plus "add")
73 (minus "sub")])
74
75+(define_code_attr sync_clobber [(ior "=&r")
76+ (and "=&r")
77+ (xor "X")
78+ (plus "X")
79+ (minus "X")])
80+
81+(define_code_attr sync_t2_reqd [(ior "4")
82+ (and "4")
83+ (xor "*")
84+ (plus "*")
85+ (minus "*")])
86+
87 (define_expand "sync_<sync_optab>si"
88 [(match_operand:SI 0 "memory_operand")
89 (match_operand:SI 1 "s_register_operand")
90@@ -286,7 +298,6 @@
91 VUNSPEC_SYNC_COMPARE_AND_SWAP))
92 (set (match_dup 1) (unspec_volatile:SI [(match_dup 2)]
93 VUNSPEC_SYNC_COMPARE_AND_SWAP))
94- (clobber:SI (match_scratch:SI 4 "=&r"))
95 (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
96 VUNSPEC_SYNC_COMPARE_AND_SWAP))
97 ]
98@@ -299,7 +310,6 @@
99 (set_attr "sync_required_value" "2")
100 (set_attr "sync_new_value" "3")
101 (set_attr "sync_t1" "0")
102- (set_attr "sync_t2" "4")
103 (set_attr "conds" "clob")
104 (set_attr "predicable" "no")])
105
106@@ -313,7 +323,6 @@
107 VUNSPEC_SYNC_COMPARE_AND_SWAP)))
108 (set (match_dup 1) (unspec_volatile:NARROW [(match_dup 2)]
109 VUNSPEC_SYNC_COMPARE_AND_SWAP))
110- (clobber:SI (match_scratch:SI 4 "=&r"))
111 (set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
112 VUNSPEC_SYNC_COMPARE_AND_SWAP))
113 ]
114@@ -326,7 +335,6 @@
115 (set_attr "sync_required_value" "2")
116 (set_attr "sync_new_value" "3")
117 (set_attr "sync_t1" "0")
118- (set_attr "sync_t2" "4")
119 (set_attr "conds" "clob")
120 (set_attr "predicable" "no")])
121
122@@ -487,7 +495,7 @@
123 VUNSPEC_SYNC_OLD_OP))
124 (clobber (reg:CC CC_REGNUM))
125 (clobber (match_scratch:SI 3 "=&r"))
126- (clobber (match_scratch:SI 4 "=&r"))]
127+ (clobber (match_scratch:SI 4 "<sync_clobber>"))]
128 "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
129 {
130 return arm_output_sync_insn (insn, operands);
131@@ -496,7 +504,7 @@
132 (set_attr "sync_memory" "1")
133 (set_attr "sync_new_value" "2")
134 (set_attr "sync_t1" "3")
135- (set_attr "sync_t2" "4")
136+ (set_attr "sync_t2" "<sync_t2_reqd>")
137 (set_attr "sync_op" "<sync_optab>")
138 (set_attr "conds" "clob")
139 (set_attr "predicable" "no")])
140@@ -540,7 +548,7 @@
141 VUNSPEC_SYNC_OLD_OP))
142 (clobber (reg:CC CC_REGNUM))
143 (clobber (match_scratch:SI 3 "=&r"))
144- (clobber (match_scratch:SI 4 "=&r"))]
145+ (clobber (match_scratch:SI 4 "<sync_clobber>"))]
146 "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
147 {
148 return arm_output_sync_insn (insn, operands);
149@@ -549,7 +557,7 @@
150 (set_attr "sync_memory" "1")
151 (set_attr "sync_new_value" "2")
152 (set_attr "sync_t1" "3")
153- (set_attr "sync_t2" "4")
154+ (set_attr "sync_t2" "<sync_t2_reqd>")
155 (set_attr "sync_op" "<sync_optab>")
156 (set_attr "conds" "clob")
157 (set_attr "predicable" "no")])
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99465.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99465.patch
new file mode 100644
index 0000000000..32c2999a7c
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99465.patch
@@ -0,0 +1,94 @@
12011-01-18 Ulrich Weigand <uweigand@de.ibm.com>
2
3 LP: #685352
4 Backport from mainline:
5
6 2011-01-18 Jakub Jelinek <jakub@redhat.com>
7
8 gcc/
9 PR rtl-optimization/47299
10 * expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: Don't use
11 subtarget. Use normal multiplication if both operands are
12 constants.
13 * expmed.c (expand_widening_mult): Don't try to optimize constant
14 multiplication if op0 has VOIDmode. Convert op1 constant to mode
15 before using it.
16
17 gcc/testsuite/
18 PR rtl-optimization/47299
19 * gcc.c-torture/execute/pr47299.c: New test.
20
21=== modified file 'gcc/expmed.c'
22Index: gcc-4_5-branch/gcc/expmed.c
23===================================================================
24--- gcc-4_5-branch.orig/gcc/expmed.c
25+++ gcc-4_5-branch/gcc/expmed.c
26@@ -3355,12 +3355,17 @@ expand_widening_mult (enum machine_mode
27 int unsignedp, optab this_optab)
28 {
29 bool speed = optimize_insn_for_speed_p ();
30+ rtx cop1;
31
32 if (CONST_INT_P (op1)
33- && (INTVAL (op1) >= 0
34+ && GET_MODE (op0) != VOIDmode
35+ && (cop1 = convert_modes (mode, GET_MODE (op0), op1,
36+ this_optab == umul_widen_optab))
37+ && CONST_INT_P (cop1)
38+ && (INTVAL (cop1) >= 0
39 || GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT))
40 {
41- HOST_WIDE_INT coeff = INTVAL (op1);
42+ HOST_WIDE_INT coeff = INTVAL (cop1);
43 int max_cost;
44 enum mult_variant variant;
45 struct algorithm algorithm;
46Index: gcc-4_5-branch/gcc/expr.c
47===================================================================
48--- gcc-4_5-branch.orig/gcc/expr.c
49+++ gcc-4_5-branch/gcc/expr.c
50@@ -7624,10 +7624,10 @@ expand_expr_real_2 (sepops ops, rtx targ
51 if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
52 {
53 if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
54- expand_operands (treeop0, treeop1, subtarget, &op0, &op1,
55+ expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
56 EXPAND_NORMAL);
57 else
58- expand_operands (treeop0, treeop1, subtarget, &op1, &op0,
59+ expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0,
60 EXPAND_NORMAL);
61 goto binop3;
62 }
63@@ -7645,7 +7645,8 @@ expand_expr_real_2 (sepops ops, rtx targ
64 optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
65 this_optab = zextend_p ? umul_widen_optab : smul_widen_optab;
66
67- if (mode == GET_MODE_2XWIDER_MODE (innermode))
68+ if (mode == GET_MODE_2XWIDER_MODE (innermode)
69+ && TREE_CODE (treeop0) != INTEGER_CST)
70 {
71 if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
72 {
73Index: gcc-4_5-branch/gcc/testsuite/gcc.c-torture/execute/pr47299.c
74===================================================================
75--- /dev/null
76+++ gcc-4_5-branch/gcc/testsuite/gcc.c-torture/execute/pr47299.c
77@@ -0,0 +1,17 @@
78+/* PR rtl-optimization/47299 */
79+
80+extern void abort (void);
81+
82+__attribute__ ((noinline, noclone)) unsigned short
83+foo (unsigned char x)
84+{
85+ return x * 255;
86+}
87+
88+int
89+main ()
90+{
91+ if (foo (0x40) != 0x3fc0)
92+ abort ();
93+ return 0;
94+}
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99466.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99466.patch
new file mode 100644
index 0000000000..580d4f4724
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99466.patch
@@ -0,0 +1,38 @@
12011-01-19 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
2
3 Backport from FSF mainline
4
5 2011-01-18 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
6
7 * config/arm/cortex-a9.md (cortex-a9-neon.md): Actually
8 include.
9 (cortex_a9_dp): Handle neon types correctly.
10
11=== modified file 'gcc/config/arm/cortex-a9.md'
12Index: gcc-4_5-branch/gcc/config/arm/cortex-a9.md
13===================================================================
14--- gcc-4_5-branch.orig/gcc/config/arm/cortex-a9.md
15+++ gcc-4_5-branch/gcc/config/arm/cortex-a9.md
16@@ -79,10 +79,11 @@ cortex_a9_p1_e2 + cortex_a9_p0_e1 + cort
17 ;; which can go down E2 without any problem.
18 (define_insn_reservation "cortex_a9_dp" 2
19 (and (eq_attr "tune" "cortexa9")
20- (ior (eq_attr "type" "alu")
21- (ior (and (eq_attr "type" "alu_shift_reg, alu_shift")
22- (eq_attr "insn" "mov"))
23- (eq_attr "neon_type" "none"))))
24+ (ior (and (eq_attr "type" "alu")
25+ (eq_attr "neon_type" "none"))
26+ (and (and (eq_attr "type" "alu_shift_reg, alu_shift")
27+ (eq_attr "insn" "mov"))
28+ (eq_attr "neon_type" "none"))))
29 "cortex_a9_p0_default|cortex_a9_p1_default")
30
31 ;; An instruction using the shifter will go down E1.
32@@ -263,3 +264,6 @@ cortex_a9_store3_4, cortex_a9_store1_2,
33 (and (eq_attr "tune" "cortexa9")
34 (eq_attr "type" "fdivd"))
35 "ca9fp_ds1 + ca9_issue_vfp_neon, nothing*24")
36+
37+;; Include Neon pipeline description
38+(include "cortex-a9-neon.md")
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch
new file mode 100644
index 0000000000..cf22aaf16f
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch
@@ -0,0 +1,811 @@
12010-12-13 Tom de Vries <tom@codesourcery.com>
2
3 gcc/
4 * tree-if-switch-conversion.c: New pass.
5 * tree-pass.h (pass_if_to_switch): Declare.
6 * common.opt (ftree-if-to-switch-conversion): New switch.
7 * opts.c (decode_options): Set flag_tree_if_to_switch_conversion at -O2
8 and higher.
9 * passes.c (init_optimization_passes): Use new pass.
10 * params.def (PARAM_IF_TO_SWITCH_THRESHOLD): New param.
11 * doc/invoke.texi (-ftree-if-to-switch-conversion)
12 (if-to-switch-threshold): New item.
13 * doc/invoke.texi (Optimization Options, option -O2): Add
14 -ftree-if-to-switch-conversion.
15 * Makefile.in (OBJS-common): Add tree-if-switch-conversion.o.
16 * Makefile.in (tree-if-switch-conversion.o): New rule.
17
18=== modified file 'gcc/Makefile.in'
19Index: gcc-4_5-branch/gcc/Makefile.in
20===================================================================
21--- gcc-4_5-branch.orig/gcc/Makefile.in
22+++ gcc-4_5-branch/gcc/Makefile.in
23@@ -1354,6 +1354,7 @@ OBJS-common = \
24 tree-profile.o \
25 tree-scalar-evolution.o \
26 tree-sra.o \
27+ tree-if-switch-conversion.o \
28 tree-switch-conversion.o \
29 tree-ssa-address.o \
30 tree-ssa-alias.o \
31@@ -3013,6 +3014,11 @@ tree-sra.o : tree-sra.c $(CONFIG_H) $(SY
32 $(TM_H) $(TREE_H) $(GIMPLE_H) $(CGRAPH_H) $(TREE_FLOW_H) $(IPA_PROP_H) \
33 $(DIAGNOSTIC_H) statistics.h $(TREE_DUMP_H) $(TIMEVAR_H) $(PARAMS_H) \
34 $(TARGET_H) $(FLAGS_H) $(EXPR_H) $(TREE_INLINE_H)
35+tree-if-switch-conversion.o : tree-if-switch-conversion.c $(CONFIG_H) \
36+ $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) \
37+ $(TREE_INLINE_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
38+ $(GIMPLE_H) $(TREE_PASS_H) $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) output.h \
39+ $(GGC_H) $(OBSTACK_H) $(PARAMS_H) $(CPPLIB_H) $(PARAMS_H)
40 tree-switch-conversion.o : tree-switch-conversion.c $(CONFIG_H) $(SYSTEM_H) \
41 $(TREE_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
42 $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(GIMPLE_H) \
43Index: gcc-4_5-branch/gcc/common.opt
44===================================================================
45--- gcc-4_5-branch.orig/gcc/common.opt
46+++ gcc-4_5-branch/gcc/common.opt
47@@ -1285,6 +1285,10 @@ ftree-switch-conversion
48 Common Report Var(flag_tree_switch_conversion) Optimization
49 Perform conversions of switch initializations.
50
51+ftree-if-to-switch-conversion
52+Common Report Var(flag_tree_if_to_switch_conversion) Optimization
53+Perform conversions of chains of ifs into switches.
54+
55 ftree-dce
56 Common Report Var(flag_tree_dce) Optimization
57 Enable SSA dead code elimination optimization on trees
58Index: gcc-4_5-branch/gcc/doc/invoke.texi
59===================================================================
60--- gcc-4_5-branch.orig/gcc/doc/invoke.texi
61+++ gcc-4_5-branch/gcc/doc/invoke.texi
62@@ -382,7 +382,8 @@ Objective-C and Objective-C++ Dialects}.
63 -fstrict-aliasing -fstrict-overflow -fthread-jumps -ftracer @gol
64 -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copy-prop @gol
65 -ftree-copyrename -ftree-dce @gol
66--ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-loop-im @gol
67+-ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre @gol
68+-ftree-if-to-switch-conversion -ftree-loop-im @gol
69 -ftree-phiprop -ftree-loop-distribution @gol
70 -ftree-loop-ivcanon -ftree-loop-linear -ftree-loop-optimize @gol
71 -ftree-parallelize-loops=@var{n} -ftree-pre -ftree-pta -ftree-reassoc @gol
72@@ -5798,6 +5799,7 @@ also turns on the following optimization
73 -fsched-interblock -fsched-spec @gol
74 -fschedule-insns -fschedule-insns2 @gol
75 -fstrict-aliasing -fstrict-overflow @gol
76+-ftree-if-to-switch-conversion @gol
77 -ftree-switch-conversion @gol
78 -ftree-pre @gol
79 -ftree-vrp}
80@@ -6634,6 +6636,10 @@ Perform conversion of simple initializat
81 initializations from a scalar array. This flag is enabled by default
82 at @option{-O2} and higher.
83
84+@item -ftree-if-to-switch-conversion
85+Perform conversion of chains of ifs into switches. This flag is enabled by
86+default at @option{-O2} and higher.
87+
88 @item -ftree-dce
89 @opindex ftree-dce
90 Perform dead code elimination (DCE) on trees. This flag is enabled by
91@@ -8577,6 +8583,12 @@ loop in the loop nest by a given number
92 length can be changed using the @option{loop-block-tile-size}
93 parameter. The default value is 51 iterations.
94
95+@item if-to-switch-threshold
96+If-chain to switch conversion, enabled by
97+@option{-ftree-if-to-switch-conversion} convert chains of ifs of sufficient
98+length into switches. The parameter @option{if-to-switch-threshold} can be
99+used to set the minimal required length. The default value is 3.
100+
101 @end table
102 @end table
103
104Index: gcc-4_5-branch/gcc/opts.c
105===================================================================
106--- gcc-4_5-branch.orig/gcc/opts.c
107+++ gcc-4_5-branch/gcc/opts.c
108@@ -905,6 +905,7 @@ decode_options (unsigned int argc, const
109 flag_tree_builtin_call_dce = opt2;
110 flag_tree_pre = opt2;
111 flag_tree_switch_conversion = opt2;
112+ flag_tree_if_to_switch_conversion = opt2;
113 flag_ipa_cp = opt2;
114 flag_ipa_sra = opt2;
115 flag_ee = opt2;
116Index: gcc-4_5-branch/gcc/params.def
117===================================================================
118--- gcc-4_5-branch.orig/gcc/params.def
119+++ gcc-4_5-branch/gcc/params.def
120@@ -826,6 +826,11 @@ DEFPARAM (PARAM_IPA_SRA_PTR_GROWTH_FACTO
121 "a pointer to an aggregate with",
122 2, 0, 0)
123
124+DEFPARAM (PARAM_IF_TO_SWITCH_THRESHOLD,
125+ "if-to-switch-threshold",
126+ "Threshold for converting an if-chain into a switch",
127+ 3, 0, 0)
128+
129 /*
130 Local variables:
131 mode:c
132Index: gcc-4_5-branch/gcc/passes.c
133===================================================================
134--- gcc-4_5-branch.orig/gcc/passes.c
135+++ gcc-4_5-branch/gcc/passes.c
136@@ -788,6 +788,7 @@ init_optimization_passes (void)
137 NEXT_PASS (pass_cd_dce);
138 NEXT_PASS (pass_early_ipa_sra);
139 NEXT_PASS (pass_tail_recursion);
140+ NEXT_PASS (pass_if_to_switch);
141 NEXT_PASS (pass_convert_switch);
142 NEXT_PASS (pass_cleanup_eh);
143 NEXT_PASS (pass_profile);
144@@ -844,6 +845,7 @@ init_optimization_passes (void)
145 NEXT_PASS (pass_phiprop);
146 NEXT_PASS (pass_fre);
147 NEXT_PASS (pass_copy_prop);
148+ NEXT_PASS (pass_if_to_switch);
149 NEXT_PASS (pass_merge_phi);
150 NEXT_PASS (pass_vrp);
151 NEXT_PASS (pass_dce);
152Index: gcc-4_5-branch/gcc/tree-if-switch-conversion.c
153===================================================================
154--- /dev/null
155+++ gcc-4_5-branch/gcc/tree-if-switch-conversion.c
156@@ -0,0 +1,643 @@
157+/* Convert a chain of ifs into a switch.
158+ Copyright (C) 2010 Free Software Foundation, Inc.
159+ Contributed by Tom de Vries <tom@codesourcery.com>
160+
161+This file is part of GCC.
162+
163+GCC is free software; you can redistribute it and/or modify it
164+under the terms of the GNU General Public License as published by the
165+Free Software Foundation; either version 3, or (at your option) any
166+later version.
167+
168+GCC is distributed in the hope that it will be useful, but WITHOUT
169+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
170+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
171+for more details.
172+
173+You should have received a copy of the GNU General Public License
174+along with GCC; see the file COPYING3. If not, write to the Free
175+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
176+02110-1301, USA. */
177+
178+
179+/* The following pass converts a chain of ifs into a switch.
180+
181+ The if-chain has the following properties:
182+ - all bbs end in a GIMPLE_COND.
183+ - all but the first bb are empty, apart from the GIMPLE_COND.
184+ - the GIMPLE_CONDs compare the same variable against integer constants.
185+ - the true gotos all target the same bb.
186+ - the false gotos target the next in the if-chain.
187+
188+ F.i., consider the following if-chain:
189+ ...
190+ <bb 4>:
191+ ...
192+ if (D.1993_3 == 32)
193+ goto <bb 3>;
194+ else
195+ goto <bb 5>;
196+
197+ <bb 5>:
198+ if (D.1993_3 == 13)
199+ goto <bb 3>;
200+ else
201+ goto <bb 6>;
202+
203+ <bb 6>:
204+ if (D.1993_3 == 10)
205+ goto <bb 3>;
206+ else
207+ goto <bb 7>;
208+
209+ <bb 7>:
210+ if (D.1993_3 == 9)
211+ goto <bb 3>;
212+ else
213+ goto <bb 8>;
214+ ...
215+
216+ The pass will report this if-chain like this:
217+ ...
218+ var: D.1993_3
219+ first: <bb 4>
220+ true: <bb 3>
221+ last: <bb 7>
222+ constants: 9 10 13 32
223+ ...
224+
225+ and then convert the if-chain into a switch:
226+ ...
227+ <bb 4>:
228+ ...
229+ switch (D.1993_3) <default: <L8>,
230+ case 9: <L7>,
231+ case 10: <L7>,
232+ case 13: <L7>,
233+ case 32: <L7>>
234+ ...
235+
236+ The conversion does not happen if the chain is too short. The threshold is
237+ determined by the parameter PARAM_IF_TO_SWITCH_THRESHOLD.
238+
239+ The pass will try to construct a chain for each bb, unless the bb it is
240+ already contained in a chain. This ensures that all chains will be found,
241+ and that no chain will be constructed twice. The pass constructs and
242+ converts the chains one-by-one, rather than first calculating all the chains
243+ and then doing the conversions.
244+
245+ The pass could detect range-checks in analyze_bb as well, and handle them.
246+ Simple ones, like 'c <= 5', and more complex ones, like
247+ '(unsigned char) c + 247 <= 1', which is generated by the C front-end from
248+ code like '(c == 9 || c == 10)' or '(9 <= c && c <= 10)'. */
249+
250+#include "config.h"
251+#include "system.h"
252+#include "coretypes.h"
253+#include "tm.h"
254+
255+#include "params.h"
256+#include "flags.h"
257+#include "tree.h"
258+#include "basic-block.h"
259+#include "tree-flow.h"
260+#include "tree-flow-inline.h"
261+#include "tree-ssa-operands.h"
262+#include "diagnostic.h"
263+#include "tree-pass.h"
264+#include "tree-dump.h"
265+#include "timevar.h"
266+
267+/* Information we've collected about a single bb. */
268+
269+struct ifsc_info
270+{
271+ /* The variable of the bb's ending GIMPLE_COND, NULL_TREE if not present. */
272+ tree var;
273+ /* The cond_code of the bb's ending GIMPLE_COND. */
274+ enum tree_code cond_code;
275+ /* The constant of the bb's ending GIMPLE_COND. */
276+ tree constant;
277+ /* Successor edge of the bb if its GIMPLE_COND is true. */
278+ edge true_edge;
279+ /* Successor edge of the bb if its GIMPLE_COND is false. */
280+ edge false_edge;
281+ /* Set if the bb has valid ifsc_info. */
282+ bool valid;
283+ /* Set if the bb is part of a chain. */
284+ bool chained;
285+};
286+
287+/* Macros to access the fields of struct ifsc_info. */
288+
289+#define BB_IFSC_VAR(bb) (((struct ifsc_info *)bb->aux)->var)
290+#define BB_IFSC_COND_CODE(bb) (((struct ifsc_info *)bb->aux)->cond_code)
291+#define BB_IFSC_CONSTANT(bb) (((struct ifsc_info *)bb->aux)->constant)
292+#define BB_IFSC_TRUE_EDGE(bb) (((struct ifsc_info *)bb->aux)->true_edge)
293+#define BB_IFSC_FALSE_EDGE(bb) (((struct ifsc_info *)bb->aux)->false_edge)
294+#define BB_IFSC_VALID(bb) (((struct ifsc_info *)bb->aux)->valid)
295+#define BB_IFSC_CHAINED(bb) (((struct ifsc_info *)bb->aux)->chained)
296+
297+/* Data-type describing an if-chain. */
298+
299+struct if_chain
300+{
301+ /* First bb in the chain. */
302+ basic_block first;
303+ /* Last bb in the chain. */
304+ basic_block last;
305+ /* Variable that GIMPLE_CONDs of all bbs in chain compare against. */
306+ tree var;
307+ /* bb that all GIMPLE_CONDs jump to if comparison succeeds. */
308+ basic_block true_dest;
309+ /* Constants that GIMPLE_CONDs of all bbs in chain compare var against. */
310+ VEC (tree, heap) *constants;
311+ /* Same as previous, but sorted and with duplicates removed. */
312+ VEC (tree, heap) *unique_constants;
313+};
314+
315+/* Utility macro. */
316+
317+#define SWAP(T, X, Y) do { T tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
318+
319+/* Helper function for sort_constants. */
320+
321+static int
322+compare_constants (const void *p1, const void *p2)
323+{
324+ const_tree const c1 = *(const_tree const*)p1;
325+ const_tree const c2 = *(const_tree const*)p2;
326+
327+ return tree_int_cst_compare (c1, c2);
328+}
329+
330+/* Sort constants in constants and copy to unique_constants, while skipping
331+ duplicates. */
332+
333+static void
334+sort_constants (VEC (tree,heap) *constants, VEC (tree,heap) **unique_constants)
335+{
336+ size_t len = VEC_length (tree, constants);
337+ unsigned int ix;
338+ tree prev = NULL_TREE, constant;
339+
340+ /* Sort constants. */
341+ qsort (VEC_address (tree, constants), len, sizeof (tree),
342+ compare_constants);
343+
344+ /* Copy to unique_constants, while skipping duplicates. */
345+ for (ix = 0; VEC_iterate (tree, constants, ix, constant); ix++)
346+ {
347+ if (prev != NULL_TREE && tree_int_cst_compare (prev, constant) == 0)
348+ continue;
349+ prev = constant;
350+
351+ VEC_safe_push (tree, heap, *unique_constants, constant);
352+ }
353+}
354+
355+/* Get true_edge and false_edge of a bb ending in a conditional jump. */
356+
357+static void
358+get_edges (basic_block bb, edge *true_edge, edge *false_edge)
359+{
360+ edge e0, e1;
361+ int e0_true;
362+ int n = EDGE_COUNT (bb->succs);
363+ gcc_assert (n == 2);
364+
365+ e0 = EDGE_SUCC (bb, 0);
366+ e1 = EDGE_SUCC (bb, 1);
367+
368+ e0_true = e0->flags & EDGE_TRUE_VALUE;
369+
370+ *true_edge = e0_true ? e0 : e1;
371+ *false_edge = e0_true ? e1 : e0;
372+
373+ gcc_assert ((*true_edge)->flags & EDGE_TRUE_VALUE);
374+ gcc_assert ((*false_edge)->flags & EDGE_FALSE_VALUE);
375+
376+ gcc_assert (((*true_edge)->flags & EDGE_FALLTHRU) == 0);
377+ gcc_assert (((*false_edge)->flags & EDGE_FALLTHRU) == 0);
378+}
379+
380+/* Analyze bb and store results in ifsc_info struct. */
381+
382+static void
383+analyze_bb (basic_block bb)
384+{
385+ gimple stmt = last_stmt (bb);
386+ tree lhs, rhs, var, constant;
387+ edge true_edge, false_edge;
388+ enum tree_code cond_code;
389+
390+ /* Don't redo analysis. */
391+ if (BB_IFSC_VALID (bb))
392+ return;
393+ BB_IFSC_VALID (bb) = true;
394+
395+
396+ /* bb needs to end in GIMPLE_COND. */
397+ if (!stmt || gimple_code (stmt) != GIMPLE_COND)
398+ return;
399+
400+ /* bb needs to end in EQ_EXPR or NE_EXPR. */
401+ cond_code = gimple_cond_code (stmt);
402+ if (cond_code != EQ_EXPR && cond_code != NE_EXPR)
403+ return;
404+
405+ lhs = gimple_cond_lhs (stmt);
406+ rhs = gimple_cond_rhs (stmt);
407+
408+ /* GIMPLE_COND needs to compare variable to constant. */
409+ if ((TREE_CONSTANT (lhs) == 0)
410+ == (TREE_CONSTANT (rhs) == 0))
411+ return;
412+
413+ var = TREE_CONSTANT (lhs) ? rhs : lhs;
414+ constant = TREE_CONSTANT (lhs)? lhs : rhs;
415+
416+ /* Switches cannot handle non-integral types. */
417+ if (!INTEGRAL_TYPE_P(TREE_TYPE (var)))
418+ return;
419+
420+ get_edges (bb, &true_edge, &false_edge);
421+
422+ if (cond_code == NE_EXPR)
423+ SWAP (edge, true_edge, false_edge);
424+
425+ /* TODO: loosen this constraint. In principle it's ok if true_edge->dest has
426+ phis, as long as for each phi all the edges coming from the chain have the
427+ same value. */
428+ if (!gimple_seq_empty_p (phi_nodes (true_edge->dest)))
429+ return;
430+
431+ /* Store analysis in ifsc_info struct. */
432+ BB_IFSC_VAR (bb) = var;
433+ BB_IFSC_COND_CODE (bb) = cond_code;
434+ BB_IFSC_CONSTANT (bb) = constant;
435+ BB_IFSC_TRUE_EDGE (bb) = true_edge;
436+ BB_IFSC_FALSE_EDGE (bb) = false_edge;
437+}
438+
439+/* Grow if-chain forward. */
440+
441+static void
442+grow_if_chain_forward (struct if_chain *chain)
443+{
444+ basic_block next_bb;
445+
446+ while (1)
447+ {
448+ next_bb = BB_IFSC_FALSE_EDGE (chain->last)->dest;
449+
450+ /* next_bb is already part of another chain. */
451+ if (BB_IFSC_CHAINED (next_bb))
452+ break;
453+
454+ /* next_bb needs to be dominated by the last bb. */
455+ if (!single_pred_p (next_bb))
456+ break;
457+
458+ analyze_bb (next_bb);
459+
460+ /* Does next_bb fit in chain? */
461+ if (BB_IFSC_VAR (next_bb) != chain->var
462+ || BB_IFSC_TRUE_EDGE (next_bb)->dest != chain->true_dest)
463+ break;
464+
465+ /* We can only add empty bbs at the end of the chain. */
466+ if (first_stmt (next_bb) != last_stmt (next_bb))
467+ break;
468+
469+ /* Add next_bb at end of chain. */
470+ VEC_safe_push (tree, heap, chain->constants, BB_IFSC_CONSTANT (next_bb));
471+ BB_IFSC_CHAINED (next_bb) = true;
472+ chain->last = next_bb;
473+ }
474+}
475+
476+/* Grow if-chain backward. */
477+
478+static void
479+grow_if_chain_backward (struct if_chain *chain)
480+{
481+ basic_block prev_bb;
482+
483+ while (1)
484+ {
485+ /* First bb is not empty, cannot grow backwards. */
486+ if (first_stmt (chain->first) != last_stmt (chain->first))
487+ break;
488+
489+ /* First bb has no single predecessor, cannot grow backwards. */
490+ if (!single_pred_p (chain->first))
491+ break;
492+
493+ prev_bb = single_pred (chain->first);
494+
495+ /* prev_bb is already part of another chain. */
496+ if (BB_IFSC_CHAINED (prev_bb))
497+ break;
498+
499+ analyze_bb (prev_bb);
500+
501+ /* Does prev_bb fit in chain? */
502+ if (BB_IFSC_VAR (prev_bb) != chain->var
503+ || BB_IFSC_TRUE_EDGE (prev_bb)->dest != chain->true_dest)
504+ break;
505+
506+ /* Add prev_bb at beginning of chain. */
507+ VEC_safe_push (tree, heap, chain->constants, BB_IFSC_CONSTANT (prev_bb));
508+ BB_IFSC_CHAINED (prev_bb) = true;
509+ chain->first = prev_bb;
510+ }
511+}
512+
513+/* Grow if-chain containing bb. */
514+
515+static void
516+grow_if_chain (basic_block bb, struct if_chain *chain)
517+{
518+ /* Initialize chain to empty. */
519+ VEC_truncate (tree, chain->constants, 0);
520+ VEC_truncate (tree, chain->unique_constants, 0);
521+
522+ /* bb is already part of another chain. */
523+ if (BB_IFSC_CHAINED (bb))
524+ return;
525+
526+ analyze_bb (bb);
527+
528+ /* bb is not fit to be part of a chain. */
529+ if (BB_IFSC_VAR (bb) == NULL_TREE)
530+ return;
531+
532+ /* Set bb as initial part of the chain. */
533+ VEC_safe_push (tree, heap, chain->constants, BB_IFSC_CONSTANT (bb));
534+ chain->first = chain->last = bb;
535+ chain->var = BB_IFSC_VAR (bb);
536+ chain->true_dest = BB_IFSC_TRUE_EDGE (bb)->dest;
537+
538+ /* bb is part of a chain now. */
539+ BB_IFSC_CHAINED (bb) = true;
540+
541+ /* Grow chain to its maximum size. */
542+ grow_if_chain_forward (chain);
543+ grow_if_chain_backward (chain);
544+
545+ /* Sort constants and skip duplicates. */
546+ sort_constants (chain->constants, &chain->unique_constants);
547+}
548+
549+static void
550+dump_tree_vector (VEC (tree, heap) *vec)
551+{
552+ unsigned int ix;
553+ tree constant;
554+
555+ for (ix = 0; VEC_iterate (tree, vec, ix, constant); ix++)
556+ {
557+ if (ix != 0)
558+ fprintf (dump_file, " ");
559+ print_generic_expr (dump_file, constant, 0);
560+ }
561+ fprintf (dump_file, "\n");
562+}
563+
564+/* Dump if-chain to dump_file. */
565+
566+static void
567+dump_if_chain (struct if_chain *chain)
568+{
569+ if (!dump_file)
570+ return;
571+
572+ fprintf (dump_file, "var: ");
573+ print_generic_expr (dump_file, chain->var, 0);
574+ fprintf (dump_file, "\n");
575+ fprintf (dump_file, "first: <bb %d>\n", chain->first->index);
576+ fprintf (dump_file, "true: <bb %d>\n", chain->true_dest->index);
577+ fprintf (dump_file, "last: <bb %d>\n",chain->last->index);
578+
579+ fprintf (dump_file, "constants: ");
580+ dump_tree_vector (chain->constants);
581+
582+ if (VEC_length (tree, chain->unique_constants)
583+ != VEC_length (tree, chain->constants))
584+ {
585+ fprintf (dump_file, "unique_constants: ");
586+ dump_tree_vector (chain->unique_constants);
587+ }
588+}
589+
590+/* Remove redundant bbs and edges. */
591+
592+static void
593+remove_redundant_bbs_and_edges (struct if_chain *chain, int *false_prob)
594+{
595+ basic_block bb, next;
596+ edge true_edge, false_edge;
597+
598+ for (bb = chain->first;; bb = next)
599+ {
600+ true_edge = BB_IFSC_TRUE_EDGE (bb);
601+ false_edge = BB_IFSC_FALSE_EDGE (bb);
602+
603+ /* Determine next, before we delete false_edge. */
604+ next = false_edge->dest;
605+
606+ /* Accumulate probability. */
607+ *false_prob = (*false_prob * false_edge->probability) / REG_BR_PROB_BASE;
608+
609+ /* Don't remove the new true_edge. */
610+ if (bb != chain->first)
611+ remove_edge (true_edge);
612+
613+ /* Don't remove the new false_edge. */
614+ if (bb != chain->last)
615+ remove_edge (false_edge);
616+
617+ /* Don't remove the first bb. */
618+ if (bb != chain->first)
619+ delete_basic_block (bb);
620+
621+ /* Stop after last. */
622+ if (bb == chain->last)
623+ break;
624+ }
625+}
626+
627+/* Update control flow graph. */
628+
629+static void
630+update_cfg (struct if_chain *chain)
631+{
632+ edge true_edge, false_edge;
633+ int false_prob;
634+ int flags_mask = ~(EDGE_FALLTHRU|EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
635+
636+ /* We keep these 2 edges, and remove the rest. We need this specific
637+ false_edge, because a phi in chain->last->dest might reference (the index
638+ of) this edge. For true_edge, we could pick any of them. */
639+ true_edge = BB_IFSC_TRUE_EDGE (chain->first);
640+ false_edge = BB_IFSC_FALSE_EDGE (chain->last);
641+
642+ /* Update true edge. */
643+ true_edge->flags &= flags_mask;
644+
645+ /* Update false edge. */
646+ redirect_edge_pred (false_edge, chain->first);
647+ false_edge->flags &= flags_mask;
648+
649+ false_prob = REG_BR_PROB_BASE;
650+ remove_redundant_bbs_and_edges (chain, &false_prob);
651+
652+ /* Repair probabilities. */
653+ true_edge->probability = REG_BR_PROB_BASE - false_prob;
654+ false_edge->probability = false_prob;
655+
656+ /* Force recalculation of dominance info. */
657+ free_dominance_info (CDI_DOMINATORS);
658+ free_dominance_info (CDI_POST_DOMINATORS);
659+}
660+
661+/* Create switch statement. Borrows from gimplify_switch_expr. */
662+
663+static void
664+convert_if_chain_to_switch (struct if_chain *chain)
665+{
666+ tree label_decl_true, label_decl_false;
667+ gimple label_true, label_false, gimple_switch;
668+ gimple_stmt_iterator gsi;
669+ tree default_case, other_case, constant;
670+ unsigned int ix;
671+ VEC (tree, heap) *labels;
672+
673+ labels = VEC_alloc (tree, heap, 8);
674+
675+ /* Create and insert true jump label. */
676+ label_decl_true = create_artificial_label (UNKNOWN_LOCATION);
677+ label_true = gimple_build_label (label_decl_true);
678+ gsi = gsi_start_bb (chain->true_dest);
679+ gsi_insert_before (&gsi, label_true, GSI_SAME_STMT);
680+
681+ /* Create and insert false jump label. */
682+ label_decl_false = create_artificial_label (UNKNOWN_LOCATION);
683+ label_false = gimple_build_label (label_decl_false);
684+ gsi = gsi_start_bb (BB_IFSC_FALSE_EDGE (chain->last)->dest);
685+ gsi_insert_before (&gsi, label_false, GSI_SAME_STMT);
686+
687+ /* Create default case label. */
688+ default_case = build3 (CASE_LABEL_EXPR, void_type_node,
689+ NULL_TREE, NULL_TREE,
690+ label_decl_false);
691+
692+ /* Create case labels. */
693+ for (ix = 0; VEC_iterate (tree, chain->unique_constants, ix, constant); ix++)
694+ {
695+ /* TODO: use ranges, as in gimplify_switch_expr. */
696+ other_case = build3 (CASE_LABEL_EXPR, void_type_node,
697+ constant, NULL_TREE,
698+ label_decl_true);
699+ VEC_safe_push (tree, heap, labels, other_case);
700+ }
701+
702+ /* Create and insert switch. */
703+ gimple_switch = gimple_build_switch_vec (chain->var, default_case, labels);
704+ gsi = gsi_for_stmt (last_stmt (chain->first));
705+ gsi_insert_before (&gsi, gimple_switch, GSI_SAME_STMT);
706+
707+ /* Remove now obsolete if. */
708+ gsi_remove (&gsi, true);
709+
710+ VEC_free (tree, heap, labels);
711+}
712+
713+/* Allocation and initialization. */
714+
715+static void
716+init_pass (struct if_chain *chain)
717+{
718+ alloc_aux_for_blocks (sizeof (struct ifsc_info));
719+
720+ chain->constants = VEC_alloc (tree, heap, 8);
721+ chain->unique_constants = VEC_alloc (tree, heap, 8);
722+}
723+
724+/* Deallocation. */
725+
726+static void
727+finish_pass (struct if_chain *chain)
728+{
729+ free_aux_for_blocks ();
730+
731+ VEC_free (tree, heap, chain->constants);
732+ VEC_free (tree, heap, chain->unique_constants);
733+}
734+
735+/* Find if-chains and convert them to switches. */
736+
737+static unsigned int
738+do_if_to_switch (void)
739+{
740+ basic_block bb;
741+ struct if_chain chain;
742+ unsigned int convert_threshold = PARAM_VALUE (PARAM_IF_TO_SWITCH_THRESHOLD);
743+
744+ init_pass (&chain);
745+
746+ for (bb = cfun->cfg->x_entry_block_ptr->next_bb;
747+ bb != cfun->cfg->x_exit_block_ptr;)
748+ {
749+ grow_if_chain (bb, &chain);
750+
751+ do
752+ bb = bb->next_bb;
753+ while (BB_IFSC_CHAINED (bb));
754+
755+ /* Determine if the chain is long enough. */
756+ if (VEC_length (tree, chain.unique_constants) < convert_threshold)
757+ continue;
758+
759+ dump_if_chain (&chain);
760+
761+ convert_if_chain_to_switch (&chain);
762+
763+ update_cfg (&chain);
764+ }
765+
766+ finish_pass (&chain);
767+
768+ return 0;
769+}
770+
771+/* The pass gate. */
772+
773+static bool
774+if_to_switch_gate (void)
775+{
776+ return flag_tree_if_to_switch_conversion;
777+}
778+
779+/* The pass definition. */
780+
781+struct gimple_opt_pass pass_if_to_switch =
782+{
783+ {
784+ GIMPLE_PASS,
785+ "iftoswitch", /* name */
786+ if_to_switch_gate, /* gate */
787+ do_if_to_switch, /* execute */
788+ NULL, /* sub */
789+ NULL, /* next */
790+ 0, /* static_pass_number */
791+ TV_TREE_SWITCH_CONVERSION, /* tv_id */
792+ PROP_cfg | PROP_ssa, /* properties_required */
793+ 0, /* properties_provided */
794+ 0, /* properties_destroyed */
795+ 0, /* todo_flags_start */
796+ TODO_update_ssa | TODO_dump_func
797+ | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */
798+ }
799+};
800Index: gcc-4_5-branch/gcc/tree-pass.h
801===================================================================
802--- gcc-4_5-branch.orig/gcc/tree-pass.h
803+++ gcc-4_5-branch/gcc/tree-pass.h
804@@ -560,6 +560,7 @@ extern struct gimple_opt_pass pass_inlin
805 extern struct gimple_opt_pass pass_all_early_optimizations;
806 extern struct gimple_opt_pass pass_update_address_taken;
807 extern struct gimple_opt_pass pass_convert_switch;
808+extern struct gimple_opt_pass pass_if_to_switch;
809
810 /* The root of the compilation pass tree, once constructed. */
811 extern struct opt_pass *all_passes, *all_small_ipa_passes, *all_lowering_passes,
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch
new file mode 100644
index 0000000000..3ac7f7f6fd
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99473.patch
@@ -0,0 +1,409 @@
12010-02-04 Tom de Vries <tom@codesourcery.com>
2
3 gcc/
4 stmt.c (set_jump_prob): Fix assert condition.
5
62010-01-27 Tom de Vries <tom@codesourcery.com>
7
8 gcc/
9 stmt.c (rtx_seq_cost): Use insn_rtx_cost instead of rtx_cost.
10
112010-01-26 Tom de Vries <tom@codesourcery.com>
12
13 gcc/
14 * stmt.c (struct case_bit_test): Add rev_hi and rev_lo field.
15 * stmt.c (emit_case_bit_test_jump): New function.
16 * stmt.c (rtx_seq_cost): New function.
17 * stmt.c (choose_case_bit_test_expand_method): New function.
18 * stmt.c (set_bit): New function.
19 * stmt.c (emit_case_bit_test): Adjust comment.
20 * stmt.c (emit_case_bit_test): Set and update rev_hi and rev_lo fields.
21 * stmt.c (emit_case_bit_test): Use set_bit.
22 * stmt.c (emit_case_bit_test): Use choose_case_bit_test_expand_method.
23 * stmt.c (emit_case_bit_test): Use emit_case_bit_test_jump.
24 * testsuite/gcc.dg/switch-bittest.c: New test.
25
262010-01-25 Tom de Vries <tom@codesourcery.com>
27
28 gcc/
29 * stmt.c (emit_case_bit_tests): Change prototype.
30 * stmt.c (struct case_bit_test): Add prob field.
31 * stmt.c (get_label_prob): New function.
32 * stmt.c (set_jump_prob): New function.
33 * stmt.c (emit_case_bit_tests): Use get_label_prob.
34 * stmt.c (emit_case_bit_tests): Set prob field.
35 * stmt.c (emit_case_bit_tests): Use set_jump_prob.
36 * stmt.c (expand_case): Add new args to emit_case_bit_tests invocation.
37 * testsuite/gcc.dg/switch-prob.c: Add test.
38
39=== modified file 'gcc/stmt.c'
40Index: gcc-4_5-branch/gcc/stmt.c
41===================================================================
42--- gcc-4_5-branch.orig/gcc/stmt.c
43+++ gcc-4_5-branch/gcc/stmt.c
44@@ -117,7 +117,8 @@ static void expand_value_return (rtx);
45 static int estimate_case_costs (case_node_ptr);
46 static bool lshift_cheap_p (void);
47 static int case_bit_test_cmp (const void *, const void *);
48-static void emit_case_bit_tests (tree, tree, tree, tree, case_node_ptr, rtx);
49+static void emit_case_bit_tests (tree, tree, tree, tree, case_node_ptr, tree,
50+ rtx, basic_block);
51 static void balance_case_nodes (case_node_ptr *, case_node_ptr);
52 static int node_has_low_bound (case_node_ptr, tree);
53 static int node_has_high_bound (case_node_ptr, tree);
54@@ -2107,8 +2108,11 @@ struct case_bit_test
55 {
56 HOST_WIDE_INT hi;
57 HOST_WIDE_INT lo;
58+ HOST_WIDE_INT rev_hi;
59+ HOST_WIDE_INT rev_lo;
60 rtx label;
61 int bits;
62+ int prob;
63 };
64
65 /* Determine whether "1 << x" is relatively cheap in word_mode. */
66@@ -2148,10 +2152,193 @@ case_bit_test_cmp (const void *p1, const
67 return CODE_LABEL_NUMBER (d2->label) - CODE_LABEL_NUMBER (d1->label);
68 }
69
70+/* Emit a bit test and a conditional jump. */
71+
72+static void
73+emit_case_bit_test_jump (unsigned int count, rtx index, rtx label,
74+ unsigned int method, HOST_WIDE_INT hi,
75+ HOST_WIDE_INT lo, HOST_WIDE_INT rev_hi,
76+ HOST_WIDE_INT rev_lo)
77+{
78+ rtx expr;
79+
80+ if (method == 1)
81+ {
82+ /* (1 << index). */
83+ if (count == 0)
84+ index = expand_binop (word_mode, ashl_optab, const1_rtx,
85+ index, NULL_RTX, 1, OPTAB_WIDEN);
86+ /* CST. */
87+ expr = immed_double_const (lo, hi, word_mode);
88+ /* ((1 << index) & CST). */
89+ expr = expand_binop (word_mode, and_optab, index, expr,
90+ NULL_RTX, 1, OPTAB_WIDEN);
91+ /* if (((1 << index) & CST)). */
92+ emit_cmp_and_jump_insns (expr, const0_rtx, NE, NULL_RTX,
93+ word_mode, 1, label);
94+ }
95+ else if (method == 2)
96+ {
97+ /* (bit_reverse (CST)) */
98+ expr = immed_double_const (rev_lo, rev_hi, word_mode);
99+ /* ((bit_reverse (CST)) << index) */
100+ expr = expand_binop (word_mode, ashl_optab, expr,
101+ index, NULL_RTX, 1, OPTAB_WIDEN);
102+ /* if (((bit_reverse (CST)) << index) < 0). */
103+ emit_cmp_and_jump_insns (expr, const0_rtx, LT, NULL_RTX,
104+ word_mode, 0, label);
105+ }
106+ else
107+ gcc_unreachable ();
108+}
109+
110+/* Return the cost of rtx sequence SEQ. The sequence is supposed to contain one
111+ jump, which has no effect in the cost. */
112+
113+static unsigned int
114+rtx_seq_cost (rtx seq)
115+{
116+ rtx one;
117+ unsigned int nr_branches = 0;
118+ unsigned int sum = 0, cost;
119+
120+ for (one = seq; one != NULL_RTX; one = NEXT_INSN (one))
121+ if (JUMP_P (one))
122+ nr_branches++;
123+ else
124+ {
125+ cost = insn_rtx_cost (PATTERN (one), optimize_insn_for_speed_p ());
126+ if (dump_file)
127+ {
128+ print_rtl_single (dump_file, one);
129+ fprintf (dump_file, "cost: %u\n", cost);
130+ }
131+ sum += cost;
132+ }
133+
134+ gcc_assert (nr_branches == 1);
135+
136+ if (dump_file)
137+ fprintf (dump_file, "total cost: %u\n", sum);
138+ return sum;
139+}
140+
141+/* Generate the rtx sequences for 2 bit test expansion methods, measure the cost
142+ and choose the cheapest. */
143+
144+static unsigned int
145+choose_case_bit_test_expand_method (rtx label)
146+{
147+ rtx seq, index;
148+ unsigned int cost[2];
149+ static bool method_known = false;
150+ static unsigned int method;
151+
152+ /* If already known, return the method. */
153+ if (method_known)
154+ return method;
155+
156+ index = gen_rtx_REG (word_mode, 10000);
157+
158+ for (method = 1; method <= 2; ++method)
159+ {
160+ start_sequence ();
161+ emit_case_bit_test_jump (0, index, label, method, 0, 0x0f0f0f0f, 0,
162+ 0x0f0f0f0f);
163+ seq = get_insns ();
164+ end_sequence ();
165+ cost[method - 1] = rtx_seq_cost (seq);
166+ }
167+
168+ /* Determine method based on heuristic. */
169+ method = ((cost[1] < cost[0]) ? 1 : 0) + 1;
170+
171+ /* Save and return method. */
172+ method_known = true;
173+ return method;
174+}
175+
176+/* Get the edge probability of the edge from SRC to LABEL_DECL. */
177+
178+static int
179+get_label_prob (basic_block src, tree label_decl)
180+{
181+ basic_block dest;
182+ int prob = 0, nr_prob = 0;
183+ unsigned int i;
184+ edge e;
185+
186+ if (label_decl == NULL_TREE)
187+ return 0;
188+
189+ dest = VEC_index (basic_block, label_to_block_map,
190+ LABEL_DECL_UID (label_decl));
191+
192+ for (i = 0; i < EDGE_COUNT (src->succs); ++i)
193+ {
194+ e = EDGE_SUCC (src, i);
195+
196+ if (e->dest != dest)
197+ continue;
198+
199+ prob += e->probability;
200+ nr_prob++;
201+ }
202+
203+ gcc_assert (nr_prob == 1);
204+
205+ return prob;
206+}
207+
208+/* Add probability note with scaled PROB to JUMP and update INV_SCALE. This
209+ function is intended to be used with a series of conditional jumps to L[i]
210+ where the probabilities p[i] to get to L[i] are known, and the jump
211+ probabilities j[i] need to be computed.
212+
213+ The algorithm to calculate the probabilities is
214+
215+ scale = REG_BR_PROB_BASE;
216+ for (i = 0; i < n; ++i)
217+ {
218+ j[i] = p[i] * scale / REG_BR_PROB_BASE;
219+ f[i] = REG_BR_PROB_BASE - j[i];
220+ scale = scale / (f[i] / REG_BR_PROB_BASE);
221+ }
222+
223+ The implementation uses inv_scale (REG_BR_PROB_BASE / scale) instead of
224+ scale, because scale tends to grow bigger than REG_BR_PROB_BASE. */
225+
226+static void
227+set_jump_prob (rtx jump, int prob, int *inv_scale)
228+{
229+ /* j[i] = p[i] * scale / REG_BR_PROB_BASE. */
230+ int jump_prob = prob * REG_BR_PROB_BASE / *inv_scale;
231+ /* f[i] = REG_BR_PROB_BASE - j[i]. */
232+ int fallthrough_prob = REG_BR_PROB_BASE - jump_prob;
233+
234+ gcc_assert (jump_prob <= REG_BR_PROB_BASE);
235+ add_reg_note (jump, REG_BR_PROB, GEN_INT (jump_prob));
236+
237+ /* scale = scale / (f[i] / REG_BR_PROB_BASE). */
238+ *inv_scale = *inv_scale * fallthrough_prob / REG_BR_PROB_BASE;
239+}
240+
241+/* Set bit in hwi hi/lo pair. */
242+
243+static void
244+set_bit (HOST_WIDE_INT *hi, HOST_WIDE_INT *lo, unsigned int j)
245+{
246+ if (j >= HOST_BITS_PER_WIDE_INT)
247+ *hi |= (HOST_WIDE_INT) 1 << (j - HOST_BITS_PER_INT);
248+ else
249+ *lo |= (HOST_WIDE_INT) 1 << j;
250+}
251+
252 /* Expand a switch statement by a short sequence of bit-wise
253 comparisons. "switch(x)" is effectively converted into
254- "if ((1 << (x-MINVAL)) & CST)" where CST and MINVAL are
255- integer constants.
256+ "if ((1 << (x-MINVAL)) & CST)" or
257+ "if (((bit_reverse (CST)) << (x-MINVAL)) < 0)", where CST
258+ and MINVAL are integer constants.
259
260 INDEX_EXPR is the value being switched on, which is of
261 type INDEX_TYPE. MINVAL is the lowest case value of in
262@@ -2165,14 +2352,17 @@ case_bit_test_cmp (const void *p1, const
263
264 static void
265 emit_case_bit_tests (tree index_type, tree index_expr, tree minval,
266- tree range, case_node_ptr nodes, rtx default_label)
267+ tree range, case_node_ptr nodes, tree default_label_decl,
268+ rtx default_label, basic_block bb)
269 {
270 struct case_bit_test test[MAX_CASE_BIT_TESTS];
271 enum machine_mode mode;
272 rtx expr, index, label;
273 unsigned int i,j,lo,hi;
274 struct case_node *n;
275- unsigned int count;
276+ unsigned int count, method;
277+ int inv_scale = REG_BR_PROB_BASE;
278+ int default_prob = get_label_prob (bb, default_label_decl);
279
280 count = 0;
281 for (n = nodes; n; n = n->right)
282@@ -2187,8 +2377,11 @@ emit_case_bit_tests (tree index_type, tr
283 gcc_assert (count < MAX_CASE_BIT_TESTS);
284 test[i].hi = 0;
285 test[i].lo = 0;
286+ test[i].rev_hi = 0;
287+ test[i].rev_lo = 0;
288 test[i].label = label;
289 test[i].bits = 1;
290+ test[i].prob = get_label_prob (bb, n->code_label);
291 count++;
292 }
293 else
294@@ -2199,10 +2392,11 @@ emit_case_bit_tests (tree index_type, tr
295 hi = tree_low_cst (fold_build2 (MINUS_EXPR, index_type,
296 n->high, minval), 1);
297 for (j = lo; j <= hi; j++)
298- if (j >= HOST_BITS_PER_WIDE_INT)
299- test[i].hi |= (HOST_WIDE_INT) 1 << (j - HOST_BITS_PER_INT);
300- else
301- test[i].lo |= (HOST_WIDE_INT) 1 << j;
302+ {
303+ set_bit (&test[i].hi, &test[i].lo, j);
304+ set_bit (&test[i].rev_hi, &test[i].rev_lo,
305+ GET_MODE_BITSIZE (word_mode) - j - 1);
306+ }
307 }
308
309 qsort (test, count, sizeof(*test), case_bit_test_cmp);
310@@ -2216,20 +2410,20 @@ emit_case_bit_tests (tree index_type, tr
311 mode = TYPE_MODE (index_type);
312 expr = expand_normal (range);
313 if (default_label)
314- emit_cmp_and_jump_insns (index, expr, GTU, NULL_RTX, mode, 1,
315- default_label);
316+ {
317+ emit_cmp_and_jump_insns (index, expr, GTU, NULL_RTX, mode, 1,
318+ default_label);
319+ set_jump_prob (get_last_insn (), default_prob / 2, &inv_scale);
320+ }
321
322 index = convert_to_mode (word_mode, index, 0);
323- index = expand_binop (word_mode, ashl_optab, const1_rtx,
324- index, NULL_RTX, 1, OPTAB_WIDEN);
325
326+ method = choose_case_bit_test_expand_method (test[0].label);
327 for (i = 0; i < count; i++)
328 {
329- expr = immed_double_const (test[i].lo, test[i].hi, word_mode);
330- expr = expand_binop (word_mode, and_optab, index, expr,
331- NULL_RTX, 1, OPTAB_WIDEN);
332- emit_cmp_and_jump_insns (expr, const0_rtx, NE, NULL_RTX,
333- word_mode, 1, test[i].label);
334+ emit_case_bit_test_jump (i, index, test[i].label, method, test[i].hi,
335+ test[i].lo, test[i].rev_hi, test[i].rev_lo);
336+ set_jump_prob (get_last_insn (), test[i].prob, &inv_scale);
337 }
338
339 if (default_label)
340@@ -2400,7 +2594,8 @@ expand_case (gimple stmt)
341 range = maxval;
342 }
343 emit_case_bit_tests (index_type, index_expr, minval, range,
344- case_list, default_label);
345+ case_list, default_label_decl, default_label,
346+ gimple_bb (stmt));
347 }
348
349 /* If range of values is much bigger than number of values,
350Index: gcc-4_5-branch/gcc/testsuite/gcc.dg/switch-bittest.c
351===================================================================
352--- /dev/null
353+++ gcc-4_5-branch/gcc/testsuite/gcc.dg/switch-bittest.c
354@@ -0,0 +1,25 @@
355+/* { dg-do compile } */
356+/* { dg-options "-O2 -fdump-rtl-expand" } */
357+
358+const char *
359+f (const char *p)
360+{
361+ while (1)
362+ {
363+ switch (*p)
364+ {
365+ case 9:
366+ case 10:
367+ case 13:
368+ case 32:
369+ break;
370+ default:
371+ return p;
372+ }
373+ }
374+}
375+
376+/* { dg-final { scan-rtl-dump-times "jump_insn" 4 "expand" { target mips*-*-* } } } */
377+/* { dg-final { scan-rtl-dump-times "REG_BR_PROB" 2 "expand" { target mips*-*-* } } } */
378+/* { dg-final { scan-rtl-dump-times "lt " 1 "expand" { target mips*-*-* } } } */
379+/* { dg-final { cleanup-rtl-dump "expand" } } */
380Index: gcc-4_5-branch/gcc/testsuite/gcc.dg/switch-prob.c
381===================================================================
382--- /dev/null
383+++ gcc-4_5-branch/gcc/testsuite/gcc.dg/switch-prob.c
384@@ -0,0 +1,25 @@
385+/* { dg-do compile } */
386+/* { dg-options "-O2 -fdump-rtl-expand" } */
387+
388+const char *
389+f (const char *p)
390+{
391+ while (1)
392+ {
393+ switch (*p)
394+ {
395+ case 9:
396+ case 10:
397+ case 13:
398+ case 32:
399+ break;
400+ default:
401+ return p;
402+ }
403+ }
404+}
405+
406+/* { dg-final { scan-rtl-dump-times "jump_insn" 4 "expand" { target mips*-*-* } } } */
407+/* { dg-final { scan-rtl-dump-times "REG_BR_PROB" 2 "expand" { target mips*-*-* } } } */
408+/* { dg-final { scan-rtl-dump-times "heuristics" 0 "expand" { target mips*-*-* } } } */
409+/* { dg-final { cleanup-rtl-dump "expand" } } */
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch
new file mode 100644
index 0000000000..9b0fb0b488
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99474.patch
@@ -0,0 +1,3346 @@
12011-01-14 Bernd Schmidt <bernds@codesourcery.com>
2
3 gcc/
4 * function.c (thread_prologue_and_epilogue_insns): Avoid uninitialized
5 variable.
6
72011-01-12 Bernd Schmidt <bernds@codesourcery.com>
8
9 gcc/
10 * config/s390/s390.c (s390_emit_epilogue): Don't use gen_rtx_RETURN.
11 * config/rx/rx.c (gen_rx_rtsd_vector): Likewise.
12 * config/m68hc11/m68hc11.md (return): Likewise.
13 * config/cris/cris.c (cris_expand_return): Likewise.
14 * config/m68k/m68k.c (m68k_expand_epilogue): Likewise.
15 * config/picochip/picochip.c (picochip_expand_epilogue): Likewise.
16 * config/h8300/h8300.c (h8300_push_pop, h8300_expand_epilogue):
17 Likewise.
18 * config/v850/v850.c (expand_epilogue): Likewise.
19 * config/bfin/bfin.c (bfin_expand_call): Likewise.
20
212011-01-04 Catherine Moore <clm@codesourcery.com>
22
23 gcc/
24 * config/rs6000/rs6000.c (rs6000_make_savres_rtx): Change
25 gen_rtx_RETURN to ret_rtx.
26 (rs6000_emit_epilogue): Likewise.
27 (rs6000_output_mi_thunk): Likewise.
28
292011-01-03 Bernd Schmidt <bernds@codesourcery.com>
30
31 gcc/
32 * doc/tm.texi (RETURN_ADDR_REGNUM): Document.
33 * doc/md.texi (simple_return): Document pattern.
34 (return): Add a sentence to clarify.
35 * doc/rtl.texi (simple_return): Document.
36 * doc/invoke.texi (Optimize Options): Document -fshrink-wrap.
37 * common.opt (fshrink-wrap): New.
38 * opts.c (decode_options): Set it for -O2 and above.
39 * gengenrtl.c (special_rtx): PC, CC0, RETURN and SIMPLE_RETURN
40 are special.
41 * rtl.h (ANY_RETURN_P): New macro.
42 (global_rtl_index): Add GR_RETURN and GR_SIMPLE_RETURN.
43 (ret_rtx, simple_return_rtx): New macros.
44 * genemit.c (gen_exp): RETURN and SIMPLE_RETURN have unique rtxs.
45 (gen_expand, gen_split): Use ANY_RETURN_P.
46 * rtl.c (copy_rtx): RETURN and SIMPLE_RETURN are shared.
47 * emit-rtl.c (verify_rtx_sharing): Likewise.
48 (skip_consecutive_labels): Return the argument if it is a return rtx.
49 (classify_insn): Handle both kinds of return.
50 (init_emit_regs): Create global rtl for ret_rtx and simple_return_rtx.
51 * df-scan.c (df_uses_record): Handle SIMPLE_RETURN.
52 * rtl.def (SIMPLE_RETURN): New.
53 * rtlanal.c (tablejump_p): Check JUMP_LABEL for returns.
54 * final.c (final_scan_insn): Recognize both kinds of return.
55 * reorg.c (function_return_label, function_simple_return_label): New
56 static variables.
57 (end_of_function_label): Remove.
58 (simplejump_or_return_p): New static function.
59 (find_end_label): Add a new arg, KIND. All callers changed.
60 Depending on KIND, look for a label suitable for return or
61 simple_return.
62 (make_return_insns): Make corresponding changes.
63 (get_jump_flags): Check JUMP_LABELs for returns.
64 (follow_jumps): Likewise.
65 (get_branch_condition): Check target for return patterns rather
66 than NULL.
67 (own_thread_p): Likewise for thread.
68 (steal_delay_list_from_target): Check JUMP_LABELs for returns.
69 Use simplejump_or_return_p.
70 (fill_simple_delay_slots): Likewise.
71 (optimize_skip): Likewise.
72 (fill_slots_from_thread): Likewise.
73 (relax_delay_slots): Likewise.
74 (dbr_schedule): Adjust handling of end_of_function_label for the
75 two new variables.
76 * ifcvt.c (find_if_case_1): Take care when redirecting jumps to the
77 exit block.
78 (dead_or_predicable): Change NEW_DEST arg to DEST_EDGE. All callers
79 changed. Ensure that the right label is passed to redirect_jump.
80 * jump.c (condjump_p, condjump_in_parallel_p, any_condjump_p,
81 returnjump_p): Handle SIMPLE_RETURNs.
82 (delete_related_insns): Check JUMP_LABEL for returns.
83 (redirect_target): New static function.
84 (redirect_exp_1): Use it. Handle any kind of return rtx as a label
85 rather than interpreting NULL as a return.
86 (redirect_jump_1): Assert that nlabel is not NULL.
87 (redirect_jump): Likewise.
88 (redirect_jump_2): Handle any kind of return rtx as a label rather
89 than interpreting NULL as a return.
90 * dwarf2out.c (compute_barrier_args_size_1): Check JUMP_LABEL for
91 returns.
92 * function.c (emit_return_into_block): Remove useless declaration.
93 (record_hard_reg_sets, frame_required_for_rtx, gen_return_pattern,
94 requires_stack_frame_p): New static functions.
95 (emit_return_into_block): New arg SIMPLE_P. All callers changed.
96 Generate either kind of return pattern and update the JUMP_LABEL.
97 (thread_prologue_and_epilogue_insns): Implement a form of
98 shrink-wrapping. Ensure JUMP_LABELs for return insns are set.
99 * print-rtl.c (print_rtx): Handle returns in JUMP_LABELs.
100 * cfglayout.c (fixup_reorder_chain): Ensure JUMP_LABELs for returns
101 remain correct.
102 * resource.c (find_dead_or_set_registers): Check JUMP_LABELs for
103 returns.
104 (mark_target_live_regs): Don't pass a return rtx to next_active_insn.
105 * basic-block.h (force_nonfallthru_and_redirect): Declare.
106 * sched-vis.c (print_pattern): Add case for SIMPLE_RETURN.
107 * cfgrtl.c (force_nonfallthru_and_redirect): No longer static. New arg
108 JUMP_LABEL. All callers changed. Use the label when generating
109 return insns.
110
111 * config/i386/i386.md (returns, return_str, return_cond): New
112 code_iterator and corresponding code_attrs.
113 (<return_str>return): Renamed from return and adapted.
114 (<return_str>return_internal): Likewise for return_internal.
115 (<return_str>return_internal_long): Likewise for return_internal_long.
116 (<return_str>return_pop_internal): Likewise for return_pop_internal.
117 (<return_str>return_indirect_internal): Likewise for
118 return_indirect_internal.
119 * config/i386/i386.c (ix86_expand_epilogue): Expand a simple_return as
120 the last insn.
121 (ix86_pad_returns): Handle both kinds of return rtx.
122 * config/arm/arm.c (use_simple_return_p): new function.
123 (is_jump_table): Handle returns in JUMP_LABELs.
124 (output_return_instruction): New arg SIMPLE. All callers changed.
125 Use it to determine which kind of return to generate.
126 (arm_final_prescan_insn): Handle both kinds of return.
127 * config/arm/arm.md (returns, return_str, return_simple_p,
128 return_cond): New code_iterator and corresponding code_attrs.
129 (<return_str>return): Renamed from return and adapted.
130 (arm_<return_str>return): Renamed from arm_return and adapted.
131 (cond_<return_str>return): Renamed from cond_return and adapted.
132 (cond_<return_str>return_inverted): Renamed from cond_return_inverted
133 and adapted.
134 (epilogue): Use ret_rtx instead of gen_rtx_RETURN.
135 * config/arm/thumb2.md (thumb2_<return_str>return): Renamed from
136 thumb2_return and adapted.
137 * config/arm/arm.h (RETURN_ADDR_REGNUM): Define.
138 * config/arm/arm-protos.h (use_simple_return_p): Declare.
139 (output_return_instruction): Adjust declaration.
140 * config/mips/mips.c (mips_expand_epilogue): Generate a simple_return
141 as final insn.
142 * config/mips/mips.md (simple_return): New expander.
143 (*simple_return, simple_return_internal): New patterns.
144 * config/sh/sh.c (barrier_align): Handle return in a JUMP_LABEL.
145 (split_branches): Don't pass a null label to redirect_jump.
146
147 From mainline:
148 * vec.h (FOR_EACH_VEC_ELT, FOR_EACH_VEC_ELT_REVERSE): New macros.
149 * haifa-sched.c (find_fallthru_edge_from): Rename from
150 find_fallthru_edge. All callers changed.
151 * sched-int.h (find_fallthru_edge_from): Rename declaration as well.
152 * basic-block.h (find_fallthru_edge): New inline function.
153
154=== modified file 'gcc/basic-block.h'
155Index: gcc-4_5-branch/gcc/basic-block.h
156===================================================================
157--- gcc-4_5-branch.orig/gcc/basic-block.h
158+++ gcc-4_5-branch/gcc/basic-block.h
159@@ -884,6 +884,7 @@ extern void flow_edge_list_print (const
160
161 /* In cfgrtl.c */
162 extern basic_block force_nonfallthru (edge);
163+extern basic_block force_nonfallthru_and_redirect (edge, basic_block, rtx);
164 extern rtx block_label (basic_block);
165 extern bool purge_all_dead_edges (void);
166 extern bool purge_dead_edges (basic_block);
167@@ -1004,6 +1005,20 @@ bb_has_abnormal_pred (basic_block bb)
168 return false;
169 }
170
171+/* Return the fallthru edge in EDGES if it exists, NULL otherwise. */
172+static inline edge
173+find_fallthru_edge (VEC(edge,gc) *edges)
174+{
175+ edge e;
176+ edge_iterator ei;
177+
178+ FOR_EACH_EDGE (e, ei, edges)
179+ if (e->flags & EDGE_FALLTHRU)
180+ break;
181+
182+ return e;
183+}
184+
185 /* In cfgloopmanip.c. */
186 extern edge mfb_kj_edge;
187 extern bool mfb_keep_just (edge);
188Index: gcc-4_5-branch/gcc/cfganal.c
189===================================================================
190--- gcc-4_5-branch.orig/gcc/cfganal.c
191+++ gcc-4_5-branch/gcc/cfganal.c
192@@ -271,6 +271,37 @@ set_edge_can_fallthru_flag (void)
193 EDGE_SUCC (bb, 0)->flags |= EDGE_CAN_FALLTHRU;
194 EDGE_SUCC (bb, 1)->flags |= EDGE_CAN_FALLTHRU;
195 }
196+ /* dwarf2out expects that a NOTE_INSN_EPILOGUE_BEGIN is always paired
197+ with a return or a sibcall. Ensure that this remains the case if
198+ they are in different basic blocks. */
199+ FOR_EACH_BB (bb)
200+ {
201+ edge e;
202+ edge_iterator ei;
203+ rtx insn, end;
204+
205+ end = BB_END (bb);
206+ FOR_BB_INSNS (bb, insn)
207+ if (GET_CODE (insn) == NOTE
208+ && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG
209+ && !(CALL_P (end) && SIBLING_CALL_P (end))
210+ && !returnjump_p (end))
211+ {
212+ basic_block other_bb = NULL;
213+ FOR_EACH_EDGE (e, ei, bb->succs)
214+ {
215+ if (e->flags & EDGE_FALLTHRU)
216+ other_bb = e->dest;
217+ else
218+ e->flags &= ~EDGE_CAN_FALLTHRU;
219+ }
220+ FOR_EACH_EDGE (e, ei, other_bb->preds)
221+ {
222+ if (!(e->flags & EDGE_FALLTHRU))
223+ e->flags &= ~EDGE_CAN_FALLTHRU;
224+ }
225+ }
226+ }
227 }
228
229 /* Find unreachable blocks. An unreachable block will have 0 in
230Index: gcc-4_5-branch/gcc/cfglayout.c
231===================================================================
232--- gcc-4_5-branch.orig/gcc/cfglayout.c
233+++ gcc-4_5-branch/gcc/cfglayout.c
234@@ -766,6 +766,7 @@ fixup_reorder_chain (void)
235 {
236 edge e_fall, e_taken, e;
237 rtx bb_end_insn;
238+ rtx ret_label = NULL_RTX;
239 basic_block nb;
240 edge_iterator ei;
241
242@@ -785,6 +786,7 @@ fixup_reorder_chain (void)
243 bb_end_insn = BB_END (bb);
244 if (JUMP_P (bb_end_insn))
245 {
246+ ret_label = JUMP_LABEL (bb_end_insn);
247 if (any_condjump_p (bb_end_insn))
248 {
249 /* This might happen if the conditional jump has side
250@@ -899,7 +901,7 @@ fixup_reorder_chain (void)
251 }
252
253 /* We got here if we need to add a new jump insn. */
254- nb = force_nonfallthru (e_fall);
255+ nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
256 if (nb)
257 {
258 nb->il.rtl->visited = 1;
259@@ -1118,24 +1120,30 @@ extern bool cfg_layout_can_duplicate_bb_
260 bool
261 cfg_layout_can_duplicate_bb_p (const_basic_block bb)
262 {
263+ rtx insn;
264+
265 /* Do not attempt to duplicate tablejumps, as we need to unshare
266 the dispatch table. This is difficult to do, as the instructions
267 computing jump destination may be hoisted outside the basic block. */
268 if (tablejump_p (BB_END (bb), NULL, NULL))
269 return false;
270
271- /* Do not duplicate blocks containing insns that can't be copied. */
272- if (targetm.cannot_copy_insn_p)
273+ insn = BB_HEAD (bb);
274+ while (1)
275 {
276- rtx insn = BB_HEAD (bb);
277- while (1)
278- {
279- if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
280- return false;
281- if (insn == BB_END (bb))
282- break;
283- insn = NEXT_INSN (insn);
284- }
285+ /* Do not duplicate blocks containing insns that can't be copied. */
286+ if (INSN_P (insn) && targetm.cannot_copy_insn_p
287+ && targetm.cannot_copy_insn_p (insn))
288+ return false;
289+ /* dwarf2out expects that these notes are always paired with a
290+ returnjump or sibling call. */
291+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG
292+ && !returnjump_p (BB_END (bb))
293+ && (!CALL_P (BB_END (bb)) || !SIBLING_CALL_P (BB_END (bb))))
294+ return false;
295+ if (insn == BB_END (bb))
296+ break;
297+ insn = NEXT_INSN (insn);
298 }
299
300 return true;
301@@ -1180,6 +1188,9 @@ duplicate_insn_chain (rtx from, rtx to)
302 break;
303 }
304 copy = emit_copy_of_insn_after (insn, get_last_insn ());
305+ if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
306+ && ANY_RETURN_P (JUMP_LABEL (insn)))
307+ JUMP_LABEL (copy) = JUMP_LABEL (insn);
308 maybe_copy_epilogue_insn (insn, copy);
309 break;
310
311Index: gcc-4_5-branch/gcc/cfgrtl.c
312===================================================================
313--- gcc-4_5-branch.orig/gcc/cfgrtl.c
314+++ gcc-4_5-branch/gcc/cfgrtl.c
315@@ -1107,10 +1107,13 @@ rtl_redirect_edge_and_branch (edge e, ba
316 }
317
318 /* Like force_nonfallthru below, but additionally performs redirection
319- Used by redirect_edge_and_branch_force. */
320+ Used by redirect_edge_and_branch_force. JUMP_LABEL is used only
321+ when redirecting to the EXIT_BLOCK, it is either a return or a
322+ simple_return rtx indicating which kind of returnjump to create.
323+ It should be NULL otherwise. */
324
325-static basic_block
326-force_nonfallthru_and_redirect (edge e, basic_block target)
327+basic_block
328+force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
329 {
330 basic_block jump_block, new_bb = NULL, src = e->src;
331 rtx note;
332@@ -1242,11 +1245,25 @@ force_nonfallthru_and_redirect (edge e,
333 e->flags &= ~EDGE_FALLTHRU;
334 if (target == EXIT_BLOCK_PTR)
335 {
336+ if (jump_label == ret_rtx)
337+ {
338 #ifdef HAVE_return
339- emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc);
340+ emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block),
341+ loc);
342 #else
343- gcc_unreachable ();
344+ gcc_unreachable ();
345 #endif
346+ }
347+ else
348+ {
349+ gcc_assert (jump_label == simple_return_rtx);
350+#ifdef HAVE_simple_return
351+ emit_jump_insn_after_setloc (gen_simple_return (),
352+ BB_END (jump_block), loc);
353+#else
354+ gcc_unreachable ();
355+#endif
356+ }
357 }
358 else
359 {
360@@ -1273,7 +1290,7 @@ force_nonfallthru_and_redirect (edge e,
361 basic_block
362 force_nonfallthru (edge e)
363 {
364- return force_nonfallthru_and_redirect (e, e->dest);
365+ return force_nonfallthru_and_redirect (e, e->dest, NULL_RTX);
366 }
367
368 /* Redirect edge even at the expense of creating new jump insn or
369@@ -1290,7 +1307,7 @@ rtl_redirect_edge_and_branch_force (edge
370 /* In case the edge redirection failed, try to force it to be non-fallthru
371 and redirect newly created simplejump. */
372 df_set_bb_dirty (e->src);
373- return force_nonfallthru_and_redirect (e, target);
374+ return force_nonfallthru_and_redirect (e, target, NULL_RTX);
375 }
376
377 /* The given edge should potentially be a fallthru edge. If that is in
378Index: gcc-4_5-branch/gcc/common.opt
379===================================================================
380--- gcc-4_5-branch.orig/gcc/common.opt
381+++ gcc-4_5-branch/gcc/common.opt
382@@ -1147,6 +1147,11 @@ fshow-column
383 Common C ObjC C++ ObjC++ Report Var(flag_show_column) Init(1)
384 Show column numbers in diagnostics, when available. Default on
385
386+fshrink-wrap
387+Common Report Var(flag_shrink_wrap) Optimization
388+Emit function prologues only before parts of the function that need it,
389+rather than at the top of the function.
390+
391 fsignaling-nans
392 Common Report Var(flag_signaling_nans) Optimization
393 Disable optimizations observable by IEEE signaling NaNs
394Index: gcc-4_5-branch/gcc/config/arm/arm-protos.h
395===================================================================
396--- gcc-4_5-branch.orig/gcc/config/arm/arm-protos.h
397+++ gcc-4_5-branch/gcc/config/arm/arm-protos.h
398@@ -26,6 +26,7 @@
399 extern void arm_override_options (void);
400 extern void arm_optimization_options (int, int);
401 extern int use_return_insn (int, rtx);
402+extern bool use_simple_return_p (void);
403 extern enum reg_class arm_regno_class (int);
404 extern void arm_load_pic_register (unsigned long);
405 extern int arm_volatile_func (void);
406@@ -137,7 +138,7 @@ extern int arm_address_offset_is_imm (rt
407 extern const char *output_add_immediate (rtx *);
408 extern const char *arithmetic_instr (rtx, int);
409 extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
410-extern const char *output_return_instruction (rtx, int, int);
411+extern const char *output_return_instruction (rtx, bool, bool, bool);
412 extern void arm_poke_function_name (FILE *, const char *);
413 extern void arm_print_operand (FILE *, rtx, int);
414 extern void arm_print_operand_address (FILE *, rtx);
415Index: gcc-4_5-branch/gcc/config/arm/arm.c
416===================================================================
417--- gcc-4_5-branch.orig/gcc/config/arm/arm.c
418+++ gcc-4_5-branch/gcc/config/arm/arm.c
419@@ -2163,6 +2163,18 @@ arm_trampoline_adjust_address (rtx addr)
420 return addr;
421 }
422
423+/* Return true if we should try to use a simple_return insn, i.e. perform
424+ shrink-wrapping if possible. This is the case if we need to emit a
425+ prologue, which we can test by looking at the offsets. */
426+bool
427+use_simple_return_p (void)
428+{
429+ arm_stack_offsets *offsets;
430+
431+ offsets = arm_get_frame_offsets ();
432+ return offsets->outgoing_args != 0;
433+}
434+
435 /* Return 1 if it is possible to return using a single instruction.
436 If SIBLING is non-null, this is a test for a return before a sibling
437 call. SIBLING is the call insn, so we can examine its register usage. */
438@@ -11284,6 +11296,7 @@ is_jump_table (rtx insn)
439
440 if (GET_CODE (insn) == JUMP_INSN
441 && JUMP_LABEL (insn) != NULL
442+ && !ANY_RETURN_P (JUMP_LABEL (insn))
443 && ((table = next_real_insn (JUMP_LABEL (insn)))
444 == next_real_insn (insn))
445 && table != NULL
446@@ -14168,7 +14181,7 @@ arm_get_vfp_saved_size (void)
447 /* Generate a function exit sequence. If REALLY_RETURN is false, then do
448 everything bar the final return instruction. */
449 const char *
450-output_return_instruction (rtx operand, int really_return, int reverse)
451+output_return_instruction (rtx operand, bool really_return, bool reverse, bool simple)
452 {
453 char conditional[10];
454 char instr[100];
455@@ -14206,10 +14219,15 @@ output_return_instruction (rtx operand,
456
457 sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd');
458
459- cfun->machine->return_used_this_function = 1;
460+ if (simple)
461+ live_regs_mask = 0;
462+ else
463+ {
464+ cfun->machine->return_used_this_function = 1;
465
466- offsets = arm_get_frame_offsets ();
467- live_regs_mask = offsets->saved_regs_mask;
468+ offsets = arm_get_frame_offsets ();
469+ live_regs_mask = offsets->saved_regs_mask;
470+ }
471
472 if (live_regs_mask)
473 {
474@@ -17108,6 +17126,7 @@ arm_final_prescan_insn (rtx insn)
475
476 /* If we start with a return insn, we only succeed if we find another one. */
477 int seeking_return = 0;
478+ enum rtx_code return_code = UNKNOWN;
479
480 /* START_INSN will hold the insn from where we start looking. This is the
481 first insn after the following code_label if REVERSE is true. */
482@@ -17146,7 +17165,7 @@ arm_final_prescan_insn (rtx insn)
483 else
484 return;
485 }
486- else if (GET_CODE (body) == RETURN)
487+ else if (ANY_RETURN_P (body))
488 {
489 start_insn = next_nonnote_insn (start_insn);
490 if (GET_CODE (start_insn) == BARRIER)
491@@ -17157,6 +17176,7 @@ arm_final_prescan_insn (rtx insn)
492 {
493 reverse = TRUE;
494 seeking_return = 1;
495+ return_code = GET_CODE (body);
496 }
497 else
498 return;
499@@ -17197,11 +17217,15 @@ arm_final_prescan_insn (rtx insn)
500 label = XEXP (XEXP (SET_SRC (body), 2), 0);
501 then_not_else = FALSE;
502 }
503- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN)
504- seeking_return = 1;
505- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
506+ else if (ANY_RETURN_P (XEXP (SET_SRC (body), 1)))
507+ {
508+ seeking_return = 1;
509+ return_code = GET_CODE (XEXP (SET_SRC (body), 1));
510+ }
511+ else if (ANY_RETURN_P (XEXP (SET_SRC (body), 2)))
512 {
513 seeking_return = 1;
514+ return_code = GET_CODE (XEXP (SET_SRC (body), 2));
515 then_not_else = FALSE;
516 }
517 else
518@@ -17302,8 +17326,7 @@ arm_final_prescan_insn (rtx insn)
519 && !use_return_insn (TRUE, NULL)
520 && !optimize_size)
521 fail = TRUE;
522- else if (GET_CODE (scanbody) == RETURN
523- && seeking_return)
524+ else if (GET_CODE (scanbody) == return_code)
525 {
526 arm_ccfsm_state = 2;
527 succeed = TRUE;
528Index: gcc-4_5-branch/gcc/config/arm/arm.h
529===================================================================
530--- gcc-4_5-branch.orig/gcc/config/arm/arm.h
531+++ gcc-4_5-branch/gcc/config/arm/arm.h
532@@ -2622,6 +2622,8 @@ extern int making_const_table;
533 #define RETURN_ADDR_RTX(COUNT, FRAME) \
534 arm_return_addr (COUNT, FRAME)
535
536+#define RETURN_ADDR_REGNUM LR_REGNUM
537+
538 /* Mask of the bits in the PC that contain the real return address
539 when running in 26-bit mode. */
540 #define RETURN_ADDR_MASK26 (0x03fffffc)
541Index: gcc-4_5-branch/gcc/config/arm/arm.md
542===================================================================
543--- gcc-4_5-branch.orig/gcc/config/arm/arm.md
544+++ gcc-4_5-branch/gcc/config/arm/arm.md
545@@ -8882,66 +8882,72 @@
546 [(set_attr "type" "call")]
547 )
548
549-(define_expand "return"
550- [(return)]
551- "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
552+;; Both kinds of return insn.
553+(define_code_iterator returns [return simple_return])
554+(define_code_attr return_str [(return "") (simple_return "simple_")])
555+(define_code_attr return_simple_p [(return "false") (simple_return "true")])
556+(define_code_attr return_cond [(return " && USE_RETURN_INSN (FALSE)")
557+ (simple_return " && use_simple_return_p ()")])
558+
559+(define_expand "<return_str>return"
560+ [(returns)]
561+ "TARGET_32BIT<return_cond>"
562 "")
563
564-;; Often the return insn will be the same as loading from memory, so set attr
565-(define_insn "*arm_return"
566- [(return)]
567- "TARGET_ARM && USE_RETURN_INSN (FALSE)"
568- "*
569- {
570- if (arm_ccfsm_state == 2)
571- {
572- arm_ccfsm_state += 2;
573- return \"\";
574- }
575- return output_return_instruction (const_true_rtx, TRUE, FALSE);
576- }"
577+(define_insn "*arm_<return_str>return"
578+ [(returns)]
579+ "TARGET_ARM<return_cond>"
580+{
581+ if (arm_ccfsm_state == 2)
582+ {
583+ arm_ccfsm_state += 2;
584+ return "";
585+ }
586+ return output_return_instruction (const_true_rtx, true, false,
587+ <return_simple_p>);
588+}
589 [(set_attr "type" "load1")
590 (set_attr "length" "12")
591 (set_attr "predicable" "yes")]
592 )
593
594-(define_insn "*cond_return"
595+(define_insn "*cond_<return_str>return"
596 [(set (pc)
597 (if_then_else (match_operator 0 "arm_comparison_operator"
598 [(match_operand 1 "cc_register" "") (const_int 0)])
599- (return)
600+ (returns)
601 (pc)))]
602- "TARGET_ARM && USE_RETURN_INSN (TRUE)"
603- "*
604- {
605- if (arm_ccfsm_state == 2)
606- {
607- arm_ccfsm_state += 2;
608- return \"\";
609- }
610- return output_return_instruction (operands[0], TRUE, FALSE);
611- }"
612+ "TARGET_ARM<return_cond>"
613+{
614+ if (arm_ccfsm_state == 2)
615+ {
616+ arm_ccfsm_state += 2;
617+ return "";
618+ }
619+ return output_return_instruction (operands[0], true, false,
620+ <return_simple_p>);
621+}
622 [(set_attr "conds" "use")
623 (set_attr "length" "12")
624 (set_attr "type" "load1")]
625 )
626
627-(define_insn "*cond_return_inverted"
628+(define_insn "*cond_<return_str>return_inverted"
629 [(set (pc)
630 (if_then_else (match_operator 0 "arm_comparison_operator"
631 [(match_operand 1 "cc_register" "") (const_int 0)])
632 (pc)
633- (return)))]
634- "TARGET_ARM && USE_RETURN_INSN (TRUE)"
635- "*
636- {
637- if (arm_ccfsm_state == 2)
638- {
639- arm_ccfsm_state += 2;
640- return \"\";
641- }
642- return output_return_instruction (operands[0], TRUE, TRUE);
643- }"
644+ (returns)))]
645+ "TARGET_ARM<return_cond>"
646+{
647+ if (arm_ccfsm_state == 2)
648+ {
649+ arm_ccfsm_state += 2;
650+ return "";
651+ }
652+ return output_return_instruction (operands[0], true, true,
653+ <return_simple_p>);
654+}
655 [(set_attr "conds" "use")
656 (set_attr "length" "12")
657 (set_attr "type" "load1")]
658@@ -10809,8 +10815,7 @@
659 DONE;
660 }
661 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
662- gen_rtvec (1,
663- gen_rtx_RETURN (VOIDmode)),
664+ gen_rtvec (1, ret_rtx),
665 VUNSPEC_EPILOGUE));
666 DONE;
667 "
668@@ -10827,7 +10832,7 @@
669 "TARGET_32BIT"
670 "*
671 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
672- return output_return_instruction (const_true_rtx, FALSE, FALSE);
673+ return output_return_instruction (const_true_rtx, false, false, false);
674 return arm_output_epilogue (next_nonnote_insn (insn));
675 "
676 ;; Length is absolute worst case
677Index: gcc-4_5-branch/gcc/config/arm/thumb2.md
678===================================================================
679--- gcc-4_5-branch.orig/gcc/config/arm/thumb2.md
680+++ gcc-4_5-branch/gcc/config/arm/thumb2.md
681@@ -1020,16 +1020,15 @@
682
683 ;; Note: this is not predicable, to avoid issues with linker-generated
684 ;; interworking stubs.
685-(define_insn "*thumb2_return"
686- [(return)]
687- "TARGET_THUMB2 && USE_RETURN_INSN (FALSE)"
688- "*
689- {
690- return output_return_instruction (const_true_rtx, TRUE, FALSE);
691- }"
692+(define_insn "*thumb2_<return_str>return"
693+ [(returns)]
694+ "TARGET_THUMB2<return_cond>"
695+{
696+ return output_return_instruction (const_true_rtx, true, false,
697+ <return_simple_p>);
698+}
699 [(set_attr "type" "load1")
700- (set_attr "length" "12")]
701-)
702+ (set_attr "length" "12")])
703
704 (define_insn_and_split "thumb2_eh_return"
705 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
706Index: gcc-4_5-branch/gcc/config/bfin/bfin.c
707===================================================================
708--- gcc-4_5-branch.orig/gcc/config/bfin/bfin.c
709+++ gcc-4_5-branch/gcc/config/bfin/bfin.c
710@@ -2359,7 +2359,7 @@ bfin_expand_call (rtx retval, rtx fnaddr
711 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
712 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
713 if (sibcall)
714- XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
715+ XVECEXP (pat, 0, n++) = ret_rtx;
716 else
717 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
718 call = emit_call_insn (pat);
719Index: gcc-4_5-branch/gcc/config/cris/cris.c
720===================================================================
721--- gcc-4_5-branch.orig/gcc/config/cris/cris.c
722+++ gcc-4_5-branch/gcc/config/cris/cris.c
723@@ -1771,7 +1771,7 @@ cris_expand_return (bool on_stack)
724 we do that until they're fixed. Currently, all return insns in a
725 function must be the same (not really a limiting factor) so we need
726 to check that it doesn't change half-way through. */
727- emit_jump_insn (gen_rtx_RETURN (VOIDmode));
728+ emit_jump_insn (ret_rtx);
729
730 CRIS_ASSERT (cfun->machine->return_type != CRIS_RETINSN_RET || !on_stack);
731 CRIS_ASSERT (cfun->machine->return_type != CRIS_RETINSN_JUMP || on_stack);
732Index: gcc-4_5-branch/gcc/config/h8300/h8300.c
733===================================================================
734--- gcc-4_5-branch.orig/gcc/config/h8300/h8300.c
735+++ gcc-4_5-branch/gcc/config/h8300/h8300.c
736@@ -691,7 +691,7 @@ h8300_push_pop (int regno, int nregs, bo
737 /* Add the return instruction. */
738 if (return_p)
739 {
740- RTVEC_ELT (vec, i) = gen_rtx_RETURN (VOIDmode);
741+ RTVEC_ELT (vec, i) = ret_rtx;
742 i++;
743 }
744
745@@ -975,7 +975,7 @@ h8300_expand_epilogue (void)
746 }
747
748 if (!returned_p)
749- emit_jump_insn (gen_rtx_RETURN (VOIDmode));
750+ emit_jump_insn (ret_rtx);
751 }
752
753 /* Return nonzero if the current function is an interrupt
754Index: gcc-4_5-branch/gcc/config/i386/i386.c
755===================================================================
756--- gcc-4_5-branch.orig/gcc/config/i386/i386.c
757+++ gcc-4_5-branch/gcc/config/i386/i386.c
758@@ -9308,13 +9308,13 @@ ix86_expand_epilogue (int style)
759
760 pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
761 popc, -1, true);
762- emit_jump_insn (gen_return_indirect_internal (ecx));
763+ emit_jump_insn (gen_simple_return_indirect_internal (ecx));
764 }
765 else
766- emit_jump_insn (gen_return_pop_internal (popc));
767+ emit_jump_insn (gen_simple_return_pop_internal (popc));
768 }
769 else
770- emit_jump_insn (gen_return_internal ());
771+ emit_jump_insn (gen_simple_return_internal ());
772
773 /* Restore the state back to the state from the prologue,
774 so that it's correct for the next epilogue. */
775@@ -26615,7 +26615,7 @@ ix86_pad_returns (void)
776 rtx prev;
777 bool replace = false;
778
779- if (!JUMP_P (ret) || GET_CODE (PATTERN (ret)) != RETURN
780+ if (!JUMP_P (ret) || !ANY_RETURN_P (PATTERN (ret))
781 || optimize_bb_for_size_p (bb))
782 continue;
783 for (prev = PREV_INSN (ret); prev; prev = PREV_INSN (prev))
784@@ -26645,7 +26645,10 @@ ix86_pad_returns (void)
785 }
786 if (replace)
787 {
788- emit_jump_insn_before (gen_return_internal_long (), ret);
789+ if (PATTERN (ret) == ret_rtx)
790+ emit_jump_insn_before (gen_return_internal_long (), ret);
791+ else
792+ emit_jump_insn_before (gen_simple_return_internal_long (), ret);
793 delete_insn (ret);
794 }
795 }
796Index: gcc-4_5-branch/gcc/config/i386/i386.md
797===================================================================
798--- gcc-4_5-branch.orig/gcc/config/i386/i386.md
799+++ gcc-4_5-branch/gcc/config/i386/i386.md
800@@ -13798,24 +13798,29 @@
801 ""
802 [(set_attr "length" "0")])
803
804+(define_code_iterator returns [return simple_return])
805+(define_code_attr return_str [(return "") (simple_return "simple_")])
806+(define_code_attr return_cond [(return "ix86_can_use_return_insn_p ()")
807+ (simple_return "")])
808+
809 ;; Insn emitted into the body of a function to return from a function.
810 ;; This is only done if the function's epilogue is known to be simple.
811 ;; See comments for ix86_can_use_return_insn_p in i386.c.
812
813-(define_expand "return"
814- [(return)]
815- "ix86_can_use_return_insn_p ()"
816+(define_expand "<return_str>return"
817+ [(returns)]
818+ "<return_cond>"
819 {
820 if (crtl->args.pops_args)
821 {
822 rtx popc = GEN_INT (crtl->args.pops_args);
823- emit_jump_insn (gen_return_pop_internal (popc));
824+ emit_jump_insn (gen_<return_str>return_pop_internal (popc));
825 DONE;
826 }
827 })
828
829-(define_insn "return_internal"
830- [(return)]
831+(define_insn "<return_str>return_internal"
832+ [(returns)]
833 "reload_completed"
834 "ret"
835 [(set_attr "length" "1")
836@@ -13826,8 +13831,8 @@
837 ;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
838 ;; instruction Athlon and K8 have.
839
840-(define_insn "return_internal_long"
841- [(return)
842+(define_insn "<return_str>return_internal_long"
843+ [(returns)
844 (unspec [(const_int 0)] UNSPEC_REP)]
845 "reload_completed"
846 "rep\;ret"
847@@ -13837,8 +13842,8 @@
848 (set_attr "prefix_rep" "1")
849 (set_attr "modrm" "0")])
850
851-(define_insn "return_pop_internal"
852- [(return)
853+(define_insn "<return_str>return_pop_internal"
854+ [(returns)
855 (use (match_operand:SI 0 "const_int_operand" ""))]
856 "reload_completed"
857 "ret\t%0"
858@@ -13847,8 +13852,8 @@
859 (set_attr "length_immediate" "2")
860 (set_attr "modrm" "0")])
861
862-(define_insn "return_indirect_internal"
863- [(return)
864+(define_insn "<return_str>return_indirect_internal"
865+ [(returns)
866 (use (match_operand:SI 0 "register_operand" "r"))]
867 "reload_completed"
868 "jmp\t%A0"
869Index: gcc-4_5-branch/gcc/config/m68hc11/m68hc11.md
870===================================================================
871--- gcc-4_5-branch.orig/gcc/config/m68hc11/m68hc11.md
872+++ gcc-4_5-branch/gcc/config/m68hc11/m68hc11.md
873@@ -6576,7 +6576,7 @@
874 if (ret_size && ret_size <= 2)
875 {
876 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
877- gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
878+ gen_rtvec (2, ret_rtx,
879 gen_rtx_USE (VOIDmode,
880 gen_rtx_REG (HImode, 1)))));
881 DONE;
882@@ -6584,7 +6584,7 @@
883 if (ret_size)
884 {
885 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
886- gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
887+ gen_rtvec (2, ret_rtx,
888 gen_rtx_USE (VOIDmode,
889 gen_rtx_REG (SImode, 0)))));
890 DONE;
891Index: gcc-4_5-branch/gcc/config/m68k/m68k.c
892===================================================================
893--- gcc-4_5-branch.orig/gcc/config/m68k/m68k.c
894+++ gcc-4_5-branch/gcc/config/m68k/m68k.c
895@@ -1366,7 +1366,7 @@ m68k_expand_epilogue (bool sibcall_p)
896 EH_RETURN_STACKADJ_RTX));
897
898 if (!sibcall_p)
899- emit_jump_insn (gen_rtx_RETURN (VOIDmode));
900+ emit_jump_insn (ret_rtx);
901 }
902
903 /* Return true if X is a valid comparison operator for the dbcc
904Index: gcc-4_5-branch/gcc/config/mips/mips.c
905===================================================================
906--- gcc-4_5-branch.orig/gcc/config/mips/mips.c
907+++ gcc-4_5-branch/gcc/config/mips/mips.c
908@@ -10497,7 +10497,8 @@ mips_expand_epilogue (bool sibcall_p)
909 regno = GP_REG_FIRST + 7;
910 else
911 regno = RETURN_ADDR_REGNUM;
912- emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, regno)));
913+ emit_jump_insn (gen_simple_return_internal (gen_rtx_REG (Pmode,
914+ regno)));
915 }
916 }
917
918Index: gcc-4_5-branch/gcc/config/mips/mips.md
919===================================================================
920--- gcc-4_5-branch.orig/gcc/config/mips/mips.md
921+++ gcc-4_5-branch/gcc/config/mips/mips.md
922@@ -5815,6 +5815,18 @@
923 [(set_attr "type" "jump")
924 (set_attr "mode" "none")])
925
926+(define_expand "simple_return"
927+ [(simple_return)]
928+ "!mips_can_use_return_insn ()"
929+ { mips_expand_before_return (); })
930+
931+(define_insn "*simple_return"
932+ [(simple_return)]
933+ "!mips_can_use_return_insn ()"
934+ "%*j\t$31%/"
935+ [(set_attr "type" "jump")
936+ (set_attr "mode" "none")])
937+
938 ;; Normal return.
939
940 (define_insn "return_internal"
941@@ -5825,6 +5837,14 @@
942 [(set_attr "type" "jump")
943 (set_attr "mode" "none")])
944
945+(define_insn "simple_return_internal"
946+ [(simple_return)
947+ (use (match_operand 0 "pmode_register_operand" ""))]
948+ ""
949+ "%*j\t%0%/"
950+ [(set_attr "type" "jump")
951+ (set_attr "mode" "none")])
952+
953 ;; Exception return.
954 (define_insn "mips_eret"
955 [(return)
956Index: gcc-4_5-branch/gcc/config/picochip/picochip.c
957===================================================================
958--- gcc-4_5-branch.orig/gcc/config/picochip/picochip.c
959+++ gcc-4_5-branch/gcc/config/picochip/picochip.c
960@@ -1996,7 +1996,7 @@ picochip_expand_epilogue (int is_sibling
961 rtvec p;
962 p = rtvec_alloc (2);
963
964- RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
965+ RTVEC_ELT (p, 0) = ret_rtx;
966 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
967 gen_rtx_REG (Pmode, LINK_REGNUM));
968 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
969Index: gcc-4_5-branch/gcc/config/rs6000/rs6000.c
970===================================================================
971--- gcc-4_5-branch.orig/gcc/config/rs6000/rs6000.c
972+++ gcc-4_5-branch/gcc/config/rs6000/rs6000.c
973@@ -18563,7 +18563,7 @@ rs6000_make_savres_rtx (rs6000_stack_t *
974 p = rtvec_alloc ((lr ? 4 : 3) + n_regs);
975
976 if (!savep && lr)
977- RTVEC_ELT (p, offset++) = gen_rtx_RETURN (VOIDmode);
978+ RTVEC_ELT (p, offset++) = ret_rtx;
979
980 RTVEC_ELT (p, offset++)
981 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
982@@ -19638,7 +19638,7 @@ rs6000_emit_epilogue (int sibcall)
983 alloc_rname = ggc_strdup (rname);
984
985 j = 0;
986- RTVEC_ELT (p, j++) = gen_rtx_RETURN (VOIDmode);
987+ RTVEC_ELT (p, j++) = ret_rtx;
988 RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
989 gen_rtx_REG (Pmode,
990 LR_REGNO));
991@@ -20254,7 +20254,7 @@ rs6000_emit_epilogue (int sibcall)
992 else
993 p = rtvec_alloc (2);
994
995- RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
996+ RTVEC_ELT (p, 0) = ret_rtx;
997 RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
998 ? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65))
999 : gen_rtx_CLOBBER (VOIDmode,
1000@@ -20695,7 +20695,7 @@ rs6000_output_mi_thunk (FILE *file, tree
1001 gen_rtx_USE (VOIDmode,
1002 gen_rtx_REG (SImode,
1003 LR_REGNO)),
1004- gen_rtx_RETURN (VOIDmode))));
1005+ ret_rtx)));
1006 SIBLING_CALL_P (insn) = 1;
1007 emit_barrier ();
1008
1009Index: gcc-4_5-branch/gcc/config/rx/rx.c
1010===================================================================
1011--- gcc-4_5-branch.orig/gcc/config/rx/rx.c
1012+++ gcc-4_5-branch/gcc/config/rx/rx.c
1013@@ -1562,7 +1562,7 @@ gen_rx_rtsd_vector (unsigned int adjust,
1014 : plus_constant (stack_pointer_rtx,
1015 i * UNITS_PER_WORD)));
1016
1017- XVECEXP (vector, 0, count - 1) = gen_rtx_RETURN (VOIDmode);
1018+ XVECEXP (vector, 0, count - 1) = ret_rtx;
1019
1020 return vector;
1021 }
1022Index: gcc-4_5-branch/gcc/config/s390/s390.c
1023===================================================================
1024--- gcc-4_5-branch.orig/gcc/config/s390/s390.c
1025+++ gcc-4_5-branch/gcc/config/s390/s390.c
1026@@ -8170,7 +8170,7 @@ s390_emit_epilogue (bool sibcall)
1027
1028 p = rtvec_alloc (2);
1029
1030- RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
1031+ RTVEC_ELT (p, 0) = ret_rtx;
1032 RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
1033 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
1034 }
1035Index: gcc-4_5-branch/gcc/config/sh/sh.c
1036===================================================================
1037--- gcc-4_5-branch.orig/gcc/config/sh/sh.c
1038+++ gcc-4_5-branch/gcc/config/sh/sh.c
1039@@ -5252,7 +5252,8 @@ barrier_align (rtx barrier_or_label)
1040 }
1041 if (prev
1042 && JUMP_P (prev)
1043- && JUMP_LABEL (prev))
1044+ && JUMP_LABEL (prev)
1045+ && !ANY_RETURN_P (JUMP_LABEL (prev)))
1046 {
1047 rtx x;
1048 if (jump_to_next
1049@@ -5951,7 +5952,7 @@ split_branches (rtx first)
1050 JUMP_LABEL (insn) = far_label;
1051 LABEL_NUSES (far_label)++;
1052 }
1053- redirect_jump (insn, NULL_RTX, 1);
1054+ redirect_jump (insn, ret_rtx, 1);
1055 far_label = 0;
1056 }
1057 }
1058Index: gcc-4_5-branch/gcc/config/v850/v850.c
1059===================================================================
1060--- gcc-4_5-branch.orig/gcc/config/v850/v850.c
1061+++ gcc-4_5-branch/gcc/config/v850/v850.c
1062@@ -1832,7 +1832,7 @@ expand_epilogue (void)
1063 {
1064 restore_all = gen_rtx_PARALLEL (VOIDmode,
1065 rtvec_alloc (num_restore + 2));
1066- XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode);
1067+ XVECEXP (restore_all, 0, 0) = ret_rtx;
1068 XVECEXP (restore_all, 0, 1)
1069 = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1070 gen_rtx_PLUS (Pmode,
1071Index: gcc-4_5-branch/gcc/df-scan.c
1072===================================================================
1073--- gcc-4_5-branch.orig/gcc/df-scan.c
1074+++ gcc-4_5-branch/gcc/df-scan.c
1075@@ -3296,6 +3296,7 @@ df_uses_record (enum df_ref_class cl, st
1076 }
1077
1078 case RETURN:
1079+ case SIMPLE_RETURN:
1080 break;
1081
1082 case ASM_OPERANDS:
1083Index: gcc-4_5-branch/gcc/doc/invoke.texi
1084===================================================================
1085--- gcc-4_5-branch.orig/gcc/doc/invoke.texi
1086+++ gcc-4_5-branch/gcc/doc/invoke.texi
1087@@ -5751,6 +5751,7 @@ compilation time.
1088 -fipa-pure-const @gol
1089 -fipa-reference @gol
1090 -fmerge-constants
1091+-fshrink-wrap @gol
1092 -fsplit-wide-types @gol
1093 -ftree-builtin-call-dce @gol
1094 -ftree-ccp @gol
1095@@ -6506,6 +6507,12 @@ This option has no effect until one of @
1096 When pipelining loops during selective scheduling, also pipeline outer loops.
1097 This option has no effect until @option{-fsel-sched-pipelining} is turned on.
1098
1099+@item -fshrink-wrap
1100+@opindex fshrink-wrap
1101+Emit function prologues only before parts of the function that need it,
1102+rather than at the top of the function. This flag is enabled by default at
1103+@option{-O} and higher.
1104+
1105 @item -fcaller-saves
1106 @opindex fcaller-saves
1107 Enable values to be allocated in registers that will be clobbered by
1108Index: gcc-4_5-branch/gcc/doc/md.texi
1109===================================================================
1110--- gcc-4_5-branch.orig/gcc/doc/md.texi
1111+++ gcc-4_5-branch/gcc/doc/md.texi
1112@@ -4801,7 +4801,19 @@ RTL generation phase. In this case it i
1113 multiple instructions are usually needed to return from a function, but
1114 some class of functions only requires one instruction to implement a
1115 return. Normally, the applicable functions are those which do not need
1116-to save any registers or allocate stack space.
1117+to save any registers or allocate stack space, although some targets
1118+have instructions that can perform both the epilogue and function return
1119+in one instruction.
1120+
1121+@cindex @code{simple_return} instruction pattern
1122+@item @samp{simple_return}
1123+Subroutine return instruction. This instruction pattern name should be
1124+defined only if a single instruction can do all the work of returning
1125+from a function on a path where no epilogue is required. This pattern
1126+is very similar to the @code{return} instruction pattern, but it is emitted
1127+only by the shrink-wrapping optimization on paths where the function
1128+prologue has not been executed, and a function return should occur without
1129+any of the effects of the epilogue.
1130
1131 @findex reload_completed
1132 @findex leaf_function_p
1133Index: gcc-4_5-branch/gcc/doc/rtl.texi
1134===================================================================
1135--- gcc-4_5-branch.orig/gcc/doc/rtl.texi
1136+++ gcc-4_5-branch/gcc/doc/rtl.texi
1137@@ -2888,6 +2888,13 @@ placed in @code{pc} to return to the cal
1138 Note that an insn pattern of @code{(return)} is logically equivalent to
1139 @code{(set (pc) (return))}, but the latter form is never used.
1140
1141+@findex simple_return
1142+@item (simple_return)
1143+Like @code{(return)}, but truly represents only a function return, while
1144+@code{(return)} may represent an insn that also performs other functions
1145+of the function epilogue. Like @code{(return)}, this may also occur in
1146+conditional jumps.
1147+
1148 @findex call
1149 @item (call @var{function} @var{nargs})
1150 Represents a function call. @var{function} is a @code{mem} expression
1151@@ -3017,7 +3024,7 @@ Represents several side effects performe
1152 brackets stand for a vector; the operand of @code{parallel} is a
1153 vector of expressions. @var{x0}, @var{x1} and so on are individual
1154 side effect expressions---expressions of code @code{set}, @code{call},
1155-@code{return}, @code{clobber} or @code{use}.
1156+@code{return}, @code{simple_return}, @code{clobber} or @code{use}.
1157
1158 ``In parallel'' means that first all the values used in the individual
1159 side-effects are computed, and second all the actual side-effects are
1160@@ -3656,14 +3663,16 @@ and @code{call_insn} insns:
1161 @table @code
1162 @findex PATTERN
1163 @item PATTERN (@var{i})
1164-An expression for the side effect performed by this insn. This must be
1165-one of the following codes: @code{set}, @code{call}, @code{use},
1166-@code{clobber}, @code{return}, @code{asm_input}, @code{asm_output},
1167-@code{addr_vec}, @code{addr_diff_vec}, @code{trap_if}, @code{unspec},
1168-@code{unspec_volatile}, @code{parallel}, @code{cond_exec}, or @code{sequence}. If it is a @code{parallel},
1169-each element of the @code{parallel} must be one these codes, except that
1170-@code{parallel} expressions cannot be nested and @code{addr_vec} and
1171-@code{addr_diff_vec} are not permitted inside a @code{parallel} expression.
1172+An expression for the side effect performed by this insn. This must
1173+be one of the following codes: @code{set}, @code{call}, @code{use},
1174+@code{clobber}, @code{return}, @code{simple_return}, @code{asm_input},
1175+@code{asm_output}, @code{addr_vec}, @code{addr_diff_vec},
1176+@code{trap_if}, @code{unspec}, @code{unspec_volatile},
1177+@code{parallel}, @code{cond_exec}, or @code{sequence}. If it is a
1178+@code{parallel}, each element of the @code{parallel} must be one these
1179+codes, except that @code{parallel} expressions cannot be nested and
1180+@code{addr_vec} and @code{addr_diff_vec} are not permitted inside a
1181+@code{parallel} expression.
1182
1183 @findex INSN_CODE
1184 @item INSN_CODE (@var{i})
1185Index: gcc-4_5-branch/gcc/doc/tm.texi
1186===================================================================
1187--- gcc-4_5-branch.orig/gcc/doc/tm.texi
1188+++ gcc-4_5-branch/gcc/doc/tm.texi
1189@@ -3287,6 +3287,12 @@ Define this if the return address of a p
1190 from the frame pointer of the previous stack frame.
1191 @end defmac
1192
1193+@defmac RETURN_ADDR_REGNUM
1194+If defined, a C expression whose value is the register number of the return
1195+address for the current function. Targets that pass the return address on
1196+the stack should not define this macro.
1197+@end defmac
1198+
1199 @defmac INCOMING_RETURN_ADDR_RTX
1200 A C expression whose value is RTL representing the location of the
1201 incoming return address at the beginning of any function, before the
1202Index: gcc-4_5-branch/gcc/dwarf2out.c
1203===================================================================
1204--- gcc-4_5-branch.orig/gcc/dwarf2out.c
1205+++ gcc-4_5-branch/gcc/dwarf2out.c
1206@@ -1396,7 +1396,7 @@ compute_barrier_args_size_1 (rtx insn, H
1207 {
1208 rtx dest = JUMP_LABEL (insn);
1209
1210- if (dest)
1211+ if (dest && !ANY_RETURN_P (dest))
1212 {
1213 if (barrier_args_size [INSN_UID (dest)] < 0)
1214 {
1215Index: gcc-4_5-branch/gcc/emit-rtl.c
1216===================================================================
1217--- gcc-4_5-branch.orig/gcc/emit-rtl.c
1218+++ gcc-4_5-branch/gcc/emit-rtl.c
1219@@ -2432,6 +2432,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
1220 case CODE_LABEL:
1221 case PC:
1222 case CC0:
1223+ case RETURN:
1224+ case SIMPLE_RETURN:
1225 case SCRATCH:
1226 return;
1227 /* SCRATCH must be shared because they represent distinct values. */
1228@@ -3323,14 +3325,17 @@ prev_label (rtx insn)
1229 return insn;
1230 }
1231
1232-/* Return the last label to mark the same position as LABEL. Return null
1233- if LABEL itself is null. */
1234+/* Return the last label to mark the same position as LABEL. Return LABEL
1235+ itself if it is null or any return rtx. */
1236
1237 rtx
1238 skip_consecutive_labels (rtx label)
1239 {
1240 rtx insn;
1241
1242+ if (label && ANY_RETURN_P (label))
1243+ return label;
1244+
1245 for (insn = label; insn != 0 && !INSN_P (insn); insn = NEXT_INSN (insn))
1246 if (LABEL_P (insn))
1247 label = insn;
1248@@ -5209,7 +5214,7 @@ classify_insn (rtx x)
1249 return CODE_LABEL;
1250 if (GET_CODE (x) == CALL)
1251 return CALL_INSN;
1252- if (GET_CODE (x) == RETURN)
1253+ if (GET_CODE (x) == RETURN || GET_CODE (x) == SIMPLE_RETURN)
1254 return JUMP_INSN;
1255 if (GET_CODE (x) == SET)
1256 {
1257@@ -5715,8 +5720,10 @@ init_emit_regs (void)
1258 init_reg_modes_target ();
1259
1260 /* Assign register numbers to the globally defined register rtx. */
1261- pc_rtx = gen_rtx_PC (VOIDmode);
1262- cc0_rtx = gen_rtx_CC0 (VOIDmode);
1263+ pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
1264+ ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
1265+ simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
1266+ cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
1267 stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
1268 frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
1269 hard_frame_pointer_rtx = gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
1270Index: gcc-4_5-branch/gcc/final.c
1271===================================================================
1272--- gcc-4_5-branch.orig/gcc/final.c
1273+++ gcc-4_5-branch/gcc/final.c
1274@@ -2428,7 +2428,7 @@ final_scan_insn (rtx insn, FILE *file, i
1275 delete_insn (insn);
1276 break;
1277 }
1278- else if (GET_CODE (SET_SRC (body)) == RETURN)
1279+ else if (ANY_RETURN_P (SET_SRC (body)))
1280 /* Replace (set (pc) (return)) with (return). */
1281 PATTERN (insn) = body = SET_SRC (body);
1282
1283Index: gcc-4_5-branch/gcc/function.c
1284===================================================================
1285--- gcc-4_5-branch.orig/gcc/function.c
1286+++ gcc-4_5-branch/gcc/function.c
1287@@ -147,9 +147,6 @@ extern tree debug_find_var_in_block_tree
1288 can always export `prologue_epilogue_contains'. */
1289 static void record_insns (rtx, rtx, htab_t *) ATTRIBUTE_UNUSED;
1290 static bool contains (const_rtx, htab_t);
1291-#ifdef HAVE_return
1292-static void emit_return_into_block (basic_block);
1293-#endif
1294 static void prepare_function_start (void);
1295 static void do_clobber_return_reg (rtx, void *);
1296 static void do_use_return_reg (rtx, void *);
1297@@ -4987,35 +4984,190 @@ prologue_epilogue_contains (const_rtx in
1298 return 0;
1299 }
1300
1301+#ifdef HAVE_simple_return
1302+/* This collects sets and clobbers of hard registers in a HARD_REG_SET,
1303+ which is pointed to by DATA. */
1304+static void
1305+record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
1306+{
1307+ HARD_REG_SET *pset = (HARD_REG_SET *)data;
1308+ if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
1309+ {
1310+ int nregs = hard_regno_nregs[REGNO (x)][GET_MODE (x)];
1311+ while (nregs-- > 0)
1312+ SET_HARD_REG_BIT (*pset, REGNO (x) + nregs);
1313+ }
1314+}
1315+
1316+/* A subroutine of requires_stack_frame_p, called via for_each_rtx.
1317+ If any change is made, set CHANGED
1318+ to true. */
1319+
1320+static int
1321+frame_required_for_rtx (rtx *loc, void *data ATTRIBUTE_UNUSED)
1322+{
1323+ rtx x = *loc;
1324+ if (x == stack_pointer_rtx || x == hard_frame_pointer_rtx
1325+ || x == arg_pointer_rtx || x == pic_offset_table_rtx
1326+#ifdef RETURN_ADDR_REGNUM
1327+ || (REG_P (x) && REGNO (x) == RETURN_ADDR_REGNUM)
1328+#endif
1329+ )
1330+ return 1;
1331+ return 0;
1332+}
1333+
1334+static bool
1335+requires_stack_frame_p (rtx insn)
1336+{
1337+ HARD_REG_SET hardregs;
1338+ unsigned regno;
1339+
1340+ if (!INSN_P (insn) || DEBUG_INSN_P (insn))
1341+ return false;
1342+ if (CALL_P (insn))
1343+ return !SIBLING_CALL_P (insn);
1344+ if (for_each_rtx (&PATTERN (insn), frame_required_for_rtx, NULL))
1345+ return true;
1346+ CLEAR_HARD_REG_SET (hardregs);
1347+ note_stores (PATTERN (insn), record_hard_reg_sets, &hardregs);
1348+ AND_COMPL_HARD_REG_SET (hardregs, call_used_reg_set);
1349+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1350+ if (TEST_HARD_REG_BIT (hardregs, regno)
1351+ && df_regs_ever_live_p (regno))
1352+ return true;
1353+ return false;
1354+}
1355+#endif
1356+
1357 #ifdef HAVE_return
1358-/* Insert gen_return at the end of block BB. This also means updating
1359- block_for_insn appropriately. */
1360+
1361+static rtx
1362+gen_return_pattern (bool simple_p)
1363+{
1364+#ifdef HAVE_simple_return
1365+ return simple_p ? gen_simple_return () : gen_return ();
1366+#else
1367+ gcc_assert (!simple_p);
1368+ return gen_return ();
1369+#endif
1370+}
1371+
1372+/* Insert an appropriate return pattern at the end of block BB. This
1373+ also means updating block_for_insn appropriately. */
1374
1375 static void
1376-emit_return_into_block (basic_block bb)
1377+emit_return_into_block (bool simple_p, basic_block bb)
1378 {
1379- emit_jump_insn_after (gen_return (), BB_END (bb));
1380+ rtx jump;
1381+ jump = emit_jump_insn_after (gen_return_pattern (simple_p), BB_END (bb));
1382+ JUMP_LABEL (jump) = simple_p ? simple_return_rtx : ret_rtx;
1383 }
1384-#endif /* HAVE_return */
1385+#endif
1386
1387 /* Generate the prologue and epilogue RTL if the machine supports it. Thread
1388 this into place with notes indicating where the prologue ends and where
1389- the epilogue begins. Update the basic block information when possible. */
1390+ the epilogue begins. Update the basic block information when possible.
1391+
1392+ Notes on epilogue placement:
1393+ There are several kinds of edges to the exit block:
1394+ * a single fallthru edge from LAST_BB
1395+ * possibly, edges from blocks containing sibcalls
1396+ * possibly, fake edges from infinite loops
1397+
1398+ The epilogue is always emitted on the fallthru edge from the last basic
1399+ block in the function, LAST_BB, into the exit block.
1400+
1401+ If LAST_BB is empty except for a label, it is the target of every
1402+ other basic block in the function that ends in a return. If a
1403+ target has a return or simple_return pattern (possibly with
1404+ conditional variants), these basic blocks can be changed so that a
1405+ return insn is emitted into them, and their target is adjusted to
1406+ the real exit block.
1407+
1408+ Notes on shrink wrapping: We implement a fairly conservative
1409+ version of shrink-wrapping rather than the textbook one. We only
1410+ generate a single prologue and a single epilogue. This is
1411+ sufficient to catch a number of interesting cases involving early
1412+ exits.
1413+
1414+ First, we identify the blocks that require the prologue to occur before
1415+ them. These are the ones that modify a call-saved register, or reference
1416+ any of the stack or frame pointer registers. To simplify things, we then
1417+ mark everything reachable from these blocks as also requiring a prologue.
1418+ This takes care of loops automatically, and avoids the need to examine
1419+ whether MEMs reference the frame, since it is sufficient to check for
1420+ occurrences of the stack or frame pointer.
1421+
1422+ We then compute the set of blocks for which the need for a prologue
1423+ is anticipatable (borrowing terminology from the shrink-wrapping
1424+ description in Muchnick's book). These are the blocks which either
1425+ require a prologue themselves, or those that have only successors
1426+ where the prologue is anticipatable. The prologue needs to be
1427+ inserted on all edges from BB1->BB2 where BB2 is in ANTIC and BB1
1428+ is not. For the moment, we ensure that only one such edge exists.
1429+
1430+ The epilogue is placed as described above, but we make a
1431+ distinction between inserting return and simple_return patterns
1432+ when modifying other blocks that end in a return. Blocks that end
1433+ in a sibcall omit the sibcall_epilogue if the block is not in
1434+ ANTIC. */
1435
1436 static void
1437 thread_prologue_and_epilogue_insns (void)
1438 {
1439 int inserted = 0;
1440+ basic_block last_bb;
1441+ bool last_bb_active;
1442+#ifdef HAVE_simple_return
1443+ bool unconverted_simple_returns = false;
1444+ basic_block simple_return_block = NULL;
1445+#endif
1446+ rtx returnjump ATTRIBUTE_UNUSED;
1447+ rtx seq ATTRIBUTE_UNUSED, epilogue_end ATTRIBUTE_UNUSED;
1448+ rtx prologue_seq ATTRIBUTE_UNUSED, split_prologue_seq ATTRIBUTE_UNUSED;
1449+ edge entry_edge, orig_entry_edge, exit_fallthru_edge;
1450 edge e;
1451-#if defined (HAVE_sibcall_epilogue) || defined (HAVE_epilogue) || defined (HAVE_return) || defined (HAVE_prologue)
1452- rtx seq;
1453-#endif
1454-#if defined (HAVE_epilogue) || defined(HAVE_return)
1455- rtx epilogue_end = NULL_RTX;
1456-#endif
1457 edge_iterator ei;
1458+ bitmap_head bb_flags;
1459+
1460+ df_analyze ();
1461
1462 rtl_profile_for_bb (ENTRY_BLOCK_PTR);
1463+
1464+ epilogue_end = NULL_RTX;
1465+ returnjump = NULL_RTX;
1466+
1467+ /* Can't deal with multiple successors of the entry block at the
1468+ moment. Function should always have at least one entry
1469+ point. */
1470+ gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
1471+ entry_edge = single_succ_edge (ENTRY_BLOCK_PTR);
1472+ orig_entry_edge = entry_edge;
1473+
1474+ exit_fallthru_edge = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
1475+ if (exit_fallthru_edge != NULL)
1476+ {
1477+ rtx label;
1478+
1479+ last_bb = exit_fallthru_edge->src;
1480+ /* Test whether there are active instructions in the last block. */
1481+ label = BB_END (last_bb);
1482+ while (label && !LABEL_P (label))
1483+ {
1484+ if (active_insn_p (label))
1485+ break;
1486+ label = PREV_INSN (label);
1487+ }
1488+
1489+ last_bb_active = BB_HEAD (last_bb) != label || !LABEL_P (label);
1490+ }
1491+ else
1492+ {
1493+ last_bb = NULL;
1494+ last_bb_active = false;
1495+ }
1496+
1497 #ifdef HAVE_prologue
1498 if (HAVE_prologue)
1499 {
1500@@ -5040,20 +5192,169 @@ thread_prologue_and_epilogue_insns (void
1501 emit_insn (gen_blockage ());
1502 #endif
1503
1504- seq = get_insns ();
1505+ prologue_seq = get_insns ();
1506 end_sequence ();
1507 set_insn_locators (seq, prologue_locator);
1508+ }
1509+#endif
1510
1511- /* Can't deal with multiple successors of the entry block
1512- at the moment. Function should always have at least one
1513- entry point. */
1514- gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
1515+ bitmap_initialize (&bb_flags, &bitmap_default_obstack);
1516
1517- insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
1518- inserted = 1;
1519+#ifdef HAVE_simple_return
1520+ /* Try to perform a kind of shrink-wrapping, making sure the
1521+ prologue/epilogue is emitted only around those parts of the
1522+ function that require it. */
1523+
1524+ if (flag_shrink_wrap && HAVE_simple_return && !flag_non_call_exceptions
1525+ && HAVE_prologue && !crtl->calls_eh_return)
1526+ {
1527+ HARD_REG_SET prologue_clobbered, live_on_edge;
1528+ rtx p_insn;
1529+ VEC(basic_block, heap) *vec;
1530+ basic_block bb;
1531+ bitmap_head bb_antic_flags;
1532+ bitmap_head bb_on_list;
1533+
1534+ bitmap_initialize (&bb_antic_flags, &bitmap_default_obstack);
1535+ bitmap_initialize (&bb_on_list, &bitmap_default_obstack);
1536+
1537+ vec = VEC_alloc (basic_block, heap, n_basic_blocks);
1538+
1539+ FOR_EACH_BB (bb)
1540+ {
1541+ rtx insn;
1542+ FOR_BB_INSNS (bb, insn)
1543+ {
1544+ if (requires_stack_frame_p (insn))
1545+ {
1546+ bitmap_set_bit (&bb_flags, bb->index);
1547+ VEC_quick_push (basic_block, vec, bb);
1548+ break;
1549+ }
1550+ }
1551+ }
1552+
1553+ /* For every basic block that needs a prologue, mark all blocks
1554+ reachable from it, so as to ensure they are also seen as
1555+ requiring a prologue. */
1556+ while (!VEC_empty (basic_block, vec))
1557+ {
1558+ basic_block tmp_bb = VEC_pop (basic_block, vec);
1559+ edge e;
1560+ edge_iterator ei;
1561+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
1562+ {
1563+ if (e->dest == EXIT_BLOCK_PTR
1564+ || bitmap_bit_p (&bb_flags, e->dest->index))
1565+ continue;
1566+ bitmap_set_bit (&bb_flags, e->dest->index);
1567+ VEC_quick_push (basic_block, vec, e->dest);
1568+ }
1569+ }
1570+ /* If the last basic block contains only a label, we'll be able
1571+ to convert jumps to it to (potentially conditional) return
1572+ insns later. This means we don't necessarily need a prologue
1573+ for paths reaching it. */
1574+ if (last_bb)
1575+ {
1576+ if (!last_bb_active)
1577+ bitmap_clear_bit (&bb_flags, last_bb->index);
1578+ else if (!bitmap_bit_p (&bb_flags, last_bb->index))
1579+ goto fail_shrinkwrap;
1580+ }
1581+
1582+ /* Now walk backwards from every block that is marked as needing
1583+ a prologue to compute the bb_antic_flags bitmap. */
1584+ bitmap_copy (&bb_antic_flags, &bb_flags);
1585+ FOR_EACH_BB (bb)
1586+ {
1587+ edge e;
1588+ edge_iterator ei;
1589+ if (!bitmap_bit_p (&bb_flags, bb->index))
1590+ continue;
1591+ FOR_EACH_EDGE (e, ei, bb->preds)
1592+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1593+ {
1594+ VEC_quick_push (basic_block, vec, e->src);
1595+ bitmap_set_bit (&bb_on_list, e->src->index);
1596+ }
1597+ }
1598+ while (!VEC_empty (basic_block, vec))
1599+ {
1600+ basic_block tmp_bb = VEC_pop (basic_block, vec);
1601+ edge e;
1602+ edge_iterator ei;
1603+ bool all_set = true;
1604+
1605+ bitmap_clear_bit (&bb_on_list, tmp_bb->index);
1606+ FOR_EACH_EDGE (e, ei, tmp_bb->succs)
1607+ {
1608+ if (!bitmap_bit_p (&bb_antic_flags, e->dest->index))
1609+ {
1610+ all_set = false;
1611+ break;
1612+ }
1613+ }
1614+ if (all_set)
1615+ {
1616+ bitmap_set_bit (&bb_antic_flags, tmp_bb->index);
1617+ FOR_EACH_EDGE (e, ei, tmp_bb->preds)
1618+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1619+ {
1620+ VEC_quick_push (basic_block, vec, e->src);
1621+ bitmap_set_bit (&bb_on_list, e->src->index);
1622+ }
1623+ }
1624+ }
1625+ /* Find exactly one edge that leads to a block in ANTIC from
1626+ a block that isn't. */
1627+ if (!bitmap_bit_p (&bb_antic_flags, entry_edge->dest->index))
1628+ FOR_EACH_BB (bb)
1629+ {
1630+ if (!bitmap_bit_p (&bb_antic_flags, bb->index))
1631+ continue;
1632+ FOR_EACH_EDGE (e, ei, bb->preds)
1633+ if (!bitmap_bit_p (&bb_antic_flags, e->src->index))
1634+ {
1635+ if (entry_edge != orig_entry_edge)
1636+ {
1637+ entry_edge = orig_entry_edge;
1638+ goto fail_shrinkwrap;
1639+ }
1640+ entry_edge = e;
1641+ }
1642+ }
1643+
1644+ /* Test whether the prologue is known to clobber any register
1645+ (other than FP or SP) which are live on the edge. */
1646+ CLEAR_HARD_REG_SET (prologue_clobbered);
1647+ for (p_insn = prologue_seq; p_insn; p_insn = NEXT_INSN (p_insn))
1648+ if (NONDEBUG_INSN_P (p_insn))
1649+ note_stores (PATTERN (p_insn), record_hard_reg_sets,
1650+ &prologue_clobbered);
1651+ CLEAR_HARD_REG_BIT (prologue_clobbered, STACK_POINTER_REGNUM);
1652+ if (frame_pointer_needed)
1653+ CLEAR_HARD_REG_BIT (prologue_clobbered, HARD_FRAME_POINTER_REGNUM);
1654+
1655+ CLEAR_HARD_REG_SET (live_on_edge);
1656+ reg_set_to_hard_reg_set (&live_on_edge,
1657+ df_get_live_in (entry_edge->dest));
1658+ if (hard_reg_set_intersect_p (live_on_edge, prologue_clobbered))
1659+ entry_edge = orig_entry_edge;
1660+
1661+ fail_shrinkwrap:
1662+ bitmap_clear (&bb_antic_flags);
1663+ bitmap_clear (&bb_on_list);
1664+ VEC_free (basic_block, heap, vec);
1665 }
1666 #endif
1667
1668+ if (prologue_seq != NULL_RTX)
1669+ {
1670+ insert_insn_on_edge (prologue_seq, entry_edge);
1671+ inserted = true;
1672+ }
1673+
1674 /* If the exit block has no non-fake predecessors, we don't need
1675 an epilogue. */
1676 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1677@@ -5063,100 +5364,130 @@ thread_prologue_and_epilogue_insns (void
1678 goto epilogue_done;
1679
1680 rtl_profile_for_bb (EXIT_BLOCK_PTR);
1681+
1682 #ifdef HAVE_return
1683- if (optimize && HAVE_return)
1684+ /* If we're allowed to generate a simple return instruction, then by
1685+ definition we don't need a full epilogue. If the last basic
1686+ block before the exit block does not contain active instructions,
1687+ examine its predecessors and try to emit (conditional) return
1688+ instructions. */
1689+ if (optimize && !last_bb_active
1690+ && (HAVE_return || entry_edge != orig_entry_edge))
1691 {
1692- /* If we're allowed to generate a simple return instruction,
1693- then by definition we don't need a full epilogue. Examine
1694- the block that falls through to EXIT. If it does not
1695- contain any code, examine its predecessors and try to
1696- emit (conditional) return instructions. */
1697-
1698- basic_block last;
1699+ edge_iterator ei2;
1700+ int i;
1701+ basic_block bb;
1702 rtx label;
1703+ VEC(basic_block,heap) *src_bbs;
1704
1705- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1706- if (e->flags & EDGE_FALLTHRU)
1707- break;
1708- if (e == NULL)
1709+ if (exit_fallthru_edge == NULL)
1710 goto epilogue_done;
1711- last = e->src;
1712+ label = BB_HEAD (last_bb);
1713
1714- /* Verify that there are no active instructions in the last block. */
1715- label = BB_END (last);
1716- while (label && !LABEL_P (label))
1717- {
1718- if (active_insn_p (label))
1719- break;
1720- label = PREV_INSN (label);
1721- }
1722+ src_bbs = VEC_alloc (basic_block, heap, EDGE_COUNT (last_bb->preds));
1723+ FOR_EACH_EDGE (e, ei2, last_bb->preds)
1724+ if (e->src != ENTRY_BLOCK_PTR)
1725+ VEC_quick_push (basic_block, src_bbs, e->src);
1726
1727- if (BB_HEAD (last) == label && LABEL_P (label))
1728+ FOR_EACH_VEC_ELT (basic_block, src_bbs, i, bb)
1729 {
1730- edge_iterator ei2;
1731+ bool simple_p;
1732+ rtx jump;
1733+ e = find_edge (bb, last_bb);
1734
1735- for (ei2 = ei_start (last->preds); (e = ei_safe_edge (ei2)); )
1736- {
1737- basic_block bb = e->src;
1738- rtx jump;
1739+ jump = BB_END (bb);
1740
1741- if (bb == ENTRY_BLOCK_PTR)
1742- {
1743- ei_next (&ei2);
1744- continue;
1745- }
1746+#ifdef HAVE_simple_return
1747+ simple_p = (entry_edge != orig_entry_edge
1748+ ? !bitmap_bit_p (&bb_flags, bb->index) : false);
1749+#else
1750+ simple_p = false;
1751+#endif
1752
1753- jump = BB_END (bb);
1754- if (!JUMP_P (jump) || JUMP_LABEL (jump) != label)
1755- {
1756- ei_next (&ei2);
1757- continue;
1758- }
1759+ if (!simple_p
1760+ && (!HAVE_return || !JUMP_P (jump)
1761+ || JUMP_LABEL (jump) != label))
1762+ continue;
1763
1764- /* If we have an unconditional jump, we can replace that
1765- with a simple return instruction. */
1766- if (simplejump_p (jump))
1767- {
1768- emit_return_into_block (bb);
1769- delete_insn (jump);
1770- }
1771+ /* If we have an unconditional jump, we can replace that
1772+ with a simple return instruction. */
1773+ if (!JUMP_P (jump))
1774+ {
1775+ emit_barrier_after (BB_END (bb));
1776+ emit_return_into_block (simple_p, bb);
1777+ }
1778+ else if (simplejump_p (jump))
1779+ {
1780+ emit_return_into_block (simple_p, bb);
1781+ delete_insn (jump);
1782+ }
1783+ else if (condjump_p (jump) && JUMP_LABEL (jump) != label)
1784+ {
1785+ basic_block new_bb;
1786+ edge new_e;
1787
1788- /* If we have a conditional jump, we can try to replace
1789- that with a conditional return instruction. */
1790- else if (condjump_p (jump))
1791- {
1792- if (! redirect_jump (jump, 0, 0))
1793- {
1794- ei_next (&ei2);
1795- continue;
1796- }
1797+ gcc_assert (simple_p);
1798+ new_bb = split_edge (e);
1799+ emit_barrier_after (BB_END (new_bb));
1800+ emit_return_into_block (simple_p, new_bb);
1801+#ifdef HAVE_simple_return
1802+ simple_return_block = new_bb;
1803+#endif
1804+ new_e = single_succ_edge (new_bb);
1805+ redirect_edge_succ (new_e, EXIT_BLOCK_PTR);
1806
1807- /* If this block has only one successor, it both jumps
1808- and falls through to the fallthru block, so we can't
1809- delete the edge. */
1810- if (single_succ_p (bb))
1811- {
1812- ei_next (&ei2);
1813- continue;
1814- }
1815- }
1816+ continue;
1817+ }
1818+ /* If we have a conditional jump branching to the last
1819+ block, we can try to replace that with a conditional
1820+ return instruction. */
1821+ else if (condjump_p (jump))
1822+ {
1823+ rtx dest;
1824+ if (simple_p)
1825+ dest = simple_return_rtx;
1826 else
1827+ dest = ret_rtx;
1828+ if (! redirect_jump (jump, dest, 0))
1829 {
1830- ei_next (&ei2);
1831+#ifdef HAVE_simple_return
1832+ if (simple_p)
1833+ unconverted_simple_returns = true;
1834+#endif
1835 continue;
1836 }
1837
1838- /* Fix up the CFG for the successful change we just made. */
1839- redirect_edge_succ (e, EXIT_BLOCK_PTR);
1840+ /* If this block has only one successor, it both jumps
1841+ and falls through to the fallthru block, so we can't
1842+ delete the edge. */
1843+ if (single_succ_p (bb))
1844+ continue;
1845+ }
1846+ else
1847+ {
1848+#ifdef HAVE_simple_return
1849+ if (simple_p)
1850+ unconverted_simple_returns = true;
1851+#endif
1852+ continue;
1853 }
1854
1855+ /* Fix up the CFG for the successful change we just made. */
1856+ redirect_edge_succ (e, EXIT_BLOCK_PTR);
1857+ }
1858+ VEC_free (basic_block, heap, src_bbs);
1859+
1860+ if (HAVE_return)
1861+ {
1862 /* Emit a return insn for the exit fallthru block. Whether
1863 this is still reachable will be determined later. */
1864
1865- emit_barrier_after (BB_END (last));
1866- emit_return_into_block (last);
1867- epilogue_end = BB_END (last);
1868- single_succ_edge (last)->flags &= ~EDGE_FALLTHRU;
1869+ emit_barrier_after (BB_END (last_bb));
1870+ emit_return_into_block (false, last_bb);
1871+ epilogue_end = BB_END (last_bb);
1872+ if (JUMP_P (epilogue_end))
1873+ JUMP_LABEL (epilogue_end) = ret_rtx;
1874+ single_succ_edge (last_bb)->flags &= ~EDGE_FALLTHRU;
1875 goto epilogue_done;
1876 }
1877 }
1878@@ -5193,15 +5524,10 @@ thread_prologue_and_epilogue_insns (void
1879 }
1880 #endif
1881
1882- /* Find the edge that falls through to EXIT. Other edges may exist
1883- due to RETURN instructions, but those don't need epilogues.
1884- There really shouldn't be a mixture -- either all should have
1885- been converted or none, however... */
1886+ /* If nothing falls through into the exit block, we don't need an
1887+ epilogue. */
1888
1889- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
1890- if (e->flags & EDGE_FALLTHRU)
1891- break;
1892- if (e == NULL)
1893+ if (exit_fallthru_edge == NULL)
1894 goto epilogue_done;
1895
1896 #ifdef HAVE_epilogue
1897@@ -5217,25 +5543,36 @@ thread_prologue_and_epilogue_insns (void
1898 set_insn_locators (seq, epilogue_locator);
1899
1900 seq = get_insns ();
1901+ returnjump = get_last_insn ();
1902 end_sequence ();
1903
1904- insert_insn_on_edge (seq, e);
1905+ insert_insn_on_edge (seq, exit_fallthru_edge);
1906 inserted = 1;
1907+ if (JUMP_P (returnjump))
1908+ {
1909+ rtx pat = PATTERN (returnjump);
1910+ if (GET_CODE (pat) == PARALLEL)
1911+ pat = XVECEXP (pat, 0, 0);
1912+ if (ANY_RETURN_P (pat))
1913+ JUMP_LABEL (returnjump) = pat;
1914+ else
1915+ JUMP_LABEL (returnjump) = ret_rtx;
1916+ }
1917 }
1918 else
1919 #endif
1920 {
1921 basic_block cur_bb;
1922
1923- if (! next_active_insn (BB_END (e->src)))
1924+ if (! next_active_insn (BB_END (exit_fallthru_edge->src)))
1925 goto epilogue_done;
1926 /* We have a fall-through edge to the exit block, the source is not
1927- at the end of the function, and there will be an assembler epilogue
1928- at the end of the function.
1929- We can't use force_nonfallthru here, because that would try to
1930- use return. Inserting a jump 'by hand' is extremely messy, so
1931+ at the end of the function, and there will be an assembler epilogue
1932+ at the end of the function.
1933+ We can't use force_nonfallthru here, because that would try to
1934+ use return. Inserting a jump 'by hand' is extremely messy, so
1935 we take advantage of cfg_layout_finalize using
1936- fixup_fallthru_exit_predecessor. */
1937+ fixup_fallthru_exit_predecessor. */
1938 cfg_layout_initialize (0);
1939 FOR_EACH_BB (cur_bb)
1940 if (cur_bb->index >= NUM_FIXED_BLOCKS
1941@@ -5244,6 +5581,7 @@ thread_prologue_and_epilogue_insns (void
1942 cfg_layout_finalize ();
1943 }
1944 epilogue_done:
1945+
1946 default_rtl_profile ();
1947
1948 if (inserted)
1949@@ -5260,33 +5598,93 @@ epilogue_done:
1950 }
1951 }
1952
1953+#ifdef HAVE_simple_return
1954+ /* If there were branches to an empty LAST_BB which we tried to
1955+ convert to conditional simple_returns, but couldn't for some
1956+ reason, create a block to hold a simple_return insn and redirect
1957+ those remaining edges. */
1958+ if (unconverted_simple_returns)
1959+ {
1960+ edge_iterator ei2;
1961+ basic_block exit_pred = EXIT_BLOCK_PTR->prev_bb;
1962+
1963+ gcc_assert (entry_edge != orig_entry_edge);
1964+
1965+#ifdef HAVE_epilogue
1966+ if (simple_return_block == NULL && returnjump != NULL_RTX
1967+ && JUMP_LABEL (returnjump) == simple_return_rtx)
1968+ {
1969+ edge e = split_block (exit_fallthru_edge->src,
1970+ PREV_INSN (returnjump));
1971+ simple_return_block = e->dest;
1972+ }
1973+#endif
1974+ if (simple_return_block == NULL)
1975+ {
1976+ basic_block bb;
1977+ rtx start;
1978+
1979+ bb = create_basic_block (NULL, NULL, exit_pred);
1980+ start = emit_jump_insn_after (gen_simple_return (),
1981+ BB_END (bb));
1982+ JUMP_LABEL (start) = simple_return_rtx;
1983+ emit_barrier_after (start);
1984+
1985+ simple_return_block = bb;
1986+ make_edge (bb, EXIT_BLOCK_PTR, 0);
1987+ }
1988+
1989+ restart_scan:
1990+ for (ei2 = ei_start (last_bb->preds); (e = ei_safe_edge (ei2)); )
1991+ {
1992+ basic_block bb = e->src;
1993+
1994+ if (bb != ENTRY_BLOCK_PTR
1995+ && !bitmap_bit_p (&bb_flags, bb->index))
1996+ {
1997+ redirect_edge_and_branch_force (e, simple_return_block);
1998+ goto restart_scan;
1999+ }
2000+ ei_next (&ei2);
2001+
2002+ }
2003+ }
2004+#endif
2005+
2006 #ifdef HAVE_sibcall_epilogue
2007 /* Emit sibling epilogues before any sibling call sites. */
2008 for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
2009 {
2010 basic_block bb = e->src;
2011 rtx insn = BB_END (bb);
2012+ rtx ep_seq;
2013
2014 if (!CALL_P (insn)
2015- || ! SIBLING_CALL_P (insn))
2016+ || ! SIBLING_CALL_P (insn)
2017+ || (entry_edge != orig_entry_edge
2018+ && !bitmap_bit_p (&bb_flags, bb->index)))
2019 {
2020 ei_next (&ei);
2021 continue;
2022 }
2023
2024- start_sequence ();
2025- emit_note (NOTE_INSN_EPILOGUE_BEG);
2026- emit_insn (gen_sibcall_epilogue ());
2027- seq = get_insns ();
2028- end_sequence ();
2029+ ep_seq = gen_sibcall_epilogue ();
2030+ if (ep_seq)
2031+ {
2032+ start_sequence ();
2033+ emit_note (NOTE_INSN_EPILOGUE_BEG);
2034+ emit_insn (ep_seq);
2035+ seq = get_insns ();
2036+ end_sequence ();
2037
2038- /* Retain a map of the epilogue insns. Used in life analysis to
2039- avoid getting rid of sibcall epilogue insns. Do this before we
2040- actually emit the sequence. */
2041- record_insns (seq, NULL, &epilogue_insn_hash);
2042- set_insn_locators (seq, epilogue_locator);
2043+ /* Retain a map of the epilogue insns. Used in life analysis to
2044+ avoid getting rid of sibcall epilogue insns. Do this before we
2045+ actually emit the sequence. */
2046+ record_insns (seq, NULL, &epilogue_insn_hash);
2047+ set_insn_locators (seq, epilogue_locator);
2048
2049- emit_insn_before (seq, insn);
2050+ emit_insn_before (seq, insn);
2051+ }
2052 ei_next (&ei);
2053 }
2054 #endif
2055@@ -5311,6 +5709,8 @@ epilogue_done:
2056 }
2057 #endif
2058
2059+ bitmap_clear (&bb_flags);
2060+
2061 /* Threading the prologue and epilogue changes the artificial refs
2062 in the entry and exit blocks. */
2063 epilogue_completed = 1;
2064Index: gcc-4_5-branch/gcc/genemit.c
2065===================================================================
2066--- gcc-4_5-branch.orig/gcc/genemit.c
2067+++ gcc-4_5-branch/gcc/genemit.c
2068@@ -222,6 +222,12 @@ gen_exp (rtx x, enum rtx_code subroutine
2069 case PC:
2070 printf ("pc_rtx");
2071 return;
2072+ case RETURN:
2073+ printf ("ret_rtx");
2074+ return;
2075+ case SIMPLE_RETURN:
2076+ printf ("simple_return_rtx");
2077+ return;
2078 case CLOBBER:
2079 if (REG_P (XEXP (x, 0)))
2080 {
2081@@ -544,8 +550,8 @@ gen_expand (rtx expand)
2082 || (GET_CODE (next) == PARALLEL
2083 && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
2084 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
2085- || GET_CODE (XVECEXP (next, 0, 0)) == RETURN))
2086- || GET_CODE (next) == RETURN)
2087+ || ANY_RETURN_P (XVECEXP (next, 0, 0))))
2088+ || ANY_RETURN_P (next))
2089 printf (" emit_jump_insn (");
2090 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
2091 || GET_CODE (next) == CALL
2092@@ -660,7 +666,7 @@ gen_split (rtx split)
2093 || (GET_CODE (next) == PARALLEL
2094 && GET_CODE (XVECEXP (next, 0, 0)) == SET
2095 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
2096- || GET_CODE (next) == RETURN)
2097+ || ANY_RETURN_P (next))
2098 printf (" emit_jump_insn (");
2099 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
2100 || GET_CODE (next) == CALL
2101Index: gcc-4_5-branch/gcc/gengenrtl.c
2102===================================================================
2103--- gcc-4_5-branch.orig/gcc/gengenrtl.c
2104+++ gcc-4_5-branch/gcc/gengenrtl.c
2105@@ -146,6 +146,10 @@ special_rtx (int idx)
2106 || strcmp (defs[idx].enumname, "REG") == 0
2107 || strcmp (defs[idx].enumname, "SUBREG") == 0
2108 || strcmp (defs[idx].enumname, "MEM") == 0
2109+ || strcmp (defs[idx].enumname, "PC") == 0
2110+ || strcmp (defs[idx].enumname, "CC0") == 0
2111+ || strcmp (defs[idx].enumname, "RETURN") == 0
2112+ || strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0
2113 || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
2114 }
2115
2116Index: gcc-4_5-branch/gcc/haifa-sched.c
2117===================================================================
2118--- gcc-4_5-branch.orig/gcc/haifa-sched.c
2119+++ gcc-4_5-branch/gcc/haifa-sched.c
2120@@ -4231,7 +4231,7 @@ xrecalloc (void *p, size_t new_nmemb, si
2121 /* Helper function.
2122 Find fallthru edge from PRED. */
2123 edge
2124-find_fallthru_edge (basic_block pred)
2125+find_fallthru_edge_from (basic_block pred)
2126 {
2127 edge e;
2128 edge_iterator ei;
2129@@ -4298,7 +4298,7 @@ init_before_recovery (basic_block *befor
2130 edge e;
2131
2132 last = EXIT_BLOCK_PTR->prev_bb;
2133- e = find_fallthru_edge (last);
2134+ e = find_fallthru_edge_from (last);
2135
2136 if (e)
2137 {
2138@@ -5234,6 +5234,11 @@ check_cfg (rtx head, rtx tail)
2139 gcc_assert (/* Usual case. */
2140 (EDGE_COUNT (bb->succs) > 1
2141 && !BARRIER_P (NEXT_INSN (head)))
2142+ /* Special cases, see cfglayout.c:
2143+ fixup_reorder_chain. */
2144+ || (EDGE_COUNT (bb->succs) == 1
2145+ && (!onlyjump_p (head)
2146+ || returnjump_p (head)))
2147 /* Or jump to the next instruction. */
2148 || (EDGE_COUNT (bb->succs) == 1
2149 && (BB_HEAD (EDGE_I (bb->succs, 0)->dest)
2150Index: gcc-4_5-branch/gcc/ifcvt.c
2151===================================================================
2152--- gcc-4_5-branch.orig/gcc/ifcvt.c
2153+++ gcc-4_5-branch/gcc/ifcvt.c
2154@@ -105,7 +105,7 @@ static int find_if_case_1 (basic_block,
2155 static int find_if_case_2 (basic_block, edge, edge);
2156 static int find_memory (rtx *, void *);
2157 static int dead_or_predicable (basic_block, basic_block, basic_block,
2158- basic_block, int);
2159+ edge, int);
2160 static void noce_emit_move_insn (rtx, rtx);
2161 static rtx block_has_only_trap (basic_block);
2162
2163@@ -3791,6 +3791,7 @@ find_if_case_1 (basic_block test_bb, edg
2164 basic_block then_bb = then_edge->dest;
2165 basic_block else_bb = else_edge->dest;
2166 basic_block new_bb;
2167+ rtx else_target = NULL_RTX;
2168 int then_bb_index;
2169
2170 /* If we are partitioning hot/cold basic blocks, we don't want to
2171@@ -3840,9 +3841,16 @@ find_if_case_1 (basic_block test_bb, edg
2172 predictable_edge_p (then_edge)))))
2173 return FALSE;
2174
2175+ if (else_bb == EXIT_BLOCK_PTR)
2176+ {
2177+ rtx jump = BB_END (else_edge->src);
2178+ gcc_assert (JUMP_P (jump));
2179+ else_target = JUMP_LABEL (jump);
2180+ }
2181+
2182 /* Registers set are dead, or are predicable. */
2183 if (! dead_or_predicable (test_bb, then_bb, else_bb,
2184- single_succ (then_bb), 1))
2185+ single_succ_edge (then_bb), 1))
2186 return FALSE;
2187
2188 /* Conversion went ok, including moving the insns and fixing up the
2189@@ -3859,6 +3867,9 @@ find_if_case_1 (basic_block test_bb, edg
2190 redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
2191 new_bb = 0;
2192 }
2193+ else if (else_bb == EXIT_BLOCK_PTR)
2194+ new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
2195+ else_bb, else_target);
2196 else
2197 new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
2198 else_bb);
2199@@ -3957,7 +3968,7 @@ find_if_case_2 (basic_block test_bb, edg
2200 return FALSE;
2201
2202 /* Registers set are dead, or are predicable. */
2203- if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0))
2204+ if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, 0))
2205 return FALSE;
2206
2207 /* Conversion went ok, including moving the insns and fixing up the
2208@@ -3995,12 +4006,34 @@ find_memory (rtx *px, void *data ATTRIBU
2209
2210 static int
2211 dead_or_predicable (basic_block test_bb, basic_block merge_bb,
2212- basic_block other_bb, basic_block new_dest, int reversep)
2213+ basic_block other_bb, edge dest_edge, int reversep)
2214 {
2215- rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX;
2216+ basic_block new_dest = dest_edge->dest;
2217+ rtx head, end, jump, earliest = NULL_RTX, old_dest;
2218 bitmap merge_set = NULL;
2219 /* Number of pending changes. */
2220 int n_validated_changes = 0;
2221+ rtx new_dest_label;
2222+
2223+ jump = BB_END (dest_edge->src);
2224+ if (JUMP_P (jump))
2225+ {
2226+ new_dest_label = JUMP_LABEL (jump);
2227+ if (new_dest_label == NULL_RTX)
2228+ {
2229+ new_dest_label = PATTERN (jump);
2230+ gcc_assert (ANY_RETURN_P (new_dest_label));
2231+ }
2232+ }
2233+ else if (other_bb != new_dest)
2234+ {
2235+ if (new_dest == EXIT_BLOCK_PTR)
2236+ new_dest_label = ret_rtx;
2237+ else
2238+ new_dest_label = block_label (new_dest);
2239+ }
2240+ else
2241+ new_dest_label = NULL_RTX;
2242
2243 jump = BB_END (test_bb);
2244
2245@@ -4220,10 +4253,9 @@ dead_or_predicable (basic_block test_bb,
2246 old_dest = JUMP_LABEL (jump);
2247 if (other_bb != new_dest)
2248 {
2249- new_label = block_label (new_dest);
2250 if (reversep
2251- ? ! invert_jump_1 (jump, new_label)
2252- : ! redirect_jump_1 (jump, new_label))
2253+ ? ! invert_jump_1 (jump, new_dest_label)
2254+ : ! redirect_jump_1 (jump, new_dest_label))
2255 goto cancel;
2256 }
2257
2258@@ -4234,7 +4266,7 @@ dead_or_predicable (basic_block test_bb,
2259
2260 if (other_bb != new_dest)
2261 {
2262- redirect_jump_2 (jump, old_dest, new_label, 0, reversep);
2263+ redirect_jump_2 (jump, old_dest, new_dest_label, 0, reversep);
2264
2265 redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
2266 if (reversep)
2267Index: gcc-4_5-branch/gcc/jump.c
2268===================================================================
2269--- gcc-4_5-branch.orig/gcc/jump.c
2270+++ gcc-4_5-branch/gcc/jump.c
2271@@ -29,7 +29,8 @@ along with GCC; see the file COPYING3.
2272 JUMP_LABEL internal field. With this we can detect labels that
2273 become unused because of the deletion of all the jumps that
2274 formerly used them. The JUMP_LABEL info is sometimes looked
2275- at by later passes.
2276+ at by later passes. For return insns, it contains either a
2277+ RETURN or a SIMPLE_RETURN rtx.
2278
2279 The subroutines redirect_jump and invert_jump are used
2280 from other passes as well. */
2281@@ -742,10 +743,10 @@ condjump_p (const_rtx insn)
2282 return (GET_CODE (x) == IF_THEN_ELSE
2283 && ((GET_CODE (XEXP (x, 2)) == PC
2284 && (GET_CODE (XEXP (x, 1)) == LABEL_REF
2285- || GET_CODE (XEXP (x, 1)) == RETURN))
2286+ || ANY_RETURN_P (XEXP (x, 1))))
2287 || (GET_CODE (XEXP (x, 1)) == PC
2288 && (GET_CODE (XEXP (x, 2)) == LABEL_REF
2289- || GET_CODE (XEXP (x, 2)) == RETURN))));
2290+ || ANY_RETURN_P (XEXP (x, 2))))));
2291 }
2292
2293 /* Return nonzero if INSN is a (possibly) conditional jump inside a
2294@@ -774,11 +775,11 @@ condjump_in_parallel_p (const_rtx insn)
2295 return 0;
2296 if (XEXP (SET_SRC (x), 2) == pc_rtx
2297 && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
2298- || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN))
2299+ || ANY_RETURN_P (XEXP (SET_SRC (x), 1)) == RETURN))
2300 return 1;
2301 if (XEXP (SET_SRC (x), 1) == pc_rtx
2302 && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
2303- || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN))
2304+ || ANY_RETURN_P (XEXP (SET_SRC (x), 2))))
2305 return 1;
2306 return 0;
2307 }
2308@@ -840,8 +841,9 @@ any_condjump_p (const_rtx insn)
2309 a = GET_CODE (XEXP (SET_SRC (x), 1));
2310 b = GET_CODE (XEXP (SET_SRC (x), 2));
2311
2312- return ((b == PC && (a == LABEL_REF || a == RETURN))
2313- || (a == PC && (b == LABEL_REF || b == RETURN)));
2314+ return ((b == PC && (a == LABEL_REF || a == RETURN || a == SIMPLE_RETURN))
2315+ || (a == PC
2316+ && (b == LABEL_REF || b == RETURN || b == SIMPLE_RETURN)));
2317 }
2318
2319 /* Return the label of a conditional jump. */
2320@@ -878,6 +880,7 @@ returnjump_p_1 (rtx *loc, void *data ATT
2321 switch (GET_CODE (x))
2322 {
2323 case RETURN:
2324+ case SIMPLE_RETURN:
2325 case EH_RETURN:
2326 return true;
2327
2328@@ -1200,7 +1203,7 @@ delete_related_insns (rtx insn)
2329 /* If deleting a jump, decrement the count of the label,
2330 and delete the label if it is now unused. */
2331
2332- if (JUMP_P (insn) && JUMP_LABEL (insn))
2333+ if (JUMP_P (insn) && JUMP_LABEL (insn) && !ANY_RETURN_P (JUMP_LABEL (insn)))
2334 {
2335 rtx lab = JUMP_LABEL (insn), lab_next;
2336
2337@@ -1331,6 +1334,18 @@ delete_for_peephole (rtx from, rtx to)
2338 is also an unconditional jump in that case. */
2339 }
2340
2341+/* A helper function for redirect_exp_1; examines its input X and returns
2342+ either a LABEL_REF around a label, or a RETURN if X was NULL. */
2343+static rtx
2344+redirect_target (rtx x)
2345+{
2346+ if (x == NULL_RTX)
2347+ return ret_rtx;
2348+ if (!ANY_RETURN_P (x))
2349+ return gen_rtx_LABEL_REF (Pmode, x);
2350+ return x;
2351+}
2352+
2353 /* Throughout LOC, redirect OLABEL to NLABEL. Treat null OLABEL or
2354 NLABEL as a return. Accrue modifications into the change group. */
2355
2356@@ -1342,37 +1357,19 @@ redirect_exp_1 (rtx *loc, rtx olabel, rt
2357 int i;
2358 const char *fmt;
2359
2360- if (code == LABEL_REF)
2361- {
2362- if (XEXP (x, 0) == olabel)
2363- {
2364- rtx n;
2365- if (nlabel)
2366- n = gen_rtx_LABEL_REF (Pmode, nlabel);
2367- else
2368- n = gen_rtx_RETURN (VOIDmode);
2369-
2370- validate_change (insn, loc, n, 1);
2371- return;
2372- }
2373- }
2374- else if (code == RETURN && olabel == 0)
2375+ if ((code == LABEL_REF && XEXP (x, 0) == olabel)
2376+ || x == olabel)
2377 {
2378- if (nlabel)
2379- x = gen_rtx_LABEL_REF (Pmode, nlabel);
2380- else
2381- x = gen_rtx_RETURN (VOIDmode);
2382- if (loc == &PATTERN (insn))
2383- x = gen_rtx_SET (VOIDmode, pc_rtx, x);
2384- validate_change (insn, loc, x, 1);
2385+ validate_change (insn, loc, redirect_target (nlabel), 1);
2386 return;
2387 }
2388
2389- if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx
2390+ if (code == SET && SET_DEST (x) == pc_rtx
2391+ && ANY_RETURN_P (nlabel)
2392 && GET_CODE (SET_SRC (x)) == LABEL_REF
2393 && XEXP (SET_SRC (x), 0) == olabel)
2394 {
2395- validate_change (insn, loc, gen_rtx_RETURN (VOIDmode), 1);
2396+ validate_change (insn, loc, nlabel, 1);
2397 return;
2398 }
2399
2400@@ -1409,6 +1406,7 @@ redirect_jump_1 (rtx jump, rtx nlabel)
2401 int ochanges = num_validated_changes ();
2402 rtx *loc, asmop;
2403
2404+ gcc_assert (nlabel);
2405 asmop = extract_asm_operands (PATTERN (jump));
2406 if (asmop)
2407 {
2408@@ -1430,17 +1428,20 @@ redirect_jump_1 (rtx jump, rtx nlabel)
2409 jump target label is unused as a result, it and the code following
2410 it may be deleted.
2411
2412- If NLABEL is zero, we are to turn the jump into a (possibly conditional)
2413- RETURN insn.
2414+ Normally, NLABEL will be a label, but it may also be a RETURN or
2415+ SIMPLE_RETURN rtx; in that case we are to turn the jump into a
2416+ (possibly conditional) return insn.
2417
2418 The return value will be 1 if the change was made, 0 if it wasn't
2419- (this can only occur for NLABEL == 0). */
2420+ (this can only occur when trying to produce return insns). */
2421
2422 int
2423 redirect_jump (rtx jump, rtx nlabel, int delete_unused)
2424 {
2425 rtx olabel = JUMP_LABEL (jump);
2426
2427+ gcc_assert (nlabel != NULL_RTX);
2428+
2429 if (nlabel == olabel)
2430 return 1;
2431
2432@@ -1452,7 +1453,7 @@ redirect_jump (rtx jump, rtx nlabel, int
2433 }
2434
2435 /* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with
2436- NLABEL in JUMP.
2437+ NEW_DEST in JUMP.
2438 If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref
2439 count has dropped to zero. */
2440 void
2441@@ -1468,13 +1469,14 @@ redirect_jump_2 (rtx jump, rtx olabel, r
2442 about this. */
2443 gcc_assert (delete_unused >= 0);
2444 JUMP_LABEL (jump) = nlabel;
2445- if (nlabel)
2446+ if (nlabel && !ANY_RETURN_P (nlabel))
2447 ++LABEL_NUSES (nlabel);
2448
2449 /* Update labels in any REG_EQUAL note. */
2450 if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
2451 {
2452- if (!nlabel || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
2453+ if (ANY_RETURN_P (nlabel)
2454+ || (invert && !invert_exp_1 (XEXP (note, 0), jump)))
2455 remove_note (jump, note);
2456 else
2457 {
2458@@ -1483,7 +1485,8 @@ redirect_jump_2 (rtx jump, rtx olabel, r
2459 }
2460 }
2461
2462- if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
2463+ if (olabel && !ANY_RETURN_P (olabel)
2464+ && --LABEL_NUSES (olabel) == 0 && delete_unused > 0
2465 /* Undefined labels will remain outside the insn stream. */
2466 && INSN_UID (olabel))
2467 delete_related_insns (olabel);
2468Index: gcc-4_5-branch/gcc/opts.c
2469===================================================================
2470--- gcc-4_5-branch.orig/gcc/opts.c
2471+++ gcc-4_5-branch/gcc/opts.c
2472@@ -909,6 +909,7 @@ decode_options (unsigned int argc, const
2473 flag_ipa_cp = opt2;
2474 flag_ipa_sra = opt2;
2475 flag_ee = opt2;
2476+ flag_shrink_wrap = opt2;
2477
2478 /* Track fields in field-sensitive alias analysis. */
2479 set_param_value ("max-fields-for-field-sensitive",
2480Index: gcc-4_5-branch/gcc/print-rtl.c
2481===================================================================
2482--- gcc-4_5-branch.orig/gcc/print-rtl.c
2483+++ gcc-4_5-branch/gcc/print-rtl.c
2484@@ -308,9 +308,16 @@ print_rtx (const_rtx in_rtx)
2485 }
2486 }
2487 else if (i == 8 && JUMP_P (in_rtx) && JUMP_LABEL (in_rtx) != NULL)
2488- /* Output the JUMP_LABEL reference. */
2489- fprintf (outfile, "\n%s%*s -> %d", print_rtx_head, indent * 2, "",
2490- INSN_UID (JUMP_LABEL (in_rtx)));
2491+ {
2492+ /* Output the JUMP_LABEL reference. */
2493+ fprintf (outfile, "\n%s%*s -> ", print_rtx_head, indent * 2, "");
2494+ if (GET_CODE (JUMP_LABEL (in_rtx)) == RETURN)
2495+ fprintf (outfile, "return");
2496+ else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN)
2497+ fprintf (outfile, "simple_return");
2498+ else
2499+ fprintf (outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
2500+ }
2501 else if (i == 0 && GET_CODE (in_rtx) == VALUE)
2502 {
2503 #ifndef GENERATOR_FILE
2504Index: gcc-4_5-branch/gcc/reorg.c
2505===================================================================
2506--- gcc-4_5-branch.orig/gcc/reorg.c
2507+++ gcc-4_5-branch/gcc/reorg.c
2508@@ -161,8 +161,11 @@ static rtx *unfilled_firstobj;
2509 #define unfilled_slots_next \
2510 ((rtx *) obstack_next_free (&unfilled_slots_obstack))
2511
2512-/* Points to the label before the end of the function. */
2513-static rtx end_of_function_label;
2514+/* Points to the label before the end of the function, or before a
2515+ return insn. */
2516+static rtx function_return_label;
2517+/* Likewise for a simple_return. */
2518+static rtx function_simple_return_label;
2519
2520 /* Mapping between INSN_UID's and position in the code since INSN_UID's do
2521 not always monotonically increase. */
2522@@ -175,7 +178,7 @@ static int stop_search_p (rtx, int);
2523 static int resource_conflicts_p (struct resources *, struct resources *);
2524 static int insn_references_resource_p (rtx, struct resources *, bool);
2525 static int insn_sets_resource_p (rtx, struct resources *, bool);
2526-static rtx find_end_label (void);
2527+static rtx find_end_label (rtx);
2528 static rtx emit_delay_sequence (rtx, rtx, int);
2529 static rtx add_to_delay_list (rtx, rtx);
2530 static rtx delete_from_delay_slot (rtx);
2531@@ -220,6 +223,15 @@ static void relax_delay_slots (rtx);
2532 static void make_return_insns (rtx);
2533 #endif
2534
2535+/* Return true iff INSN is a simplejump, or any kind of return insn. */
2536+
2537+static bool
2538+simplejump_or_return_p (rtx insn)
2539+{
2540+ return (JUMP_P (insn)
2541+ && (simplejump_p (insn) || ANY_RETURN_P (PATTERN (insn))));
2542+}
2543+
2544 /* Return TRUE if this insn should stop the search for insn to fill delay
2545 slots. LABELS_P indicates that labels should terminate the search.
2546 In all cases, jumps terminate the search. */
2547@@ -335,23 +347,29 @@ insn_sets_resource_p (rtx insn, struct r
2548
2549 ??? There may be a problem with the current implementation. Suppose
2550 we start with a bare RETURN insn and call find_end_label. It may set
2551- end_of_function_label just before the RETURN. Suppose the machinery
2552+ function_return_label just before the RETURN. Suppose the machinery
2553 is able to fill the delay slot of the RETURN insn afterwards. Then
2554- end_of_function_label is no longer valid according to the property
2555+ function_return_label is no longer valid according to the property
2556 described above and find_end_label will still return it unmodified.
2557 Note that this is probably mitigated by the following observation:
2558- once end_of_function_label is made, it is very likely the target of
2559+ once function_return_label is made, it is very likely the target of
2560 a jump, so filling the delay slot of the RETURN will be much more
2561 difficult. */
2562
2563 static rtx
2564-find_end_label (void)
2565+find_end_label (rtx kind)
2566 {
2567 rtx insn;
2568+ rtx *plabel;
2569+
2570+ if (kind == ret_rtx)
2571+ plabel = &function_return_label;
2572+ else
2573+ plabel = &function_simple_return_label;
2574
2575 /* If we found one previously, return it. */
2576- if (end_of_function_label)
2577- return end_of_function_label;
2578+ if (*plabel)
2579+ return *plabel;
2580
2581 /* Otherwise, see if there is a label at the end of the function. If there
2582 is, it must be that RETURN insns aren't needed, so that is our return
2583@@ -366,44 +384,44 @@ find_end_label (void)
2584
2585 /* When a target threads its epilogue we might already have a
2586 suitable return insn. If so put a label before it for the
2587- end_of_function_label. */
2588+ function_return_label. */
2589 if (BARRIER_P (insn)
2590 && JUMP_P (PREV_INSN (insn))
2591- && GET_CODE (PATTERN (PREV_INSN (insn))) == RETURN)
2592+ && PATTERN (PREV_INSN (insn)) == kind)
2593 {
2594 rtx temp = PREV_INSN (PREV_INSN (insn));
2595- end_of_function_label = gen_label_rtx ();
2596- LABEL_NUSES (end_of_function_label) = 0;
2597+ rtx label = gen_label_rtx ();
2598+ LABEL_NUSES (label) = 0;
2599
2600 /* Put the label before an USE insns that may precede the RETURN insn. */
2601 while (GET_CODE (temp) == USE)
2602 temp = PREV_INSN (temp);
2603
2604- emit_label_after (end_of_function_label, temp);
2605+ emit_label_after (label, temp);
2606+ *plabel = label;
2607 }
2608
2609 else if (LABEL_P (insn))
2610- end_of_function_label = insn;
2611+ *plabel = insn;
2612 else
2613 {
2614- end_of_function_label = gen_label_rtx ();
2615- LABEL_NUSES (end_of_function_label) = 0;
2616+ rtx label = gen_label_rtx ();
2617+ LABEL_NUSES (label) = 0;
2618 /* If the basic block reorder pass moves the return insn to
2619 some other place try to locate it again and put our
2620- end_of_function_label there. */
2621- while (insn && ! (JUMP_P (insn)
2622- && (GET_CODE (PATTERN (insn)) == RETURN)))
2623+ function_return_label there. */
2624+ while (insn && ! (JUMP_P (insn) && (PATTERN (insn) == kind)))
2625 insn = PREV_INSN (insn);
2626 if (insn)
2627 {
2628 insn = PREV_INSN (insn);
2629
2630- /* Put the label before an USE insns that may proceed the
2631+ /* Put the label before an USE insns that may precede the
2632 RETURN insn. */
2633 while (GET_CODE (insn) == USE)
2634 insn = PREV_INSN (insn);
2635
2636- emit_label_after (end_of_function_label, insn);
2637+ emit_label_after (label, insn);
2638 }
2639 else
2640 {
2641@@ -413,19 +431,16 @@ find_end_label (void)
2642 && ! HAVE_return
2643 #endif
2644 )
2645- {
2646- /* The RETURN insn has its delay slot filled so we cannot
2647- emit the label just before it. Since we already have
2648- an epilogue and cannot emit a new RETURN, we cannot
2649- emit the label at all. */
2650- end_of_function_label = NULL_RTX;
2651- return end_of_function_label;
2652- }
2653+ /* The RETURN insn has its delay slot filled so we cannot
2654+ emit the label just before it. Since we already have
2655+ an epilogue and cannot emit a new RETURN, we cannot
2656+ emit the label at all. */
2657+ return NULL_RTX;
2658 #endif /* HAVE_epilogue */
2659
2660 /* Otherwise, make a new label and emit a RETURN and BARRIER,
2661 if needed. */
2662- emit_label (end_of_function_label);
2663+ emit_label (label);
2664 #ifdef HAVE_return
2665 /* We don't bother trying to create a return insn if the
2666 epilogue has filled delay-slots; we would have to try and
2667@@ -437,19 +452,21 @@ find_end_label (void)
2668 /* The return we make may have delay slots too. */
2669 rtx insn = gen_return ();
2670 insn = emit_jump_insn (insn);
2671+ JUMP_LABEL (insn) = ret_rtx;
2672 emit_barrier ();
2673 if (num_delay_slots (insn) > 0)
2674 obstack_ptr_grow (&unfilled_slots_obstack, insn);
2675 }
2676 #endif
2677 }
2678+ *plabel = label;
2679 }
2680
2681 /* Show one additional use for this label so it won't go away until
2682 we are done. */
2683- ++LABEL_NUSES (end_of_function_label);
2684+ ++LABEL_NUSES (*plabel);
2685
2686- return end_of_function_label;
2687+ return *plabel;
2688 }
2689
2690 /* Put INSN and LIST together in a SEQUENCE rtx of LENGTH, and replace
2691@@ -797,10 +814,8 @@ optimize_skip (rtx insn)
2692 if ((next_trial == next_active_insn (JUMP_LABEL (insn))
2693 && ! (next_trial == 0 && crtl->epilogue_delay_list != 0))
2694 || (next_trial != 0
2695- && JUMP_P (next_trial)
2696- && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)
2697- && (simplejump_p (next_trial)
2698- || GET_CODE (PATTERN (next_trial)) == RETURN)))
2699+ && simplejump_or_return_p (next_trial)
2700+ && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)))
2701 {
2702 if (eligible_for_annul_false (insn, 0, trial, flags))
2703 {
2704@@ -819,13 +834,11 @@ optimize_skip (rtx insn)
2705 branch, thread our jump to the target of that branch. Don't
2706 change this into a RETURN here, because it may not accept what
2707 we have in the delay slot. We'll fix this up later. */
2708- if (next_trial && JUMP_P (next_trial)
2709- && (simplejump_p (next_trial)
2710- || GET_CODE (PATTERN (next_trial)) == RETURN))
2711+ if (next_trial && simplejump_or_return_p (next_trial))
2712 {
2713 rtx target_label = JUMP_LABEL (next_trial);
2714- if (target_label == 0)
2715- target_label = find_end_label ();
2716+ if (ANY_RETURN_P (target_label))
2717+ target_label = find_end_label (target_label);
2718
2719 if (target_label)
2720 {
2721@@ -866,7 +879,7 @@ get_jump_flags (rtx insn, rtx label)
2722 if (JUMP_P (insn)
2723 && (condjump_p (insn) || condjump_in_parallel_p (insn))
2724 && INSN_UID (insn) <= max_uid
2725- && label != 0
2726+ && label != 0 && !ANY_RETURN_P (label)
2727 && INSN_UID (label) <= max_uid)
2728 flags
2729 = (uid_to_ruid[INSN_UID (label)] > uid_to_ruid[INSN_UID (insn)])
2730@@ -1038,7 +1051,7 @@ get_branch_condition (rtx insn, rtx targ
2731 pat = XVECEXP (pat, 0, 0);
2732
2733 if (GET_CODE (pat) == RETURN)
2734- return target == 0 ? const_true_rtx : 0;
2735+ return ANY_RETURN_P (target) ? const_true_rtx : 0;
2736
2737 else if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
2738 return 0;
2739@@ -1318,7 +1331,11 @@ steal_delay_list_from_target (rtx insn,
2740 }
2741
2742 /* Show the place to which we will be branching. */
2743- *pnew_thread = next_active_insn (JUMP_LABEL (XVECEXP (seq, 0, 0)));
2744+ temp = JUMP_LABEL (XVECEXP (seq, 0, 0));
2745+ if (ANY_RETURN_P (temp))
2746+ *pnew_thread = temp;
2747+ else
2748+ *pnew_thread = next_active_insn (temp);
2749
2750 /* Add any new insns to the delay list and update the count of the
2751 number of slots filled. */
2752@@ -1358,8 +1375,7 @@ steal_delay_list_from_fallthrough (rtx i
2753 /* We can't do anything if SEQ's delay insn isn't an
2754 unconditional branch. */
2755
2756- if (! simplejump_p (XVECEXP (seq, 0, 0))
2757- && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) != RETURN)
2758+ if (! simplejump_or_return_p (XVECEXP (seq, 0, 0)))
2759 return delay_list;
2760
2761 for (i = 1; i < XVECLEN (seq, 0); i++)
2762@@ -1827,7 +1843,7 @@ own_thread_p (rtx thread, rtx label, int
2763 rtx insn;
2764
2765 /* We don't own the function end. */
2766- if (thread == 0)
2767+ if (ANY_RETURN_P (thread))
2768 return 0;
2769
2770 /* Get the first active insn, or THREAD, if it is an active insn. */
2771@@ -2245,7 +2261,8 @@ fill_simple_delay_slots (int non_jumps_p
2772 && (!JUMP_P (insn)
2773 || ((condjump_p (insn) || condjump_in_parallel_p (insn))
2774 && ! simplejump_p (insn)
2775- && JUMP_LABEL (insn) != 0)))
2776+ && JUMP_LABEL (insn) != 0
2777+ && !ANY_RETURN_P (JUMP_LABEL (insn)))))
2778 {
2779 /* Invariant: If insn is a JUMP_INSN, the insn's jump
2780 label. Otherwise, zero. */
2781@@ -2270,7 +2287,7 @@ fill_simple_delay_slots (int non_jumps_p
2782 target = JUMP_LABEL (insn);
2783 }
2784
2785- if (target == 0)
2786+ if (target == 0 || ANY_RETURN_P (target))
2787 for (trial = next_nonnote_insn (insn); trial; trial = next_trial)
2788 {
2789 next_trial = next_nonnote_insn (trial);
2790@@ -2349,6 +2366,7 @@ fill_simple_delay_slots (int non_jumps_p
2791 && JUMP_P (trial)
2792 && simplejump_p (trial)
2793 && (target == 0 || JUMP_LABEL (trial) == target)
2794+ && !ANY_RETURN_P (JUMP_LABEL (trial))
2795 && (next_trial = next_active_insn (JUMP_LABEL (trial))) != 0
2796 && ! (NONJUMP_INSN_P (next_trial)
2797 && GET_CODE (PATTERN (next_trial)) == SEQUENCE)
2798@@ -2371,7 +2389,7 @@ fill_simple_delay_slots (int non_jumps_p
2799 if (new_label != 0)
2800 new_label = get_label_before (new_label);
2801 else
2802- new_label = find_end_label ();
2803+ new_label = find_end_label (simple_return_rtx);
2804
2805 if (new_label)
2806 {
2807@@ -2503,7 +2521,8 @@ fill_simple_delay_slots (int non_jumps_p
2808
2809 /* Follow any unconditional jump at LABEL;
2810 return the ultimate label reached by any such chain of jumps.
2811- Return null if the chain ultimately leads to a return instruction.
2812+ Return a suitable return rtx if the chain ultimately leads to a
2813+ return instruction.
2814 If LABEL is not followed by a jump, return LABEL.
2815 If the chain loops or we can't find end, return LABEL,
2816 since that tells caller to avoid changing the insn. */
2817@@ -2518,6 +2537,7 @@ follow_jumps (rtx label)
2818
2819 for (depth = 0;
2820 (depth < 10
2821+ && !ANY_RETURN_P (value)
2822 && (insn = next_active_insn (value)) != 0
2823 && JUMP_P (insn)
2824 && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn)
2825@@ -2527,18 +2547,22 @@ follow_jumps (rtx label)
2826 && BARRIER_P (next));
2827 depth++)
2828 {
2829- rtx tem;
2830+ rtx this_label = JUMP_LABEL (insn);
2831
2832 /* If we have found a cycle, make the insn jump to itself. */
2833- if (JUMP_LABEL (insn) == label)
2834+ if (this_label == label)
2835 return label;
2836
2837- tem = next_active_insn (JUMP_LABEL (insn));
2838- if (tem && (GET_CODE (PATTERN (tem)) == ADDR_VEC
2839+ if (!ANY_RETURN_P (this_label))
2840+ {
2841+ rtx tem = next_active_insn (this_label);
2842+ if (tem
2843+ && (GET_CODE (PATTERN (tem)) == ADDR_VEC
2844 || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC))
2845- break;
2846+ break;
2847+ }
2848
2849- value = JUMP_LABEL (insn);
2850+ value = this_label;
2851 }
2852 if (depth == 10)
2853 return label;
2854@@ -2901,6 +2925,7 @@ fill_slots_from_thread (rtx insn, rtx co
2855 arithmetic insn after the jump insn and put the arithmetic insn in the
2856 delay slot. If we can't do this, return. */
2857 if (delay_list == 0 && likely && new_thread
2858+ && !ANY_RETURN_P (new_thread)
2859 && NONJUMP_INSN_P (new_thread)
2860 && GET_CODE (PATTERN (new_thread)) != ASM_INPUT
2861 && asm_noperands (PATTERN (new_thread)) < 0)
2862@@ -2985,16 +3010,14 @@ fill_slots_from_thread (rtx insn, rtx co
2863
2864 gcc_assert (thread_if_true);
2865
2866- if (new_thread && JUMP_P (new_thread)
2867- && (simplejump_p (new_thread)
2868- || GET_CODE (PATTERN (new_thread)) == RETURN)
2869+ if (new_thread && simplejump_or_return_p (new_thread)
2870 && redirect_with_delay_list_safe_p (insn,
2871 JUMP_LABEL (new_thread),
2872 delay_list))
2873 new_thread = follow_jumps (JUMP_LABEL (new_thread));
2874
2875- if (new_thread == 0)
2876- label = find_end_label ();
2877+ if (ANY_RETURN_P (new_thread))
2878+ label = find_end_label (new_thread);
2879 else if (LABEL_P (new_thread))
2880 label = new_thread;
2881 else
2882@@ -3340,11 +3363,12 @@ relax_delay_slots (rtx first)
2883 group of consecutive labels. */
2884 if (JUMP_P (insn)
2885 && (condjump_p (insn) || condjump_in_parallel_p (insn))
2886- && (target_label = JUMP_LABEL (insn)) != 0)
2887+ && (target_label = JUMP_LABEL (insn)) != 0
2888+ && !ANY_RETURN_P (target_label))
2889 {
2890 target_label = skip_consecutive_labels (follow_jumps (target_label));
2891- if (target_label == 0)
2892- target_label = find_end_label ();
2893+ if (ANY_RETURN_P (target_label))
2894+ target_label = find_end_label (target_label);
2895
2896 if (target_label && next_active_insn (target_label) == next
2897 && ! condjump_in_parallel_p (insn))
2898@@ -3359,9 +3383,8 @@ relax_delay_slots (rtx first)
2899 /* See if this jump conditionally branches around an unconditional
2900 jump. If so, invert this jump and point it to the target of the
2901 second jump. */
2902- if (next && JUMP_P (next)
2903+ if (next && simplejump_or_return_p (next)
2904 && any_condjump_p (insn)
2905- && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
2906 && target_label
2907 && next_active_insn (target_label) == next_active_insn (next)
2908 && no_labels_between_p (insn, next))
2909@@ -3403,8 +3426,7 @@ relax_delay_slots (rtx first)
2910 Don't do this if we expect the conditional branch to be true, because
2911 we would then be making the more common case longer. */
2912
2913- if (JUMP_P (insn)
2914- && (simplejump_p (insn) || GET_CODE (PATTERN (insn)) == RETURN)
2915+ if (simplejump_or_return_p (insn)
2916 && (other = prev_active_insn (insn)) != 0
2917 && any_condjump_p (other)
2918 && no_labels_between_p (other, insn)
2919@@ -3445,10 +3467,10 @@ relax_delay_slots (rtx first)
2920 Only do so if optimizing for size since this results in slower, but
2921 smaller code. */
2922 if (optimize_function_for_size_p (cfun)
2923- && GET_CODE (PATTERN (delay_insn)) == RETURN
2924+ && ANY_RETURN_P (PATTERN (delay_insn))
2925 && next
2926 && JUMP_P (next)
2927- && GET_CODE (PATTERN (next)) == RETURN)
2928+ && PATTERN (next) == PATTERN (delay_insn))
2929 {
2930 rtx after;
2931 int i;
2932@@ -3487,14 +3509,16 @@ relax_delay_slots (rtx first)
2933 continue;
2934
2935 target_label = JUMP_LABEL (delay_insn);
2936+ if (target_label && ANY_RETURN_P (target_label))
2937+ continue;
2938
2939 if (target_label)
2940 {
2941 /* If this jump goes to another unconditional jump, thread it, but
2942 don't convert a jump into a RETURN here. */
2943 trial = skip_consecutive_labels (follow_jumps (target_label));
2944- if (trial == 0)
2945- trial = find_end_label ();
2946+ if (ANY_RETURN_P (trial))
2947+ trial = find_end_label (trial);
2948
2949 if (trial && trial != target_label
2950 && redirect_with_delay_slots_safe_p (delay_insn, trial, insn))
2951@@ -3517,7 +3541,7 @@ relax_delay_slots (rtx first)
2952 later incorrectly compute register live/death info. */
2953 rtx tmp = next_active_insn (trial);
2954 if (tmp == 0)
2955- tmp = find_end_label ();
2956+ tmp = find_end_label (simple_return_rtx);
2957
2958 if (tmp)
2959 {
2960@@ -3537,14 +3561,12 @@ relax_delay_slots (rtx first)
2961 delay list and that insn is redundant, thread the jump. */
2962 if (trial && GET_CODE (PATTERN (trial)) == SEQUENCE
2963 && XVECLEN (PATTERN (trial), 0) == 2
2964- && JUMP_P (XVECEXP (PATTERN (trial), 0, 0))
2965- && (simplejump_p (XVECEXP (PATTERN (trial), 0, 0))
2966- || GET_CODE (PATTERN (XVECEXP (PATTERN (trial), 0, 0))) == RETURN)
2967+ && simplejump_or_return_p (XVECEXP (PATTERN (trial), 0, 0))
2968 && redundant_insn (XVECEXP (PATTERN (trial), 0, 1), insn, 0))
2969 {
2970 target_label = JUMP_LABEL (XVECEXP (PATTERN (trial), 0, 0));
2971- if (target_label == 0)
2972- target_label = find_end_label ();
2973+ if (ANY_RETURN_P (target_label))
2974+ target_label = find_end_label (target_label);
2975
2976 if (target_label
2977 && redirect_with_delay_slots_safe_p (delay_insn, target_label,
2978@@ -3622,16 +3644,15 @@ relax_delay_slots (rtx first)
2979 a RETURN here. */
2980 if (! INSN_ANNULLED_BRANCH_P (delay_insn)
2981 && any_condjump_p (delay_insn)
2982- && next && JUMP_P (next)
2983- && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
2984+ && next && simplejump_or_return_p (next)
2985 && next_active_insn (target_label) == next_active_insn (next)
2986 && no_labels_between_p (insn, next))
2987 {
2988 rtx label = JUMP_LABEL (next);
2989 rtx old_label = JUMP_LABEL (delay_insn);
2990
2991- if (label == 0)
2992- label = find_end_label ();
2993+ if (ANY_RETURN_P (label))
2994+ label = find_end_label (label);
2995
2996 /* find_end_label can generate a new label. Check this first. */
2997 if (label
2998@@ -3692,7 +3713,8 @@ static void
2999 make_return_insns (rtx first)
3000 {
3001 rtx insn, jump_insn, pat;
3002- rtx real_return_label = end_of_function_label;
3003+ rtx real_return_label = function_return_label;
3004+ rtx real_simple_return_label = function_simple_return_label;
3005 int slots, i;
3006
3007 #ifdef DELAY_SLOTS_FOR_EPILOGUE
3008@@ -3707,18 +3729,25 @@ make_return_insns (rtx first)
3009 #endif
3010
3011 /* See if there is a RETURN insn in the function other than the one we
3012- made for END_OF_FUNCTION_LABEL. If so, set up anything we can't change
3013+ made for FUNCTION_RETURN_LABEL. If so, set up anything we can't change
3014 into a RETURN to jump to it. */
3015 for (insn = first; insn; insn = NEXT_INSN (insn))
3016- if (JUMP_P (insn) && GET_CODE (PATTERN (insn)) == RETURN)
3017+ if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
3018 {
3019- real_return_label = get_label_before (insn);
3020+ rtx t = get_label_before (insn);
3021+ if (PATTERN (insn) == ret_rtx)
3022+ real_return_label = t;
3023+ else
3024+ real_simple_return_label = t;
3025 break;
3026 }
3027
3028 /* Show an extra usage of REAL_RETURN_LABEL so it won't go away if it
3029- was equal to END_OF_FUNCTION_LABEL. */
3030- LABEL_NUSES (real_return_label)++;
3031+ was equal to FUNCTION_RETURN_LABEL. */
3032+ if (real_return_label)
3033+ LABEL_NUSES (real_return_label)++;
3034+ if (real_simple_return_label)
3035+ LABEL_NUSES (real_simple_return_label)++;
3036
3037 /* Clear the list of insns to fill so we can use it. */
3038 obstack_free (&unfilled_slots_obstack, unfilled_firstobj);
3039@@ -3726,13 +3755,27 @@ make_return_insns (rtx first)
3040 for (insn = first; insn; insn = NEXT_INSN (insn))
3041 {
3042 int flags;
3043+ rtx kind, real_label;
3044
3045 /* Only look at filled JUMP_INSNs that go to the end of function
3046 label. */
3047 if (!NONJUMP_INSN_P (insn)
3048 || GET_CODE (PATTERN (insn)) != SEQUENCE
3049- || !JUMP_P (XVECEXP (PATTERN (insn), 0, 0))
3050- || JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) != end_of_function_label)
3051+ || !JUMP_P (XVECEXP (PATTERN (insn), 0, 0)))
3052+ continue;
3053+
3054+ if (JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) == function_return_label)
3055+ {
3056+ kind = ret_rtx;
3057+ real_label = real_return_label;
3058+ }
3059+ else if (JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0))
3060+ == function_simple_return_label)
3061+ {
3062+ kind = simple_return_rtx;
3063+ real_label = real_simple_return_label;
3064+ }
3065+ else
3066 continue;
3067
3068 pat = PATTERN (insn);
3069@@ -3740,14 +3783,12 @@ make_return_insns (rtx first)
3070
3071 /* If we can't make the jump into a RETURN, try to redirect it to the best
3072 RETURN and go on to the next insn. */
3073- if (! reorg_redirect_jump (jump_insn, NULL_RTX))
3074+ if (! reorg_redirect_jump (jump_insn, kind))
3075 {
3076 /* Make sure redirecting the jump will not invalidate the delay
3077 slot insns. */
3078- if (redirect_with_delay_slots_safe_p (jump_insn,
3079- real_return_label,
3080- insn))
3081- reorg_redirect_jump (jump_insn, real_return_label);
3082+ if (redirect_with_delay_slots_safe_p (jump_insn, real_label, insn))
3083+ reorg_redirect_jump (jump_insn, real_label);
3084 continue;
3085 }
3086
3087@@ -3787,7 +3828,7 @@ make_return_insns (rtx first)
3088 RETURN, delete the SEQUENCE and output the individual insns,
3089 followed by the RETURN. Then set things up so we try to find
3090 insns for its delay slots, if it needs some. */
3091- if (GET_CODE (PATTERN (jump_insn)) == RETURN)
3092+ if (ANY_RETURN_P (PATTERN (jump_insn)))
3093 {
3094 rtx prev = PREV_INSN (insn);
3095
3096@@ -3804,13 +3845,16 @@ make_return_insns (rtx first)
3097 else
3098 /* It is probably more efficient to keep this with its current
3099 delay slot as a branch to a RETURN. */
3100- reorg_redirect_jump (jump_insn, real_return_label);
3101+ reorg_redirect_jump (jump_insn, real_label);
3102 }
3103
3104 /* Now delete REAL_RETURN_LABEL if we never used it. Then try to fill any
3105 new delay slots we have created. */
3106- if (--LABEL_NUSES (real_return_label) == 0)
3107+ if (real_return_label != NULL_RTX && --LABEL_NUSES (real_return_label) == 0)
3108 delete_related_insns (real_return_label);
3109+ if (real_simple_return_label != NULL_RTX
3110+ && --LABEL_NUSES (real_simple_return_label) == 0)
3111+ delete_related_insns (real_simple_return_label);
3112
3113 fill_simple_delay_slots (1);
3114 fill_simple_delay_slots (0);
3115@@ -3878,7 +3922,7 @@ dbr_schedule (rtx first)
3116 init_resource_info (epilogue_insn);
3117
3118 /* Show we haven't computed an end-of-function label yet. */
3119- end_of_function_label = 0;
3120+ function_return_label = function_simple_return_label = NULL_RTX;
3121
3122 /* Initialize the statistics for this function. */
3123 memset (num_insns_needing_delays, 0, sizeof num_insns_needing_delays);
3124@@ -3900,11 +3944,23 @@ dbr_schedule (rtx first)
3125 /* If we made an end of function label, indicate that it is now
3126 safe to delete it by undoing our prior adjustment to LABEL_NUSES.
3127 If it is now unused, delete it. */
3128- if (end_of_function_label && --LABEL_NUSES (end_of_function_label) == 0)
3129- delete_related_insns (end_of_function_label);
3130+ if (function_return_label && --LABEL_NUSES (function_return_label) == 0)
3131+ delete_related_insns (function_return_label);
3132+ if (function_simple_return_label
3133+ && --LABEL_NUSES (function_simple_return_label) == 0)
3134+ delete_related_insns (function_simple_return_label);
3135
3136+#if defined HAVE_return || defined HAVE_simple_return
3137+ if (
3138 #ifdef HAVE_return
3139- if (HAVE_return && end_of_function_label != 0)
3140+ (HAVE_return && function_return_label != 0)
3141+#else
3142+ 0
3143+#endif
3144+#ifdef HAVE_simple_return
3145+ || (HAVE_simple_return && function_simple_return_label != 0)
3146+#endif
3147+ )
3148 make_return_insns (first);
3149 #endif
3150
3151Index: gcc-4_5-branch/gcc/resource.c
3152===================================================================
3153--- gcc-4_5-branch.orig/gcc/resource.c
3154+++ gcc-4_5-branch/gcc/resource.c
3155@@ -495,6 +495,8 @@ find_dead_or_set_registers (rtx target,
3156 || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
3157 {
3158 next = JUMP_LABEL (this_jump_insn);
3159+ if (next && ANY_RETURN_P (next))
3160+ next = NULL_RTX;
3161 if (jump_insn == 0)
3162 {
3163 jump_insn = insn;
3164@@ -562,9 +564,10 @@ find_dead_or_set_registers (rtx target,
3165 AND_COMPL_HARD_REG_SET (scratch, needed.regs);
3166 AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
3167
3168- find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
3169- &target_res, 0, jump_count,
3170- target_set, needed);
3171+ if (!ANY_RETURN_P (JUMP_LABEL (this_jump_insn)))
3172+ find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
3173+ &target_res, 0, jump_count,
3174+ target_set, needed);
3175 find_dead_or_set_registers (next,
3176 &fallthrough_res, 0, jump_count,
3177 set, needed);
3178@@ -1097,6 +1100,8 @@ mark_target_live_regs (rtx insns, rtx ta
3179 struct resources new_resources;
3180 rtx stop_insn = next_active_insn (jump_insn);
3181
3182+ if (jump_target && ANY_RETURN_P (jump_target))
3183+ jump_target = NULL_RTX;
3184 mark_target_live_regs (insns, next_active_insn (jump_target),
3185 &new_resources);
3186 CLEAR_RESOURCE (&set);
3187Index: gcc-4_5-branch/gcc/rtl.c
3188===================================================================
3189--- gcc-4_5-branch.orig/gcc/rtl.c
3190+++ gcc-4_5-branch/gcc/rtl.c
3191@@ -256,6 +256,8 @@ copy_rtx (rtx orig)
3192 case CODE_LABEL:
3193 case PC:
3194 case CC0:
3195+ case RETURN:
3196+ case SIMPLE_RETURN:
3197 case SCRATCH:
3198 /* SCRATCH must be shared because they represent distinct values. */
3199 return orig;
3200Index: gcc-4_5-branch/gcc/rtl.def
3201===================================================================
3202--- gcc-4_5-branch.orig/gcc/rtl.def
3203+++ gcc-4_5-branch/gcc/rtl.def
3204@@ -296,6 +296,10 @@ DEF_RTL_EXPR(CALL, "call", "ee", RTX_EXT
3205
3206 DEF_RTL_EXPR(RETURN, "return", "", RTX_EXTRA)
3207
3208+/* A plain return, to be used on paths that are reached without going
3209+ through the function prologue. */
3210+DEF_RTL_EXPR(SIMPLE_RETURN, "simple_return", "", RTX_EXTRA)
3211+
3212 /* Special for EH return from subroutine. */
3213
3214 DEF_RTL_EXPR(EH_RETURN, "eh_return", "", RTX_EXTRA)
3215Index: gcc-4_5-branch/gcc/rtl.h
3216===================================================================
3217--- gcc-4_5-branch.orig/gcc/rtl.h
3218+++ gcc-4_5-branch/gcc/rtl.h
3219@@ -411,6 +411,10 @@ struct GTY(()) rtvec_def {
3220 (JUMP_P (INSN) && (GET_CODE (PATTERN (INSN)) == ADDR_VEC || \
3221 GET_CODE (PATTERN (INSN)) == ADDR_DIFF_VEC))
3222
3223+/* Predicate yielding nonzero iff X is a return or simple_preturn. */
3224+#define ANY_RETURN_P(X) \
3225+ (GET_CODE (X) == RETURN || GET_CODE (X) == SIMPLE_RETURN)
3226+
3227 /* 1 if X is a unary operator. */
3228
3229 #define UNARY_P(X) \
3230@@ -1998,6 +2002,8 @@ enum global_rtl_index
3231 {
3232 GR_PC,
3233 GR_CC0,
3234+ GR_RETURN,
3235+ GR_SIMPLE_RETURN,
3236 GR_STACK_POINTER,
3237 GR_FRAME_POINTER,
3238 /* For register elimination to work properly these hard_frame_pointer_rtx,
3239@@ -2032,6 +2038,8 @@ extern GTY(()) rtx global_rtl[GR_MAX];
3240
3241 /* Standard pieces of rtx, to be substituted directly into things. */
3242 #define pc_rtx (global_rtl[GR_PC])
3243+#define ret_rtx (global_rtl[GR_RETURN])
3244+#define simple_return_rtx (global_rtl[GR_SIMPLE_RETURN])
3245 #define cc0_rtx (global_rtl[GR_CC0])
3246
3247 /* All references to certain hard regs, except those created
3248Index: gcc-4_5-branch/gcc/rtlanal.c
3249===================================================================
3250--- gcc-4_5-branch.orig/gcc/rtlanal.c
3251+++ gcc-4_5-branch/gcc/rtlanal.c
3252@@ -2673,6 +2673,7 @@ tablejump_p (const_rtx insn, rtx *labelp
3253
3254 if (JUMP_P (insn)
3255 && (label = JUMP_LABEL (insn)) != NULL_RTX
3256+ && !ANY_RETURN_P (label)
3257 && (table = next_active_insn (label)) != NULL_RTX
3258 && JUMP_TABLE_DATA_P (table))
3259 {
3260Index: gcc-4_5-branch/gcc/sched-int.h
3261===================================================================
3262--- gcc-4_5-branch.orig/gcc/sched-int.h
3263+++ gcc-4_5-branch/gcc/sched-int.h
3264@@ -199,7 +199,7 @@ extern int max_issue (struct ready_list
3265
3266 extern void ebb_compute_jump_reg_dependencies (rtx, regset, regset, regset);
3267
3268-extern edge find_fallthru_edge (basic_block);
3269+extern edge find_fallthru_edge_from (basic_block);
3270
3271 extern void (* sched_init_only_bb) (basic_block, basic_block);
3272 extern basic_block (* sched_split_block) (basic_block, rtx);
3273Index: gcc-4_5-branch/gcc/sched-vis.c
3274===================================================================
3275--- gcc-4_5-branch.orig/gcc/sched-vis.c
3276+++ gcc-4_5-branch/gcc/sched-vis.c
3277@@ -549,6 +549,9 @@ print_pattern (char *buf, const_rtx x, i
3278 case RETURN:
3279 sprintf (buf, "return");
3280 break;
3281+ case SIMPLE_RETURN:
3282+ sprintf (buf, "simple_return");
3283+ break;
3284 case CALL:
3285 print_exp (buf, x, verbose);
3286 break;
3287Index: gcc-4_5-branch/gcc/sel-sched-ir.c
3288===================================================================
3289--- gcc-4_5-branch.orig/gcc/sel-sched-ir.c
3290+++ gcc-4_5-branch/gcc/sel-sched-ir.c
3291@@ -686,7 +686,7 @@ merge_fences (fence_t f, insn_t insn,
3292
3293 /* Find fallthrough edge. */
3294 gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb);
3295- candidate = find_fallthru_edge (BLOCK_FOR_INSN (insn)->prev_bb);
3296+ candidate = find_fallthru_edge_from (BLOCK_FOR_INSN (insn)->prev_bb);
3297
3298 if (!candidate
3299 || (candidate->src != BLOCK_FOR_INSN (last_scheduled_insn)
3300Index: gcc-4_5-branch/gcc/sel-sched.c
3301===================================================================
3302--- gcc-4_5-branch.orig/gcc/sel-sched.c
3303+++ gcc-4_5-branch/gcc/sel-sched.c
3304@@ -617,8 +617,8 @@ in_fallthru_bb_p (rtx insn, rtx succ)
3305 if (bb == BLOCK_FOR_INSN (succ))
3306 return true;
3307
3308- if (find_fallthru_edge (bb))
3309- bb = find_fallthru_edge (bb)->dest;
3310+ if (find_fallthru_edge_from (bb))
3311+ bb = find_fallthru_edge_from (bb)->dest;
3312 else
3313 return false;
3314
3315@@ -4911,7 +4911,7 @@ move_cond_jump (rtx insn, bnd_t bnd)
3316 next = PREV_INSN (insn);
3317 BND_TO (bnd) = insn;
3318
3319- ft_edge = find_fallthru_edge (block_from);
3320+ ft_edge = find_fallthru_edge_from (block_from);
3321 block_next = ft_edge->dest;
3322 /* There must be a fallthrough block (or where should go
3323 control flow in case of false jump predicate otherwise?). */
3324Index: gcc-4_5-branch/gcc/vec.h
3325===================================================================
3326--- gcc-4_5-branch.orig/gcc/vec.h
3327+++ gcc-4_5-branch/gcc/vec.h
3328@@ -188,6 +188,18 @@ along with GCC; see the file COPYING3.
3329
3330 #define VEC_iterate(T,V,I,P) (VEC_OP(T,base,iterate)(VEC_BASE(V),I,&(P)))
3331
3332+/* Convenience macro for forward iteration. */
3333+
3334+#define FOR_EACH_VEC_ELT(T, V, I, P) \
3335+ for (I = 0; VEC_iterate (T, (V), (I), (P)); ++(I))
3336+
3337+/* Convenience macro for reverse iteration. */
3338+
3339+#define FOR_EACH_VEC_ELT_REVERSE(T,V,I,P) \
3340+ for (I = VEC_length (T, (V)) - 1; \
3341+ VEC_iterate (T, (V), (I), (P)); \
3342+ (I)--)
3343+
3344 /* Allocate new vector.
3345 VEC(T,A) *VEC_T_A_alloc(int reserve);
3346
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch
new file mode 100644
index 0000000000..aa9d6aa368
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99475.patch
@@ -0,0 +1,4217 @@
12011-02-08 Andrew Stubbs <ams@codesourcery.com>
2
3 Backport from FSF mainline:
4
5 2010-06-30 H.J. Lu <hongjiu.lu@intel.com>
6
7 PR target/44721
8 * config/i386/i386.md (peephole2 for arithmetic ops with memory):
9 Fix last commit.
10
11 2010-06-30 Richard Guenther <rguenther@suse.de>
12
13 PR target/44722
14 * config/i386/i386.md (peephole2 for fix:SSEMODEI24): Guard
15 against oscillation with reverse peephole2.
16
17 2010-07-01 Bernd Schmidt <bernds@codesourcery.com>
18
19 PR target/44727
20 * config/i386/i386.md (peephole2 for arithmetic ops with memory):
21 Make sure operand 0 dies.
22
232010-12-03 Yao Qi <yao@codesourcery.com>
24
25 * config/arm/arm-ldmstm.ml: Rewrite ldm/stm RTL patterns to fix
26 regressions.
27 * config/arm/ldmstm.md: Regenreate.
28
292010-12-03 Yao Qi <yao@codesourcery.com>
30
31 Backport from FSF mainline:
32
33 2010-08-02 Bernd Schmidt <bernds@codesourcery.com>
34
35 PR target/40457
36 * config/arm/arm.h (arm_regs_in_sequence): Declare.
37 * config/arm/arm-protos.h (emit_ldm_seq, emit_stm_seq,
38 load_multiple_sequence, store_multiple_sequence): Delete
39 declarations.
40 (arm_gen_load_multiple, arm_gen_store_multiple): Adjust
41 declarations.
42 * config/arm/ldmstm.md: New file.
43 * config/arm/arm.c (arm_regs_in_sequence): New array.
44 (load_multiple_sequence): Now static. New args SAVED_ORDER,
45 CHECK_REGS. All callers changed.
46 If SAVED_ORDER is nonnull, copy the computed order into it.
47 If CHECK_REGS is false, don't sort REGS. Handle Thumb mode.
48 (store_multiple_sequence): Now static. New args NOPS_TOTAL,
49 SAVED_ORDER, REG_RTXS and CHECK_REGS. All callers changed.
50 If SAVED_ORDER is nonnull, copy the computed order into it.
51 If CHECK_REGS is false, don't sort REGS. Set up REG_RTXS just
52 like REGS. Handle Thumb mode.
53 (arm_gen_load_multiple_1): New function, broken out of
54 arm_gen_load_multiple.
55 (arm_gen_store_multiple_1): New function, broken out of
56 arm_gen_store_multiple.
57 (arm_gen_multiple_op): New function, with code from
58 arm_gen_load_multiple and arm_gen_store_multiple moved here.
59 (arm_gen_load_multiple, arm_gen_store_multiple): Now just
60 wrappers around arm_gen_multiple_op. Remove argument UP, all callers
61 changed.
62 (gen_ldm_seq, gen_stm_seq, gen_const_stm_seq): New functions.
63 * config/arm/predicates.md (commutative_binary_operator): New.
64 (load_multiple_operation, store_multiple_operation): Handle more
65 variants of these patterns with different starting offsets. Handle
66 Thumb-1.
67 * config/arm/arm.md: Include "ldmstm.md".
68 (ldmsi_postinc4, ldmsi_postinc4_thumb1, ldmsi_postinc3, ldmsi_postinc2,
69 ldmsi4, ldmsi3, ldmsi2, stmsi_postinc4, stmsi_postinc4_thumb1,
70 stmsi_postinc3, stmsi_postinc2, stmsi4, stmsi3, stmsi2 and related
71 peepholes): Delete.
72 * config/arm/ldmstm.md: New file.
73 * config/arm/arm-ldmstm.ml: New file.
74
75 * config/arm/arm.c (arm_rtx_costs_1): Remove second clause from the
76 if statement which adds extra costs to frame-related expressions.
77
78 2010-05-06 Bernd Schmidt <bernds@codesourcery.com>
79
80 * config/arm/arm.h (MAX_LDM_STM_OPS): New macro.
81 * config/arm/arm.c (multiple_operation_profitable_p,
82 compute_offset_order): New static functions.
83 (load_multiple_sequence, store_multiple_sequence): Use them.
84 Replace constant 4 with MAX_LDM_STM_OPS. Compute order[0] from
85 memory offsets, not register numbers.
86 (emit_ldm_seq, emit_stm_seq): Replace constant 4 with MAX_LDM_STM_OPS.
87
88 2010-04-16 Bernd Schmidt <bernds@codesourcery.com>
89
90 * recog.h (struct recog_data): New field is_operator.
91 (struct insn_operand_data): New field is_operator.
92 * recog.c (extract_insn): Set recog_data.is_operator.
93 * genoutput.c (output_operand_data): Emit code to set the
94 is_operator field.
95 * reload.c (find_reloads): Use it rather than testing for an
96 empty constraint string.
97
98=== added file 'gcc/config/arm/arm-ldmstm.ml'
99Index: gcc-4_5-branch/gcc/config/arm/arm-ldmstm.ml
100===================================================================
101--- /dev/null
102+++ gcc-4_5-branch/gcc/config/arm/arm-ldmstm.ml
103@@ -0,0 +1,333 @@
104+(* Auto-generate ARM ldm/stm patterns
105+ Copyright (C) 2010 Free Software Foundation, Inc.
106+ Contributed by CodeSourcery.
107+
108+ This file is part of GCC.
109+
110+ GCC is free software; you can redistribute it and/or modify it under
111+ the terms of the GNU General Public License as published by the Free
112+ Software Foundation; either version 3, or (at your option) any later
113+ version.
114+
115+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
116+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
117+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
118+ for more details.
119+
120+ You should have received a copy of the GNU General Public License
121+ along with GCC; see the file COPYING3. If not see
122+ <http://www.gnu.org/licenses/>.
123+
124+ This is an O'Caml program. The O'Caml compiler is available from:
125+
126+ http://caml.inria.fr/
127+
128+ Or from your favourite OS's friendly packaging system. Tested with version
129+ 3.09.2, though other versions will probably work too.
130+
131+ Run with:
132+ ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.ml
133+*)
134+
135+type amode = IA | IB | DA | DB
136+
137+type optype = IN | OUT | INOUT
138+
139+let rec string_of_addrmode addrmode =
140+ match addrmode with
141+ IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
142+
143+let rec initial_offset addrmode nregs =
144+ match addrmode with
145+ IA -> 0
146+ | IB -> 4
147+ | DA -> -4 * nregs + 4
148+ | DB -> -4 * nregs
149+
150+let rec final_offset addrmode nregs =
151+ match addrmode with
152+ IA -> nregs * 4
153+ | IB -> nregs * 4
154+ | DA -> -4 * nregs
155+ | DB -> -4 * nregs
156+
157+let constr thumb =
158+ if thumb then "l" else "rk"
159+
160+let inout_constr op_type =
161+ match op_type with
162+ OUT -> "="
163+ | INOUT -> "+&"
164+ | IN -> ""
165+
166+let destreg nregs first op_type thumb =
167+ if not first then
168+ Printf.sprintf "(match_dup %d)" (nregs)
169+ else
170+ Printf.sprintf ("(match_operand:SI %d \"s_register_operand\" \"%s%s\")")
171+ (nregs) (inout_constr op_type) (constr thumb)
172+
173+let write_ldm_set thumb nregs offset opnr first =
174+ let indent = " " in
175+ Printf.printf "%s" (if first then " [" else indent);
176+ Printf.printf "(set (match_operand:SI %d \"arm_hard_register_operand\" \"\")\n" opnr;
177+ Printf.printf "%s (mem:SI " indent;
178+ begin if offset != 0 then Printf.printf "(plus:SI " end;
179+ Printf.printf "%s" (destreg nregs first IN thumb);
180+ begin if offset != 0 then Printf.printf "\n%s (const_int %d))" indent offset end;
181+ Printf.printf "))"
182+
183+let write_stm_set thumb nregs offset opnr first =
184+ let indent = " " in
185+ Printf.printf "%s" (if first then " [" else indent);
186+ Printf.printf "(set (mem:SI ";
187+ begin if offset != 0 then Printf.printf "(plus:SI " end;
188+ Printf.printf "%s" (destreg nregs first IN thumb);
189+ begin if offset != 0 then Printf.printf " (const_int %d))" offset end;
190+ Printf.printf ")\n%s (match_operand:SI %d \"arm_hard_register_operand\" \"\"))" indent opnr
191+
192+let write_ldm_peep_set extra_indent nregs opnr first =
193+ let indent = " " ^ extra_indent in
194+ Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
195+ Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
196+ Printf.printf "%s (match_operand:SI %d \"memory_operand\" \"\"))" indent (nregs + opnr)
197+
198+let write_stm_peep_set extra_indent nregs opnr first =
199+ let indent = " " ^ extra_indent in
200+ Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
201+ Printf.printf "(set (match_operand:SI %d \"memory_operand\" \"\")\n" (nregs + opnr);
202+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\"))" indent opnr
203+
204+let write_any_load optype nregs opnr first =
205+ let indent = " " in
206+ Printf.printf "%s" (if first then " [" else indent);
207+ Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
208+ Printf.printf "%s (match_operand:SI %d \"%s\" \"\"))" indent (nregs * 2 + opnr) optype
209+
210+let write_const_store nregs opnr first =
211+ let indent = " " in
212+ Printf.printf "%s(set (match_operand:SI %d \"memory_operand\" \"\")\n" indent (nregs + opnr);
213+ Printf.printf "%s (match_dup %d))" indent opnr
214+
215+let write_const_stm_peep_set nregs opnr first =
216+ write_any_load "const_int_operand" nregs opnr first;
217+ Printf.printf "\n";
218+ write_const_store nregs opnr false
219+
220+
221+let rec write_pat_sets func opnr offset first n_left =
222+ func offset opnr first;
223+ begin
224+ if n_left > 1 then begin
225+ Printf.printf "\n";
226+ write_pat_sets func (opnr + 1) (offset + 4) false (n_left - 1);
227+ end else
228+ Printf.printf "]"
229+ end
230+
231+let rec write_peep_sets func opnr first n_left =
232+ func opnr first;
233+ begin
234+ if n_left > 1 then begin
235+ Printf.printf "\n";
236+ write_peep_sets func (opnr + 1) false (n_left - 1);
237+ end
238+ end
239+
240+let can_thumb addrmode update is_store =
241+ match addrmode, update, is_store with
242+ (* Thumb1 mode only supports IA with update. However, for LDMIA,
243+ if the address register also appears in the list of loaded
244+ registers, the loaded value is stored, hence the RTL pattern
245+ to describe such an insn does not have an update. We check
246+ in the match_parallel predicate that the condition described
247+ above is met. *)
248+ IA, _, false -> true
249+ | IA, true, true -> true
250+ | _ -> false
251+
252+let target addrmode thumb =
253+ match addrmode, thumb with
254+ IA, true -> "TARGET_THUMB1"
255+ | IA, false -> "TARGET_32BIT"
256+ | DB, false -> "TARGET_32BIT"
257+ | _, false -> "TARGET_ARM"
258+
259+let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
260+ let astr = string_of_addrmode addrmode in
261+ Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
262+ (if thumb then "thumb_" else "") name nregs astr
263+ (if update then "_update" else "");
264+ Printf.printf " [(match_parallel 0 \"%s_multiple_operation\"\n" ls;
265+ begin
266+ if update then begin
267+ Printf.printf " [(set %s\n (plus:SI "
268+ (destreg 1 true OUT thumb); (*destreg 2 true IN thumb*)
269+ Printf.printf "(match_operand:SI 2 \"s_register_operand\" \"1\")";
270+ Printf.printf " (const_int %d)))\n"
271+ (final_offset addrmode nregs)
272+ end
273+ end;
274+ write_pat_sets
275+ (write_set_fn thumb (if update then 2 else 1)) (if update then 3 else 2)
276+ (initial_offset addrmode nregs)
277+ (not update) nregs;
278+ Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
279+ (target addrmode thumb)
280+ (if update then nregs + 1 else nregs);
281+ Printf.printf " \"%s%%(%s%%)\\t%%%d%s, {"
282+ name astr (1) (if update then "!" else "");
283+ for n = 1 to nregs; do
284+ Printf.printf "%%%d%s" (n+(if update then 2 else 1)) (if n < nregs then ", " else "")
285+ done;
286+ Printf.printf "}\"\n";
287+ Printf.printf " [(set_attr \"type\" \"%s%d\")" ls nregs;
288+ begin if not thumb then
289+ Printf.printf "\n (set_attr \"predicable\" \"yes\")";
290+ end;
291+ Printf.printf "])\n\n"
292+
293+let write_ldm_pattern addrmode nregs update =
294+ write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update false;
295+ begin if can_thumb addrmode update false then
296+ write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update true;
297+ end
298+
299+let write_stm_pattern addrmode nregs update =
300+ write_pattern_1 "stm" "store" addrmode nregs write_stm_set update false;
301+ begin if can_thumb addrmode update true then
302+ write_pattern_1 "stm" "store" addrmode nregs write_stm_set update true;
303+ end
304+
305+let write_ldm_commutative_peephole thumb =
306+ let nregs = 2 in
307+ Printf.printf "(define_peephole2\n";
308+ write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
309+ let indent = " " in
310+ if thumb then begin
311+ Printf.printf "\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
312+ Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
313+ Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
314+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
315+ end else begin
316+ Printf.printf "\n%s(parallel\n" indent;
317+ Printf.printf "%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
318+ Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
319+ Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
320+ Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
321+ Printf.printf "%s (clobber (reg:CC CC_REGNUM))])]\n" indent
322+ end;
323+ Printf.printf " \"(((operands[%d] == operands[0] && operands[%d] == operands[1])\n" (nregs * 2 + 2) (nregs * 2 + 3);
324+ Printf.printf " || (operands[%d] == operands[0] && operands[%d] == operands[1]))\n" (nregs * 2 + 3) (nregs * 2 + 2);
325+ Printf.printf " && peep2_reg_dead_p (%d, operands[0]) && peep2_reg_dead_p (%d, operands[1]))\"\n" (nregs + 1) (nregs + 1);
326+ begin
327+ if thumb then
328+ Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
329+ (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
330+ else begin
331+ Printf.printf " [(parallel\n";
332+ Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
333+ (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
334+ Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
335+ end
336+ end;
337+ Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
338+ Printf.printf "})\n\n"
339+
340+let write_ldm_peephole nregs =
341+ Printf.printf "(define_peephole2\n";
342+ write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
343+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
344+ Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
345+
346+let write_ldm_peephole_b nregs =
347+ if nregs > 2 then begin
348+ Printf.printf "(define_peephole2\n";
349+ write_ldm_peep_set "" nregs 0 true;
350+ Printf.printf "\n (parallel\n";
351+ write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
352+ Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
353+ Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
354+ end
355+
356+let write_stm_peephole nregs =
357+ Printf.printf "(define_peephole2\n";
358+ write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
359+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
360+ Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
361+
362+let write_stm_peephole_b nregs =
363+ if nregs > 2 then begin
364+ Printf.printf "(define_peephole2\n";
365+ write_stm_peep_set "" nregs 0 true;
366+ Printf.printf "\n (parallel\n";
367+ write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
368+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
369+ Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
370+ end
371+
372+let write_const_stm_peephole_a nregs =
373+ Printf.printf "(define_peephole2\n";
374+ write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
375+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
376+ Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
377+
378+let write_const_stm_peephole_b nregs =
379+ Printf.printf "(define_peephole2\n";
380+ write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
381+ Printf.printf "\n";
382+ write_peep_sets (write_const_store nregs) 0 false nregs;
383+ Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
384+ Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
385+
386+let patterns () =
387+ let addrmodes = [ IA; IB; DA; DB ] in
388+ let sizes = [ 4; 3; 2] in
389+ List.iter
390+ (fun n ->
391+ List.iter
392+ (fun addrmode ->
393+ write_ldm_pattern addrmode n false;
394+ write_ldm_pattern addrmode n true;
395+ write_stm_pattern addrmode n false;
396+ write_stm_pattern addrmode n true)
397+ addrmodes;
398+ write_ldm_peephole n;
399+ write_ldm_peephole_b n;
400+ write_const_stm_peephole_a n;
401+ write_const_stm_peephole_b n;
402+ write_stm_peephole n;)
403+ sizes;
404+ write_ldm_commutative_peephole false;
405+ write_ldm_commutative_peephole true
406+
407+let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
408+
409+(* Do it. *)
410+
411+let _ =
412+ print_lines [
413+"/* ARM ldm/stm instruction patterns. This file was automatically generated";
414+" using arm-ldmstm.ml. Please do not edit manually.";
415+"";
416+" Copyright (C) 2010 Free Software Foundation, Inc.";
417+" Contributed by CodeSourcery.";
418+"";
419+" This file is part of GCC.";
420+"";
421+" GCC is free software; you can redistribute it and/or modify it";
422+" under the terms of the GNU General Public License as published";
423+" by the Free Software Foundation; either version 3, or (at your";
424+" option) any later version.";
425+"";
426+" GCC is distributed in the hope that it will be useful, but WITHOUT";
427+" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
428+" or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
429+" License for more details.";
430+"";
431+" You should have received a copy of the GNU General Public License and";
432+" a copy of the GCC Runtime Library Exception along with this program;";
433+" see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
434+" <http://www.gnu.org/licenses/>. */";
435+""];
436+ patterns ();
437Index: gcc-4_5-branch/gcc/config/arm/arm-protos.h
438===================================================================
439--- gcc-4_5-branch.orig/gcc/config/arm/arm-protos.h
440+++ gcc-4_5-branch/gcc/config/arm/arm-protos.h
441@@ -100,14 +100,11 @@ extern int symbol_mentioned_p (rtx);
442 extern int label_mentioned_p (rtx);
443 extern RTX_CODE minmax_code (rtx);
444 extern int adjacent_mem_locations (rtx, rtx);
445-extern int load_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
446-extern const char *emit_ldm_seq (rtx *, int);
447-extern int store_multiple_sequence (rtx *, int, int *, int *, HOST_WIDE_INT *);
448-extern const char * emit_stm_seq (rtx *, int);
449-extern rtx arm_gen_load_multiple (int, int, rtx, int, int,
450- rtx, HOST_WIDE_INT *);
451-extern rtx arm_gen_store_multiple (int, int, rtx, int, int,
452- rtx, HOST_WIDE_INT *);
453+extern bool gen_ldm_seq (rtx *, int, bool);
454+extern bool gen_stm_seq (rtx *, int);
455+extern bool gen_const_stm_seq (rtx *, int);
456+extern rtx arm_gen_load_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
457+extern rtx arm_gen_store_multiple (int *, int, rtx, int, rtx, HOST_WIDE_INT *);
458 extern int arm_gen_movmemqi (rtx *);
459 extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
460 extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
461Index: gcc-4_5-branch/gcc/config/arm/arm.c
462===================================================================
463--- gcc-4_5-branch.orig/gcc/config/arm/arm.c
464+++ gcc-4_5-branch/gcc/config/arm/arm.c
465@@ -753,6 +753,12 @@ static const char * const arm_condition_
466 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
467 };
468
469+/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
470+int arm_regs_in_sequence[] =
471+{
472+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
473+};
474+
475 #define ARM_LSL_NAME (TARGET_UNIFIED_ASM ? "lsl" : "asl")
476 #define streq(string1, string2) (strcmp (string1, string2) == 0)
477
478@@ -9680,24 +9686,125 @@ adjacent_mem_locations (rtx a, rtx b)
479 return 0;
480 }
481
482-int
483-load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
484- HOST_WIDE_INT *load_offset)
485+
486+/* Return true iff it would be profitable to turn a sequence of NOPS loads
487+ or stores (depending on IS_STORE) into a load-multiple or store-multiple
488+ instruction. ADD_OFFSET is nonzero if the base address register needs
489+ to be modified with an add instruction before we can use it. */
490+
491+static bool
492+multiple_operation_profitable_p (bool is_store ATTRIBUTE_UNUSED,
493+ int nops, HOST_WIDE_INT add_offset)
494+ {
495+ /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
496+ if the offset isn't small enough. The reason 2 ldrs are faster
497+ is because these ARMs are able to do more than one cache access
498+ in a single cycle. The ARM9 and StrongARM have Harvard caches,
499+ whilst the ARM8 has a double bandwidth cache. This means that
500+ these cores can do both an instruction fetch and a data fetch in
501+ a single cycle, so the trick of calculating the address into a
502+ scratch register (one of the result regs) and then doing a load
503+ multiple actually becomes slower (and no smaller in code size).
504+ That is the transformation
505+
506+ ldr rd1, [rbase + offset]
507+ ldr rd2, [rbase + offset + 4]
508+
509+ to
510+
511+ add rd1, rbase, offset
512+ ldmia rd1, {rd1, rd2}
513+
514+ produces worse code -- '3 cycles + any stalls on rd2' instead of
515+ '2 cycles + any stalls on rd2'. On ARMs with only one cache
516+ access per cycle, the first sequence could never complete in less
517+ than 6 cycles, whereas the ldm sequence would only take 5 and
518+ would make better use of sequential accesses if not hitting the
519+ cache.
520+
521+ We cheat here and test 'arm_ld_sched' which we currently know to
522+ only be true for the ARM8, ARM9 and StrongARM. If this ever
523+ changes, then the test below needs to be reworked. */
524+ if (nops == 2 && arm_ld_sched && add_offset != 0)
525+ return false;
526+
527+ return true;
528+}
529+
530+/* Subroutine of load_multiple_sequence and store_multiple_sequence.
531+ Given an array of UNSORTED_OFFSETS, of which there are NOPS, compute
532+ an array ORDER which describes the sequence to use when accessing the
533+ offsets that produces an ascending order. In this sequence, each
534+ offset must be larger by exactly 4 than the previous one. ORDER[0]
535+ must have been filled in with the lowest offset by the caller.
536+ If UNSORTED_REGS is nonnull, it is an array of register numbers that
537+ we use to verify that ORDER produces an ascending order of registers.
538+ Return true if it was possible to construct such an order, false if
539+ not. */
540+
541+static bool
542+compute_offset_order (int nops, HOST_WIDE_INT *unsorted_offsets, int *order,
543+ int *unsorted_regs)
544 {
545- int unsorted_regs[4];
546- HOST_WIDE_INT unsorted_offsets[4];
547- int order[4];
548- int base_reg = -1;
549 int i;
550+ for (i = 1; i < nops; i++)
551+ {
552+ int j;
553+
554+ order[i] = order[i - 1];
555+ for (j = 0; j < nops; j++)
556+ if (unsorted_offsets[j] == unsorted_offsets[order[i - 1]] + 4)
557+ {
558+ /* We must find exactly one offset that is higher than the
559+ previous one by 4. */
560+ if (order[i] != order[i - 1])
561+ return false;
562+ order[i] = j;
563+ }
564+ if (order[i] == order[i - 1])
565+ return false;
566+ /* The register numbers must be ascending. */
567+ if (unsorted_regs != NULL
568+ && unsorted_regs[order[i]] <= unsorted_regs[order[i - 1]])
569+ return false;
570+ }
571+ return true;
572+}
573+
574+/* Used to determine in a peephole whether a sequence of load
575+ instructions can be changed into a load-multiple instruction.
576+ NOPS is the number of separate load instructions we are examining. The
577+ first NOPS entries in OPERANDS are the destination registers, the
578+ next NOPS entries are memory operands. If this function is
579+ successful, *BASE is set to the common base register of the memory
580+ accesses; *LOAD_OFFSET is set to the first memory location's offset
581+ from that base register.
582+ REGS is an array filled in with the destination register numbers.
583+ SAVED_ORDER (if nonnull), is an array filled in with an order that maps
584+ insn numbers to to an ascending order of stores. If CHECK_REGS is true,
585+ the sequence of registers in REGS matches the loads from ascending memory
586+ locations, and the function verifies that the register numbers are
587+ themselves ascending. If CHECK_REGS is false, the register numbers
588+ are stored in the order they are found in the operands. */
589+static int
590+load_multiple_sequence (rtx *operands, int nops, int *regs, int *saved_order,
591+ int *base, HOST_WIDE_INT *load_offset, bool check_regs)
592+{
593+ int unsorted_regs[MAX_LDM_STM_OPS];
594+ HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
595+ int order[MAX_LDM_STM_OPS];
596+ rtx base_reg_rtx = NULL;
597+ int base_reg = -1;
598+ int i, ldm_case;
599
600 if (low_irq_latency)
601 return 0;
602
603- /* Can only handle 2, 3, or 4 insns at present,
604- though could be easily extended if required. */
605- gcc_assert (nops >= 2 && nops <= 4);
606+ /* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
607+ easily extended if required. */
608+ gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
609
610- memset (order, 0, 4 * sizeof (int));
611+ memset (order, 0, MAX_LDM_STM_OPS * sizeof (int));
612
613 /* Loop over the operands and check that the memory references are
614 suitable (i.e. immediate offsets from the same base register). At
615@@ -9735,32 +9842,30 @@ load_multiple_sequence (rtx *operands, i
616 if (i == 0)
617 {
618 base_reg = REGNO (reg);
619- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
620- ? REGNO (operands[i])
621- : REGNO (SUBREG_REG (operands[i])));
622- order[0] = 0;
623- }
624- else
625- {
626- if (base_reg != (int) REGNO (reg))
627- /* Not addressed from the same base register. */
628+ base_reg_rtx = reg;
629+ if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
630 return 0;
631-
632- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
633- ? REGNO (operands[i])
634- : REGNO (SUBREG_REG (operands[i])));
635- if (unsorted_regs[i] < unsorted_regs[order[0]])
636- order[0] = i;
637 }
638+ else if (base_reg != (int) REGNO (reg))
639+ /* Not addressed from the same base register. */
640+ return 0;
641+
642+ unsorted_regs[i] = (GET_CODE (operands[i]) == REG
643+ ? REGNO (operands[i])
644+ : REGNO (SUBREG_REG (operands[i])));
645
646 /* If it isn't an integer register, or if it overwrites the
647 base register but isn't the last insn in the list, then
648 we can't do this. */
649- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14
650+ if (unsorted_regs[i] < 0
651+ || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
652+ || unsorted_regs[i] > 14
653 || (i != nops - 1 && unsorted_regs[i] == base_reg))
654 return 0;
655
656 unsorted_offsets[i] = INTVAL (offset);
657+ if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]])
658+ order[0] = i;
659 }
660 else
661 /* Not a suitable memory address. */
662@@ -9769,167 +9874,90 @@ load_multiple_sequence (rtx *operands, i
663
664 /* All the useful information has now been extracted from the
665 operands into unsorted_regs and unsorted_offsets; additionally,
666- order[0] has been set to the lowest numbered register in the
667- list. Sort the registers into order, and check that the memory
668- offsets are ascending and adjacent. */
669-
670- for (i = 1; i < nops; i++)
671- {
672- int j;
673-
674- order[i] = order[i - 1];
675- for (j = 0; j < nops; j++)
676- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
677- && (order[i] == order[i - 1]
678- || unsorted_regs[j] < unsorted_regs[order[i]]))
679- order[i] = j;
680-
681- /* Have we found a suitable register? if not, one must be used more
682- than once. */
683- if (order[i] == order[i - 1])
684- return 0;
685+ order[0] has been set to the lowest offset in the list. Sort
686+ the offsets into order, verifying that they are adjacent, and
687+ check that the register numbers are ascending. */
688+ if (!compute_offset_order (nops, unsorted_offsets, order,
689+ check_regs ? unsorted_regs : NULL))
690+ return 0;
691
692- /* Is the memory address adjacent and ascending? */
693- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
694- return 0;
695- }
696+ if (saved_order)
697+ memcpy (saved_order, order, sizeof order);
698
699 if (base)
700 {
701 *base = base_reg;
702
703 for (i = 0; i < nops; i++)
704- regs[i] = unsorted_regs[order[i]];
705+ regs[i] = unsorted_regs[check_regs ? order[i] : i];
706
707 *load_offset = unsorted_offsets[order[0]];
708 }
709
710- if (unsorted_offsets[order[0]] == 0)
711- return 1; /* ldmia */
712-
713- if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
714- return 2; /* ldmib */
715-
716- if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
717- return 3; /* ldmda */
718-
719- if (unsorted_offsets[order[nops - 1]] == -4)
720- return 4; /* ldmdb */
721-
722- /* For ARM8,9 & StrongARM, 2 ldr instructions are faster than an ldm
723- if the offset isn't small enough. The reason 2 ldrs are faster
724- is because these ARMs are able to do more than one cache access
725- in a single cycle. The ARM9 and StrongARM have Harvard caches,
726- whilst the ARM8 has a double bandwidth cache. This means that
727- these cores can do both an instruction fetch and a data fetch in
728- a single cycle, so the trick of calculating the address into a
729- scratch register (one of the result regs) and then doing a load
730- multiple actually becomes slower (and no smaller in code size).
731- That is the transformation
732-
733- ldr rd1, [rbase + offset]
734- ldr rd2, [rbase + offset + 4]
735-
736- to
737-
738- add rd1, rbase, offset
739- ldmia rd1, {rd1, rd2}
740-
741- produces worse code -- '3 cycles + any stalls on rd2' instead of
742- '2 cycles + any stalls on rd2'. On ARMs with only one cache
743- access per cycle, the first sequence could never complete in less
744- than 6 cycles, whereas the ldm sequence would only take 5 and
745- would make better use of sequential accesses if not hitting the
746- cache.
747-
748- We cheat here and test 'arm_ld_sched' which we currently know to
749- only be true for the ARM8, ARM9 and StrongARM. If this ever
750- changes, then the test below needs to be reworked. */
751- if (nops == 2 && arm_ld_sched)
752+ if (TARGET_THUMB1
753+ && !peep2_reg_dead_p (nops, base_reg_rtx))
754 return 0;
755
756- /* Can't do it without setting up the offset, only do this if it takes
757- no more than one insn. */
758- return (const_ok_for_arm (unsorted_offsets[order[0]])
759- || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
760-}
761-
762-const char *
763-emit_ldm_seq (rtx *operands, int nops)
764-{
765- int regs[4];
766- int base_reg;
767- HOST_WIDE_INT offset;
768- char buf[100];
769- int i;
770-
771- switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
772- {
773- case 1:
774- strcpy (buf, "ldm%(ia%)\t");
775- break;
776-
777- case 2:
778- strcpy (buf, "ldm%(ib%)\t");
779- break;
780-
781- case 3:
782- strcpy (buf, "ldm%(da%)\t");
783- break;
784-
785- case 4:
786- strcpy (buf, "ldm%(db%)\t");
787- break;
788-
789- case 5:
790- if (offset >= 0)
791- sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
792- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
793- (long) offset);
794- else
795- sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
796- reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
797- (long) -offset);
798- output_asm_insn (buf, operands);
799- base_reg = regs[0];
800- strcpy (buf, "ldm%(ia%)\t");
801- break;
802-
803- default:
804- gcc_unreachable ();
805- }
806-
807- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
808- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
809-
810- for (i = 1; i < nops; i++)
811- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
812- reg_names[regs[i]]);
813+ if (unsorted_offsets[order[0]] == 0)
814+ ldm_case = 1; /* ldmia */
815+ else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
816+ ldm_case = 2; /* ldmib */
817+ else if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
818+ ldm_case = 3; /* ldmda */
819+ else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
820+ ldm_case = 4; /* ldmdb */
821+ else if (const_ok_for_arm (unsorted_offsets[order[0]])
822+ || const_ok_for_arm (-unsorted_offsets[order[0]]))
823+ ldm_case = 5;
824+ else
825+ return 0;
826
827- strcat (buf, "}\t%@ phole ldm");
828+ if (!multiple_operation_profitable_p (false, nops,
829+ ldm_case == 5
830+ ? unsorted_offsets[order[0]] : 0))
831+ return 0;
832
833- output_asm_insn (buf, operands);
834- return "";
835+ return ldm_case;
836 }
837
838-int
839-store_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
840- HOST_WIDE_INT * load_offset)
841-{
842- int unsorted_regs[4];
843- HOST_WIDE_INT unsorted_offsets[4];
844- int order[4];
845+/* Used to determine in a peephole whether a sequence of store instructions can
846+ be changed into a store-multiple instruction.
847+ NOPS is the number of separate store instructions we are examining.
848+ NOPS_TOTAL is the total number of instructions recognized by the peephole
849+ pattern.
850+ The first NOPS entries in OPERANDS are the source registers, the next
851+ NOPS entries are memory operands. If this function is successful, *BASE is
852+ set to the common base register of the memory accesses; *LOAD_OFFSET is set
853+ to the first memory location's offset from that base register. REGS is an
854+ array filled in with the source register numbers, REG_RTXS (if nonnull) is
855+ likewise filled with the corresponding rtx's.
856+ SAVED_ORDER (if nonnull), is an array filled in with an order that maps insn
857+ numbers to to an ascending order of stores.
858+ If CHECK_REGS is true, the sequence of registers in *REGS matches the stores
859+ from ascending memory locations, and the function verifies that the register
860+ numbers are themselves ascending. If CHECK_REGS is false, the register
861+ numbers are stored in the order they are found in the operands. */
862+static int
863+store_multiple_sequence (rtx *operands, int nops, int nops_total,
864+ int *regs, rtx *reg_rtxs, int *saved_order, int *base,
865+ HOST_WIDE_INT *load_offset, bool check_regs)
866+{
867+ int unsorted_regs[MAX_LDM_STM_OPS];
868+ rtx unsorted_reg_rtxs[MAX_LDM_STM_OPS];
869+ HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
870+ int order[MAX_LDM_STM_OPS];
871 int base_reg = -1;
872- int i;
873+ rtx base_reg_rtx = NULL;
874+ int i, stm_case;
875
876 if (low_irq_latency)
877 return 0;
878
879- /* Can only handle 2, 3, or 4 insns at present, though could be easily
880- extended if required. */
881- gcc_assert (nops >= 2 && nops <= 4);
882+ /* Can only handle up to MAX_LDM_STM_OPS insns at present, though could be
883+ easily extended if required. */
884+ gcc_assert (nops >= 2 && nops <= MAX_LDM_STM_OPS);
885
886- memset (order, 0, 4 * sizeof (int));
887+ memset (order, 0, MAX_LDM_STM_OPS * sizeof (int));
888
889 /* Loop over the operands and check that the memory references are
890 suitable (i.e. immediate offsets from the same base register). At
891@@ -9964,32 +9992,32 @@ store_multiple_sequence (rtx *operands,
892 && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
893 == CONST_INT)))
894 {
895+ unsorted_reg_rtxs[i] = (GET_CODE (operands[i]) == REG
896+ ? operands[i] : SUBREG_REG (operands[i]));
897+ unsorted_regs[i] = REGNO (unsorted_reg_rtxs[i]);
898+
899 if (i == 0)
900 {
901 base_reg = REGNO (reg);
902- unsorted_regs[0] = (GET_CODE (operands[i]) == REG
903- ? REGNO (operands[i])
904- : REGNO (SUBREG_REG (operands[i])));
905- order[0] = 0;
906- }
907- else
908- {
909- if (base_reg != (int) REGNO (reg))
910- /* Not addressed from the same base register. */
911+ base_reg_rtx = reg;
912+ if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
913 return 0;
914-
915- unsorted_regs[i] = (GET_CODE (operands[i]) == REG
916- ? REGNO (operands[i])
917- : REGNO (SUBREG_REG (operands[i])));
918- if (unsorted_regs[i] < unsorted_regs[order[0]])
919- order[0] = i;
920 }
921+ else if (base_reg != (int) REGNO (reg))
922+ /* Not addressed from the same base register. */
923+ return 0;
924
925 /* If it isn't an integer register, then we can't do this. */
926- if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
927+ if (unsorted_regs[i] < 0
928+ || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM)
929+ || (TARGET_THUMB2 && unsorted_regs[i] == base_reg)
930+ || (TARGET_THUMB2 && unsorted_regs[i] == SP_REGNUM)
931+ || unsorted_regs[i] > 14)
932 return 0;
933
934 unsorted_offsets[i] = INTVAL (offset);
935+ if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]])
936+ order[0] = i;
937 }
938 else
939 /* Not a suitable memory address. */
940@@ -9998,111 +10026,65 @@ store_multiple_sequence (rtx *operands,
941
942 /* All the useful information has now been extracted from the
943 operands into unsorted_regs and unsorted_offsets; additionally,
944- order[0] has been set to the lowest numbered register in the
945- list. Sort the registers into order, and check that the memory
946- offsets are ascending and adjacent. */
947-
948- for (i = 1; i < nops; i++)
949- {
950- int j;
951-
952- order[i] = order[i - 1];
953- for (j = 0; j < nops; j++)
954- if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
955- && (order[i] == order[i - 1]
956- || unsorted_regs[j] < unsorted_regs[order[i]]))
957- order[i] = j;
958-
959- /* Have we found a suitable register? if not, one must be used more
960- than once. */
961- if (order[i] == order[i - 1])
962- return 0;
963+ order[0] has been set to the lowest offset in the list. Sort
964+ the offsets into order, verifying that they are adjacent, and
965+ check that the register numbers are ascending. */
966+ if (!compute_offset_order (nops, unsorted_offsets, order,
967+ check_regs ? unsorted_regs : NULL))
968+ return 0;
969
970- /* Is the memory address adjacent and ascending? */
971- if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
972- return 0;
973- }
974+ if (saved_order)
975+ memcpy (saved_order, order, sizeof order);
976
977 if (base)
978 {
979 *base = base_reg;
980
981 for (i = 0; i < nops; i++)
982- regs[i] = unsorted_regs[order[i]];
983+ {
984+ regs[i] = unsorted_regs[check_regs ? order[i] : i];
985+ if (reg_rtxs)
986+ reg_rtxs[i] = unsorted_reg_rtxs[check_regs ? order[i] : i];
987+ }
988
989 *load_offset = unsorted_offsets[order[0]];
990 }
991
992- if (unsorted_offsets[order[0]] == 0)
993- return 1; /* stmia */
994-
995- if (unsorted_offsets[order[0]] == 4)
996- return 2; /* stmib */
997-
998- if (unsorted_offsets[order[nops - 1]] == 0)
999- return 3; /* stmda */
1000-
1001- if (unsorted_offsets[order[nops - 1]] == -4)
1002- return 4; /* stmdb */
1003-
1004- return 0;
1005-}
1006-
1007-const char *
1008-emit_stm_seq (rtx *operands, int nops)
1009-{
1010- int regs[4];
1011- int base_reg;
1012- HOST_WIDE_INT offset;
1013- char buf[100];
1014- int i;
1015-
1016- switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
1017- {
1018- case 1:
1019- strcpy (buf, "stm%(ia%)\t");
1020- break;
1021-
1022- case 2:
1023- strcpy (buf, "stm%(ib%)\t");
1024- break;
1025-
1026- case 3:
1027- strcpy (buf, "stm%(da%)\t");
1028- break;
1029-
1030- case 4:
1031- strcpy (buf, "stm%(db%)\t");
1032- break;
1033-
1034- default:
1035- gcc_unreachable ();
1036- }
1037-
1038- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
1039- reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
1040+ if (TARGET_THUMB1
1041+ && !peep2_reg_dead_p (nops_total, base_reg_rtx))
1042+ return 0;
1043
1044- for (i = 1; i < nops; i++)
1045- sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
1046- reg_names[regs[i]]);
1047+ if (unsorted_offsets[order[0]] == 0)
1048+ stm_case = 1; /* stmia */
1049+ else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
1050+ stm_case = 2; /* stmib */
1051+ else if (TARGET_ARM && unsorted_offsets[order[nops - 1]] == 0)
1052+ stm_case = 3; /* stmda */
1053+ else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
1054+ stm_case = 4; /* stmdb */
1055+ else
1056+ return 0;
1057
1058- strcat (buf, "}\t%@ phole stm");
1059+ if (!multiple_operation_profitable_p (false, nops, 0))
1060+ return 0;
1061
1062- output_asm_insn (buf, operands);
1063- return "";
1064+ return stm_case;
1065 }
1066
1067 /* Routines for use in generating RTL. */
1068
1069-rtx
1070-arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
1071- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1072+/* Generate a load-multiple instruction. COUNT is the number of loads in
1073+ the instruction; REGS and MEMS are arrays containing the operands.
1074+ BASEREG is the base register to be used in addressing the memory operands.
1075+ WBACK_OFFSET is nonzero if the instruction should update the base
1076+ register. */
1077+
1078+static rtx
1079+arm_gen_load_multiple_1 (int count, int *regs, rtx *mems, rtx basereg,
1080+ HOST_WIDE_INT wback_offset)
1081 {
1082- HOST_WIDE_INT offset = *offsetp;
1083 int i = 0, j;
1084 rtx result;
1085- int sign = up ? 1 : -1;
1086- rtx mem, addr;
1087
1088 /* XScale has load-store double instructions, but they have stricter
1089 alignment requirements than load-store multiple, so we cannot
1090@@ -10139,18 +10121,10 @@ arm_gen_load_multiple (int base_regno, i
1091 start_sequence ();
1092
1093 for (i = 0; i < count; i++)
1094- {
1095- addr = plus_constant (from, i * 4 * sign);
1096- mem = adjust_automodify_address (basemem, SImode, addr, offset);
1097- emit_move_insn (gen_rtx_REG (SImode, base_regno + i), mem);
1098- offset += 4 * sign;
1099- }
1100+ emit_move_insn (gen_rtx_REG (SImode, regs[i]), mems[i]);
1101
1102- if (write_back)
1103- {
1104- emit_move_insn (from, plus_constant (from, count * 4 * sign));
1105- *offsetp = offset;
1106- }
1107+ if (wback_offset != 0)
1108+ emit_move_insn (basereg, plus_constant (basereg, wback_offset));
1109
1110 seq = get_insns ();
1111 end_sequence ();
1112@@ -10159,41 +10133,40 @@ arm_gen_load_multiple (int base_regno, i
1113 }
1114
1115 result = gen_rtx_PARALLEL (VOIDmode,
1116- rtvec_alloc (count + (write_back ? 1 : 0)));
1117- if (write_back)
1118+ rtvec_alloc (count + (wback_offset != 0 ? 1 : 0)));
1119+ if (wback_offset != 0)
1120 {
1121 XVECEXP (result, 0, 0)
1122- = gen_rtx_SET (VOIDmode, from, plus_constant (from, count * 4 * sign));
1123+ = gen_rtx_SET (VOIDmode, basereg,
1124+ plus_constant (basereg, wback_offset));
1125 i = 1;
1126 count++;
1127 }
1128
1129 for (j = 0; i < count; i++, j++)
1130- {
1131- addr = plus_constant (from, j * 4 * sign);
1132- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1133- XVECEXP (result, 0, i)
1134- = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, base_regno + j), mem);
1135- offset += 4 * sign;
1136- }
1137-
1138- if (write_back)
1139- *offsetp = offset;
1140+ XVECEXP (result, 0, i)
1141+ = gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, regs[j]), mems[j]);
1142
1143 return result;
1144 }
1145
1146-rtx
1147-arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
1148- int write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1149+/* Generate a store-multiple instruction. COUNT is the number of stores in
1150+ the instruction; REGS and MEMS are arrays containing the operands.
1151+ BASEREG is the base register to be used in addressing the memory operands.
1152+ WBACK_OFFSET is nonzero if the instruction should update the base
1153+ register. */
1154+
1155+static rtx
1156+arm_gen_store_multiple_1 (int count, int *regs, rtx *mems, rtx basereg,
1157+ HOST_WIDE_INT wback_offset)
1158 {
1159- HOST_WIDE_INT offset = *offsetp;
1160 int i = 0, j;
1161 rtx result;
1162- int sign = up ? 1 : -1;
1163- rtx mem, addr;
1164
1165- /* See arm_gen_load_multiple for discussion of
1166+ if (GET_CODE (basereg) == PLUS)
1167+ basereg = XEXP (basereg, 0);
1168+
1169+ /* See arm_gen_load_multiple_1 for discussion of
1170 the pros/cons of ldm/stm usage for XScale. */
1171 if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size))
1172 {
1173@@ -10202,18 +10175,10 @@ arm_gen_store_multiple (int base_regno,
1174 start_sequence ();
1175
1176 for (i = 0; i < count; i++)
1177- {
1178- addr = plus_constant (to, i * 4 * sign);
1179- mem = adjust_automodify_address (basemem, SImode, addr, offset);
1180- emit_move_insn (mem, gen_rtx_REG (SImode, base_regno + i));
1181- offset += 4 * sign;
1182- }
1183+ emit_move_insn (mems[i], gen_rtx_REG (SImode, regs[i]));
1184
1185- if (write_back)
1186- {
1187- emit_move_insn (to, plus_constant (to, count * 4 * sign));
1188- *offsetp = offset;
1189- }
1190+ if (wback_offset != 0)
1191+ emit_move_insn (basereg, plus_constant (basereg, wback_offset));
1192
1193 seq = get_insns ();
1194 end_sequence ();
1195@@ -10222,29 +10187,319 @@ arm_gen_store_multiple (int base_regno,
1196 }
1197
1198 result = gen_rtx_PARALLEL (VOIDmode,
1199- rtvec_alloc (count + (write_back ? 1 : 0)));
1200- if (write_back)
1201+ rtvec_alloc (count + (wback_offset != 0 ? 1 : 0)));
1202+ if (wback_offset != 0)
1203 {
1204 XVECEXP (result, 0, 0)
1205- = gen_rtx_SET (VOIDmode, to,
1206- plus_constant (to, count * 4 * sign));
1207+ = gen_rtx_SET (VOIDmode, basereg,
1208+ plus_constant (basereg, wback_offset));
1209 i = 1;
1210 count++;
1211 }
1212
1213 for (j = 0; i < count; i++, j++)
1214+ XVECEXP (result, 0, i)
1215+ = gen_rtx_SET (VOIDmode, mems[j], gen_rtx_REG (SImode, regs[j]));
1216+
1217+ return result;
1218+}
1219+
1220+/* Generate either a load-multiple or a store-multiple instruction. This
1221+ function can be used in situations where we can start with a single MEM
1222+ rtx and adjust its address upwards.
1223+ COUNT is the number of operations in the instruction, not counting a
1224+ possible update of the base register. REGS is an array containing the
1225+ register operands.
1226+ BASEREG is the base register to be used in addressing the memory operands,
1227+ which are constructed from BASEMEM.
1228+ WRITE_BACK specifies whether the generated instruction should include an
1229+ update of the base register.
1230+ OFFSETP is used to pass an offset to and from this function; this offset
1231+ is not used when constructing the address (instead BASEMEM should have an
1232+ appropriate offset in its address), it is used only for setting
1233+ MEM_OFFSET. It is updated only if WRITE_BACK is true.*/
1234+
1235+static rtx
1236+arm_gen_multiple_op (bool is_load, int *regs, int count, rtx basereg,
1237+ bool write_back, rtx basemem, HOST_WIDE_INT *offsetp)
1238+{
1239+ rtx mems[MAX_LDM_STM_OPS];
1240+ HOST_WIDE_INT offset = *offsetp;
1241+ int i;
1242+
1243+ gcc_assert (count <= MAX_LDM_STM_OPS);
1244+
1245+ if (GET_CODE (basereg) == PLUS)
1246+ basereg = XEXP (basereg, 0);
1247+
1248+ for (i = 0; i < count; i++)
1249 {
1250- addr = plus_constant (to, j * 4 * sign);
1251- mem = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1252- XVECEXP (result, 0, i)
1253- = gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (SImode, base_regno + j));
1254- offset += 4 * sign;
1255+ rtx addr = plus_constant (basereg, i * 4);
1256+ mems[i] = adjust_automodify_address_nv (basemem, SImode, addr, offset);
1257+ offset += 4;
1258 }
1259
1260 if (write_back)
1261 *offsetp = offset;
1262
1263- return result;
1264+ if (is_load)
1265+ return arm_gen_load_multiple_1 (count, regs, mems, basereg,
1266+ write_back ? 4 * count : 0);
1267+ else
1268+ return arm_gen_store_multiple_1 (count, regs, mems, basereg,
1269+ write_back ? 4 * count : 0);
1270+}
1271+
1272+rtx
1273+arm_gen_load_multiple (int *regs, int count, rtx basereg, int write_back,
1274+ rtx basemem, HOST_WIDE_INT *offsetp)
1275+{
1276+ return arm_gen_multiple_op (TRUE, regs, count, basereg, write_back, basemem,
1277+ offsetp);
1278+}
1279+
1280+rtx
1281+arm_gen_store_multiple (int *regs, int count, rtx basereg, int write_back,
1282+ rtx basemem, HOST_WIDE_INT *offsetp)
1283+{
1284+ return arm_gen_multiple_op (FALSE, regs, count, basereg, write_back, basemem,
1285+ offsetp);
1286+}
1287+
1288+/* Called from a peephole2 expander to turn a sequence of loads into an
1289+ LDM instruction. OPERANDS are the operands found by the peephole matcher;
1290+ NOPS indicates how many separate loads we are trying to combine. SORT_REGS
1291+ is true if we can reorder the registers because they are used commutatively
1292+ subsequently.
1293+ Returns true iff we could generate a new instruction. */
1294+
1295+bool
1296+gen_ldm_seq (rtx *operands, int nops, bool sort_regs)
1297+{
1298+ int regs[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1299+ rtx mems[MAX_LDM_STM_OPS];
1300+ int i, j, base_reg;
1301+ rtx base_reg_rtx;
1302+ HOST_WIDE_INT offset;
1303+ int write_back = FALSE;
1304+ int ldm_case;
1305+ rtx addr;
1306+
1307+ ldm_case = load_multiple_sequence (operands, nops, regs, mem_order,
1308+ &base_reg, &offset, !sort_regs);
1309+
1310+ if (ldm_case == 0)
1311+ return false;
1312+
1313+ if (sort_regs)
1314+ for (i = 0; i < nops - 1; i++)
1315+ for (j = i + 1; j < nops; j++)
1316+ if (regs[i] > regs[j])
1317+ {
1318+ int t = regs[i];
1319+ regs[i] = regs[j];
1320+ regs[j] = t;
1321+ }
1322+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1323+
1324+ if (TARGET_THUMB1)
1325+ {
1326+ gcc_assert (peep2_reg_dead_p (nops, base_reg_rtx));
1327+ gcc_assert (ldm_case == 1 || ldm_case == 5);
1328+ write_back = TRUE;
1329+ }
1330+
1331+ if (ldm_case == 5)
1332+ {
1333+ rtx newbase = TARGET_THUMB1 ? base_reg_rtx : gen_rtx_REG (SImode, regs[0]);
1334+ emit_insn (gen_addsi3 (newbase, base_reg_rtx, GEN_INT (offset)));
1335+ offset = 0;
1336+ if (!TARGET_THUMB1)
1337+ {
1338+ base_reg = regs[0];
1339+ base_reg_rtx = newbase;
1340+ }
1341+ }
1342+
1343+ for (i = 0; i < nops; i++)
1344+ {
1345+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1346+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1347+ SImode, addr, 0);
1348+ }
1349+ emit_insn (arm_gen_load_multiple_1 (nops, regs, mems, base_reg_rtx,
1350+ write_back ? offset + i * 4 : 0));
1351+ return true;
1352+}
1353+
1354+/* Called from a peephole2 expander to turn a sequence of stores into an
1355+ STM instruction. OPERANDS are the operands found by the peephole matcher;
1356+ NOPS indicates how many separate stores we are trying to combine.
1357+ Returns true iff we could generate a new instruction. */
1358+
1359+bool
1360+gen_stm_seq (rtx *operands, int nops)
1361+{
1362+ int i;
1363+ int regs[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1364+ rtx mems[MAX_LDM_STM_OPS];
1365+ int base_reg;
1366+ rtx base_reg_rtx;
1367+ HOST_WIDE_INT offset;
1368+ int write_back = FALSE;
1369+ int stm_case;
1370+ rtx addr;
1371+ bool base_reg_dies;
1372+
1373+ stm_case = store_multiple_sequence (operands, nops, nops, regs, NULL,
1374+ mem_order, &base_reg, &offset, true);
1375+
1376+ if (stm_case == 0)
1377+ return false;
1378+
1379+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1380+
1381+ base_reg_dies = peep2_reg_dead_p (nops, base_reg_rtx);
1382+ if (TARGET_THUMB1)
1383+ {
1384+ gcc_assert (base_reg_dies);
1385+ write_back = TRUE;
1386+ }
1387+
1388+ if (stm_case == 5)
1389+ {
1390+ gcc_assert (base_reg_dies);
1391+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, GEN_INT (offset)));
1392+ offset = 0;
1393+ }
1394+
1395+ addr = plus_constant (base_reg_rtx, offset);
1396+
1397+ for (i = 0; i < nops; i++)
1398+ {
1399+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1400+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1401+ SImode, addr, 0);
1402+ }
1403+ emit_insn (arm_gen_store_multiple_1 (nops, regs, mems, base_reg_rtx,
1404+ write_back ? offset + i * 4 : 0));
1405+ return true;
1406+}
1407+
1408+/* Called from a peephole2 expander to turn a sequence of stores that are
1409+ preceded by constant loads into an STM instruction. OPERANDS are the
1410+ operands found by the peephole matcher; NOPS indicates how many
1411+ separate stores we are trying to combine; there are 2 * NOPS
1412+ instructions in the peephole.
1413+ Returns true iff we could generate a new instruction. */
1414+
1415+bool
1416+gen_const_stm_seq (rtx *operands, int nops)
1417+{
1418+ int regs[MAX_LDM_STM_OPS], sorted_regs[MAX_LDM_STM_OPS];
1419+ int reg_order[MAX_LDM_STM_OPS], mem_order[MAX_LDM_STM_OPS];
1420+ rtx reg_rtxs[MAX_LDM_STM_OPS], orig_reg_rtxs[MAX_LDM_STM_OPS];
1421+ rtx mems[MAX_LDM_STM_OPS];
1422+ int base_reg;
1423+ rtx base_reg_rtx;
1424+ HOST_WIDE_INT offset;
1425+ int write_back = FALSE;
1426+ int stm_case;
1427+ rtx addr;
1428+ bool base_reg_dies;
1429+ int i, j;
1430+ HARD_REG_SET allocated;
1431+
1432+ stm_case = store_multiple_sequence (operands, nops, 2 * nops, regs, reg_rtxs,
1433+ mem_order, &base_reg, &offset, false);
1434+
1435+ if (stm_case == 0)
1436+ return false;
1437+
1438+ memcpy (orig_reg_rtxs, reg_rtxs, sizeof orig_reg_rtxs);
1439+
1440+ /* If the same register is used more than once, try to find a free
1441+ register. */
1442+ CLEAR_HARD_REG_SET (allocated);
1443+ for (i = 0; i < nops; i++)
1444+ {
1445+ for (j = i + 1; j < nops; j++)
1446+ if (regs[i] == regs[j])
1447+ {
1448+ rtx t = peep2_find_free_register (0, nops * 2,
1449+ TARGET_THUMB1 ? "l" : "r",
1450+ SImode, &allocated);
1451+ if (t == NULL_RTX)
1452+ return false;
1453+ reg_rtxs[i] = t;
1454+ regs[i] = REGNO (t);
1455+ }
1456+ }
1457+
1458+ /* Compute an ordering that maps the register numbers to an ascending
1459+ sequence. */
1460+ reg_order[0] = 0;
1461+ for (i = 0; i < nops; i++)
1462+ if (regs[i] < regs[reg_order[0]])
1463+ reg_order[0] = i;
1464+
1465+ for (i = 1; i < nops; i++)
1466+ {
1467+ int this_order = reg_order[i - 1];
1468+ for (j = 0; j < nops; j++)
1469+ if (regs[j] > regs[reg_order[i - 1]]
1470+ && (this_order == reg_order[i - 1]
1471+ || regs[j] < regs[this_order]))
1472+ this_order = j;
1473+ reg_order[i] = this_order;
1474+ }
1475+
1476+ /* Ensure that registers that must be live after the instruction end
1477+ up with the correct value. */
1478+ for (i = 0; i < nops; i++)
1479+ {
1480+ int this_order = reg_order[i];
1481+ if ((this_order != mem_order[i]
1482+ || orig_reg_rtxs[this_order] != reg_rtxs[this_order])
1483+ && !peep2_reg_dead_p (nops * 2, orig_reg_rtxs[this_order]))
1484+ return false;
1485+ }
1486+
1487+ /* Load the constants. */
1488+ for (i = 0; i < nops; i++)
1489+ {
1490+ rtx op = operands[2 * nops + mem_order[i]];
1491+ sorted_regs[i] = regs[reg_order[i]];
1492+ emit_move_insn (reg_rtxs[reg_order[i]], op);
1493+ }
1494+
1495+ base_reg_rtx = gen_rtx_REG (Pmode, base_reg);
1496+
1497+ base_reg_dies = peep2_reg_dead_p (nops * 2, base_reg_rtx);
1498+ if (TARGET_THUMB1)
1499+ {
1500+ gcc_assert (base_reg_dies);
1501+ write_back = TRUE;
1502+ }
1503+
1504+ if (stm_case == 5)
1505+ {
1506+ gcc_assert (base_reg_dies);
1507+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, GEN_INT (offset)));
1508+ offset = 0;
1509+ }
1510+
1511+ addr = plus_constant (base_reg_rtx, offset);
1512+
1513+ for (i = 0; i < nops; i++)
1514+ {
1515+ addr = plus_constant (base_reg_rtx, offset + i * 4);
1516+ mems[i] = adjust_automodify_address_nv (operands[nops + mem_order[i]],
1517+ SImode, addr, 0);
1518+ }
1519+ emit_insn (arm_gen_store_multiple_1 (nops, sorted_regs, mems, base_reg_rtx,
1520+ write_back ? offset + i * 4 : 0));
1521+ return true;
1522 }
1523
1524 int
1525@@ -10280,20 +10535,21 @@ arm_gen_movmemqi (rtx *operands)
1526 for (i = 0; in_words_to_go >= 2; i+=4)
1527 {
1528 if (in_words_to_go > 4)
1529- emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
1530- srcbase, &srcoffset));
1531+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, src,
1532+ TRUE, srcbase, &srcoffset));
1533 else
1534- emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
1535- FALSE, srcbase, &srcoffset));
1536+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, in_words_to_go,
1537+ src, FALSE, srcbase,
1538+ &srcoffset));
1539
1540 if (out_words_to_go)
1541 {
1542 if (out_words_to_go > 4)
1543- emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
1544- dstbase, &dstoffset));
1545+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, dst,
1546+ TRUE, dstbase, &dstoffset));
1547 else if (out_words_to_go != 1)
1548- emit_insn (arm_gen_store_multiple (0, out_words_to_go,
1549- dst, TRUE,
1550+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence,
1551+ out_words_to_go, dst,
1552 (last_bytes == 0
1553 ? FALSE : TRUE),
1554 dstbase, &dstoffset));
1555Index: gcc-4_5-branch/gcc/config/arm/arm.h
1556===================================================================
1557--- gcc-4_5-branch.orig/gcc/config/arm/arm.h
1558+++ gcc-4_5-branch/gcc/config/arm/arm.h
1559@@ -1143,6 +1143,9 @@ extern int arm_structure_size_boundary;
1560 ((MODE) == TImode || (MODE) == EImode || (MODE) == OImode \
1561 || (MODE) == CImode || (MODE) == XImode)
1562
1563+/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
1564+extern int arm_regs_in_sequence[];
1565+
1566 /* The order in which register should be allocated. It is good to use ip
1567 since no saving is required (though calls clobber it) and it never contains
1568 function parameters. It is quite good to use lr since other calls may
1569@@ -2823,4 +2826,8 @@ enum arm_builtins
1570 #define NEED_INDICATE_EXEC_STACK 0
1571 #endif
1572
1573+/* The maximum number of parallel loads or stores we support in an ldm/stm
1574+ instruction. */
1575+#define MAX_LDM_STM_OPS 4
1576+
1577 #endif /* ! GCC_ARM_H */
1578Index: gcc-4_5-branch/gcc/config/arm/arm.md
1579===================================================================
1580--- gcc-4_5-branch.orig/gcc/config/arm/arm.md
1581+++ gcc-4_5-branch/gcc/config/arm/arm.md
1582@@ -6282,7 +6282,7 @@
1583
1584 ;; load- and store-multiple insns
1585 ;; The arm can load/store any set of registers, provided that they are in
1586-;; ascending order; but that is beyond GCC so stick with what it knows.
1587+;; ascending order, but these expanders assume a contiguous set.
1588
1589 (define_expand "load_multiple"
1590 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
1591@@ -6303,126 +6303,12 @@
1592 FAIL;
1593
1594 operands[3]
1595- = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
1596+ = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
1597+ INTVAL (operands[2]),
1598 force_reg (SImode, XEXP (operands[1], 0)),
1599- TRUE, FALSE, operands[1], &offset);
1600+ FALSE, operands[1], &offset);
1601 })
1602
1603-;; Load multiple with write-back
1604-
1605-(define_insn "*ldmsi_postinc4"
1606- [(match_parallel 0 "load_multiple_operation"
1607- [(set (match_operand:SI 1 "s_register_operand" "=r")
1608- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1609- (const_int 16)))
1610- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1611- (mem:SI (match_dup 2)))
1612- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1613- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1614- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1615- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
1616- (set (match_operand:SI 6 "arm_hard_register_operand" "")
1617- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
1618- "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
1619- "ldm%(ia%)\\t%1!, {%3, %4, %5, %6}"
1620- [(set_attr "type" "load4")
1621- (set_attr "predicable" "yes")]
1622-)
1623-
1624-(define_insn "*ldmsi_postinc4_thumb1"
1625- [(match_parallel 0 "load_multiple_operation"
1626- [(set (match_operand:SI 1 "s_register_operand" "=l")
1627- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1628- (const_int 16)))
1629- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1630- (mem:SI (match_dup 2)))
1631- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1632- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1633- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1634- (mem:SI (plus:SI (match_dup 2) (const_int 8))))
1635- (set (match_operand:SI 6 "arm_hard_register_operand" "")
1636- (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
1637- "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
1638- "ldmia\\t%1!, {%3, %4, %5, %6}"
1639- [(set_attr "type" "load4")]
1640-)
1641-
1642-(define_insn "*ldmsi_postinc3"
1643- [(match_parallel 0 "load_multiple_operation"
1644- [(set (match_operand:SI 1 "s_register_operand" "=r")
1645- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1646- (const_int 12)))
1647- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1648- (mem:SI (match_dup 2)))
1649- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1650- (mem:SI (plus:SI (match_dup 2) (const_int 4))))
1651- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1652- (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
1653- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1654- "ldm%(ia%)\\t%1!, {%3, %4, %5}"
1655- [(set_attr "type" "load3")
1656- (set_attr "predicable" "yes")]
1657-)
1658-
1659-(define_insn "*ldmsi_postinc2"
1660- [(match_parallel 0 "load_multiple_operation"
1661- [(set (match_operand:SI 1 "s_register_operand" "=r")
1662- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1663- (const_int 8)))
1664- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1665- (mem:SI (match_dup 2)))
1666- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1667- (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
1668- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1669- "ldm%(ia%)\\t%1!, {%3, %4}"
1670- [(set_attr "type" "load2")
1671- (set_attr "predicable" "yes")]
1672-)
1673-
1674-;; Ordinary load multiple
1675-
1676-(define_insn "*ldmsi4"
1677- [(match_parallel 0 "load_multiple_operation"
1678- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1679- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1680- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1681- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
1682- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1683- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
1684- (set (match_operand:SI 5 "arm_hard_register_operand" "")
1685- (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
1686- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1687- "ldm%(ia%)\\t%1, {%2, %3, %4, %5}"
1688- [(set_attr "type" "load4")
1689- (set_attr "predicable" "yes")]
1690-)
1691-
1692-(define_insn "*ldmsi3"
1693- [(match_parallel 0 "load_multiple_operation"
1694- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1695- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1696- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1697- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
1698- (set (match_operand:SI 4 "arm_hard_register_operand" "")
1699- (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
1700- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1701- "ldm%(ia%)\\t%1, {%2, %3, %4}"
1702- [(set_attr "type" "load3")
1703- (set_attr "predicable" "yes")]
1704-)
1705-
1706-(define_insn "*ldmsi2"
1707- [(match_parallel 0 "load_multiple_operation"
1708- [(set (match_operand:SI 2 "arm_hard_register_operand" "")
1709- (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
1710- (set (match_operand:SI 3 "arm_hard_register_operand" "")
1711- (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
1712- "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
1713- "ldm%(ia%)\\t%1, {%2, %3}"
1714- [(set_attr "type" "load2")
1715- (set_attr "predicable" "yes")]
1716-)
1717-
1718 (define_expand "store_multiple"
1719 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
1720 (match_operand:SI 1 "" ""))
1721@@ -6442,125 +6328,12 @@
1722 FAIL;
1723
1724 operands[3]
1725- = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
1726+ = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
1727+ INTVAL (operands[2]),
1728 force_reg (SImode, XEXP (operands[0], 0)),
1729- TRUE, FALSE, operands[0], &offset);
1730+ FALSE, operands[0], &offset);
1731 })
1732
1733-;; Store multiple with write-back
1734-
1735-(define_insn "*stmsi_postinc4"
1736- [(match_parallel 0 "store_multiple_operation"
1737- [(set (match_operand:SI 1 "s_register_operand" "=r")
1738- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1739- (const_int 16)))
1740- (set (mem:SI (match_dup 2))
1741- (match_operand:SI 3 "arm_hard_register_operand" ""))
1742- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1743- (match_operand:SI 4 "arm_hard_register_operand" ""))
1744- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1745- (match_operand:SI 5 "arm_hard_register_operand" ""))
1746- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
1747- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
1748- "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
1749- "stm%(ia%)\\t%1!, {%3, %4, %5, %6}"
1750- [(set_attr "predicable" "yes")
1751- (set_attr "type" "store4")]
1752-)
1753-
1754-(define_insn "*stmsi_postinc4_thumb1"
1755- [(match_parallel 0 "store_multiple_operation"
1756- [(set (match_operand:SI 1 "s_register_operand" "=l")
1757- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1758- (const_int 16)))
1759- (set (mem:SI (match_dup 2))
1760- (match_operand:SI 3 "arm_hard_register_operand" ""))
1761- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1762- (match_operand:SI 4 "arm_hard_register_operand" ""))
1763- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1764- (match_operand:SI 5 "arm_hard_register_operand" ""))
1765- (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
1766- (match_operand:SI 6 "arm_hard_register_operand" ""))])]
1767- "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
1768- "stmia\\t%1!, {%3, %4, %5, %6}"
1769- [(set_attr "type" "store4")]
1770-)
1771-
1772-(define_insn "*stmsi_postinc3"
1773- [(match_parallel 0 "store_multiple_operation"
1774- [(set (match_operand:SI 1 "s_register_operand" "=r")
1775- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1776- (const_int 12)))
1777- (set (mem:SI (match_dup 2))
1778- (match_operand:SI 3 "arm_hard_register_operand" ""))
1779- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1780- (match_operand:SI 4 "arm_hard_register_operand" ""))
1781- (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
1782- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
1783- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1784- "stm%(ia%)\\t%1!, {%3, %4, %5}"
1785- [(set_attr "predicable" "yes")
1786- (set_attr "type" "store3")]
1787-)
1788-
1789-(define_insn "*stmsi_postinc2"
1790- [(match_parallel 0 "store_multiple_operation"
1791- [(set (match_operand:SI 1 "s_register_operand" "=r")
1792- (plus:SI (match_operand:SI 2 "s_register_operand" "1")
1793- (const_int 8)))
1794- (set (mem:SI (match_dup 2))
1795- (match_operand:SI 3 "arm_hard_register_operand" ""))
1796- (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
1797- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
1798- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1799- "stm%(ia%)\\t%1!, {%3, %4}"
1800- [(set_attr "predicable" "yes")
1801- (set_attr "type" "store2")]
1802-)
1803-
1804-;; Ordinary store multiple
1805-
1806-(define_insn "*stmsi4"
1807- [(match_parallel 0 "store_multiple_operation"
1808- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1809- (match_operand:SI 2 "arm_hard_register_operand" ""))
1810- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1811- (match_operand:SI 3 "arm_hard_register_operand" ""))
1812- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
1813- (match_operand:SI 4 "arm_hard_register_operand" ""))
1814- (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
1815- (match_operand:SI 5 "arm_hard_register_operand" ""))])]
1816- "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
1817- "stm%(ia%)\\t%1, {%2, %3, %4, %5}"
1818- [(set_attr "predicable" "yes")
1819- (set_attr "type" "store4")]
1820-)
1821-
1822-(define_insn "*stmsi3"
1823- [(match_parallel 0 "store_multiple_operation"
1824- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1825- (match_operand:SI 2 "arm_hard_register_operand" ""))
1826- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1827- (match_operand:SI 3 "arm_hard_register_operand" ""))
1828- (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
1829- (match_operand:SI 4 "arm_hard_register_operand" ""))])]
1830- "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
1831- "stm%(ia%)\\t%1, {%2, %3, %4}"
1832- [(set_attr "predicable" "yes")
1833- (set_attr "type" "store3")]
1834-)
1835-
1836-(define_insn "*stmsi2"
1837- [(match_parallel 0 "store_multiple_operation"
1838- [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
1839- (match_operand:SI 2 "arm_hard_register_operand" ""))
1840- (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
1841- (match_operand:SI 3 "arm_hard_register_operand" ""))])]
1842- "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
1843- "stm%(ia%)\\t%1, {%2, %3}"
1844- [(set_attr "predicable" "yes")
1845- (set_attr "type" "store2")]
1846-)
1847
1848 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
1849 ;; We could let this apply for blocks of less than this, but it clobbers so
1850@@ -9031,8 +8804,8 @@
1851 if (REGNO (reg) == R0_REGNUM)
1852 {
1853 /* On thumb we have to use a write-back instruction. */
1854- emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
1855- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1856+ emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
1857+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1858 size = TARGET_ARM ? 16 : 0;
1859 }
1860 else
1861@@ -9078,8 +8851,8 @@
1862 if (REGNO (reg) == R0_REGNUM)
1863 {
1864 /* On thumb we have to use a write-back instruction. */
1865- emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
1866- TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1867+ emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
1868+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1869 size = TARGET_ARM ? 16 : 0;
1870 }
1871 else
1872@@ -10672,87 +10445,6 @@
1873 ""
1874 )
1875
1876-; Peepholes to spot possible load- and store-multiples, if the ordering is
1877-; reversed, check that the memory references aren't volatile.
1878-
1879-(define_peephole
1880- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1881- (match_operand:SI 4 "memory_operand" "m"))
1882- (set (match_operand:SI 1 "s_register_operand" "=rk")
1883- (match_operand:SI 5 "memory_operand" "m"))
1884- (set (match_operand:SI 2 "s_register_operand" "=rk")
1885- (match_operand:SI 6 "memory_operand" "m"))
1886- (set (match_operand:SI 3 "s_register_operand" "=rk")
1887- (match_operand:SI 7 "memory_operand" "m"))]
1888- "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
1889- "*
1890- return emit_ldm_seq (operands, 4);
1891- "
1892-)
1893-
1894-(define_peephole
1895- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1896- (match_operand:SI 3 "memory_operand" "m"))
1897- (set (match_operand:SI 1 "s_register_operand" "=rk")
1898- (match_operand:SI 4 "memory_operand" "m"))
1899- (set (match_operand:SI 2 "s_register_operand" "=rk")
1900- (match_operand:SI 5 "memory_operand" "m"))]
1901- "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
1902- "*
1903- return emit_ldm_seq (operands, 3);
1904- "
1905-)
1906-
1907-(define_peephole
1908- [(set (match_operand:SI 0 "s_register_operand" "=rk")
1909- (match_operand:SI 2 "memory_operand" "m"))
1910- (set (match_operand:SI 1 "s_register_operand" "=rk")
1911- (match_operand:SI 3 "memory_operand" "m"))]
1912- "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
1913- "*
1914- return emit_ldm_seq (operands, 2);
1915- "
1916-)
1917-
1918-(define_peephole
1919- [(set (match_operand:SI 4 "memory_operand" "=m")
1920- (match_operand:SI 0 "s_register_operand" "rk"))
1921- (set (match_operand:SI 5 "memory_operand" "=m")
1922- (match_operand:SI 1 "s_register_operand" "rk"))
1923- (set (match_operand:SI 6 "memory_operand" "=m")
1924- (match_operand:SI 2 "s_register_operand" "rk"))
1925- (set (match_operand:SI 7 "memory_operand" "=m")
1926- (match_operand:SI 3 "s_register_operand" "rk"))]
1927- "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
1928- "*
1929- return emit_stm_seq (operands, 4);
1930- "
1931-)
1932-
1933-(define_peephole
1934- [(set (match_operand:SI 3 "memory_operand" "=m")
1935- (match_operand:SI 0 "s_register_operand" "rk"))
1936- (set (match_operand:SI 4 "memory_operand" "=m")
1937- (match_operand:SI 1 "s_register_operand" "rk"))
1938- (set (match_operand:SI 5 "memory_operand" "=m")
1939- (match_operand:SI 2 "s_register_operand" "rk"))]
1940- "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
1941- "*
1942- return emit_stm_seq (operands, 3);
1943- "
1944-)
1945-
1946-(define_peephole
1947- [(set (match_operand:SI 2 "memory_operand" "=m")
1948- (match_operand:SI 0 "s_register_operand" "rk"))
1949- (set (match_operand:SI 3 "memory_operand" "=m")
1950- (match_operand:SI 1 "s_register_operand" "rk"))]
1951- "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
1952- "*
1953- return emit_stm_seq (operands, 2);
1954- "
1955-)
1956-
1957 (define_split
1958 [(set (match_operand:SI 0 "s_register_operand" "")
1959 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
1960@@ -11554,6 +11246,8 @@
1961 "
1962 )
1963
1964+;; Load the load/store multiple patterns
1965+(include "ldmstm.md")
1966 ;; Load the FPA co-processor patterns
1967 (include "fpa.md")
1968 ;; Load the Maverick co-processor patterns
1969Index: gcc-4_5-branch/gcc/config/arm/ldmstm.md
1970===================================================================
1971--- /dev/null
1972+++ gcc-4_5-branch/gcc/config/arm/ldmstm.md
1973@@ -0,0 +1,1191 @@
1974+/* ARM ldm/stm instruction patterns. This file was automatically generated
1975+ using arm-ldmstm.ml. Please do not edit manually.
1976+
1977+ Copyright (C) 2010 Free Software Foundation, Inc.
1978+ Contributed by CodeSourcery.
1979+
1980+ This file is part of GCC.
1981+
1982+ GCC is free software; you can redistribute it and/or modify it
1983+ under the terms of the GNU General Public License as published
1984+ by the Free Software Foundation; either version 3, or (at your
1985+ option) any later version.
1986+
1987+ GCC is distributed in the hope that it will be useful, but WITHOUT
1988+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1989+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1990+ License for more details.
1991+
1992+ You should have received a copy of the GNU General Public License and
1993+ a copy of the GCC Runtime Library Exception along with this program;
1994+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
1995+ <http://www.gnu.org/licenses/>. */
1996+
1997+(define_insn "*ldm4_ia"
1998+ [(match_parallel 0 "load_multiple_operation"
1999+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2000+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2001+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2002+ (mem:SI (plus:SI (match_dup 1)
2003+ (const_int 4))))
2004+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2005+ (mem:SI (plus:SI (match_dup 1)
2006+ (const_int 8))))
2007+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2008+ (mem:SI (plus:SI (match_dup 1)
2009+ (const_int 12))))])]
2010+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2011+ "ldm%(ia%)\t%1, {%2, %3, %4, %5}"
2012+ [(set_attr "type" "load4")
2013+ (set_attr "predicable" "yes")])
2014+
2015+(define_insn "*thumb_ldm4_ia"
2016+ [(match_parallel 0 "load_multiple_operation"
2017+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2018+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2019+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2020+ (mem:SI (plus:SI (match_dup 1)
2021+ (const_int 4))))
2022+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2023+ (mem:SI (plus:SI (match_dup 1)
2024+ (const_int 8))))
2025+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2026+ (mem:SI (plus:SI (match_dup 1)
2027+ (const_int 12))))])]
2028+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2029+ "ldm%(ia%)\t%1, {%2, %3, %4, %5}"
2030+ [(set_attr "type" "load4")])
2031+
2032+(define_insn "*ldm4_ia_update"
2033+ [(match_parallel 0 "load_multiple_operation"
2034+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2035+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2036+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2037+ (mem:SI (match_dup 2)))
2038+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2039+ (mem:SI (plus:SI (match_dup 2)
2040+ (const_int 4))))
2041+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2042+ (mem:SI (plus:SI (match_dup 2)
2043+ (const_int 8))))
2044+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2045+ (mem:SI (plus:SI (match_dup 2)
2046+ (const_int 12))))])]
2047+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2048+ "ldm%(ia%)\t%1!, {%3, %4, %5, %6}"
2049+ [(set_attr "type" "load4")
2050+ (set_attr "predicable" "yes")])
2051+
2052+(define_insn "*thumb_ldm4_ia_update"
2053+ [(match_parallel 0 "load_multiple_operation"
2054+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2055+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2056+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2057+ (mem:SI (match_dup 2)))
2058+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2059+ (mem:SI (plus:SI (match_dup 2)
2060+ (const_int 4))))
2061+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2062+ (mem:SI (plus:SI (match_dup 2)
2063+ (const_int 8))))
2064+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2065+ (mem:SI (plus:SI (match_dup 2)
2066+ (const_int 12))))])]
2067+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
2068+ "ldm%(ia%)\t%1!, {%3, %4, %5, %6}"
2069+ [(set_attr "type" "load4")])
2070+
2071+(define_insn "*stm4_ia"
2072+ [(match_parallel 0 "store_multiple_operation"
2073+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2074+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2075+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2076+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2077+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2078+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2079+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2080+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2081+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2082+ "stm%(ia%)\t%1, {%2, %3, %4, %5}"
2083+ [(set_attr "type" "store4")
2084+ (set_attr "predicable" "yes")])
2085+
2086+(define_insn "*stm4_ia_update"
2087+ [(match_parallel 0 "store_multiple_operation"
2088+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2089+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2090+ (set (mem:SI (match_dup 2))
2091+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2092+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2093+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2094+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2095+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2096+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2097+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2098+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2099+ "stm%(ia%)\t%1!, {%3, %4, %5, %6}"
2100+ [(set_attr "type" "store4")
2101+ (set_attr "predicable" "yes")])
2102+
2103+(define_insn "*thumb_stm4_ia_update"
2104+ [(match_parallel 0 "store_multiple_operation"
2105+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2106+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2107+ (set (mem:SI (match_dup 2))
2108+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2109+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2110+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2111+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2112+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2113+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2114+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2115+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
2116+ "stm%(ia%)\t%1!, {%3, %4, %5, %6}"
2117+ [(set_attr "type" "store4")])
2118+
2119+(define_insn "*ldm4_ib"
2120+ [(match_parallel 0 "load_multiple_operation"
2121+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2122+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2123+ (const_int 4))))
2124+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2125+ (mem:SI (plus:SI (match_dup 1)
2126+ (const_int 8))))
2127+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2128+ (mem:SI (plus:SI (match_dup 1)
2129+ (const_int 12))))
2130+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2131+ (mem:SI (plus:SI (match_dup 1)
2132+ (const_int 16))))])]
2133+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2134+ "ldm%(ib%)\t%1, {%2, %3, %4, %5}"
2135+ [(set_attr "type" "load4")
2136+ (set_attr "predicable" "yes")])
2137+
2138+(define_insn "*ldm4_ib_update"
2139+ [(match_parallel 0 "load_multiple_operation"
2140+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2141+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2142+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2143+ (mem:SI (plus:SI (match_dup 2)
2144+ (const_int 4))))
2145+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2146+ (mem:SI (plus:SI (match_dup 2)
2147+ (const_int 8))))
2148+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2149+ (mem:SI (plus:SI (match_dup 2)
2150+ (const_int 12))))
2151+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2152+ (mem:SI (plus:SI (match_dup 2)
2153+ (const_int 16))))])]
2154+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2155+ "ldm%(ib%)\t%1!, {%3, %4, %5, %6}"
2156+ [(set_attr "type" "load4")
2157+ (set_attr "predicable" "yes")])
2158+
2159+(define_insn "*stm4_ib"
2160+ [(match_parallel 0 "store_multiple_operation"
2161+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2162+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2163+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2164+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2165+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2166+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2167+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
2168+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2169+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2170+ "stm%(ib%)\t%1, {%2, %3, %4, %5}"
2171+ [(set_attr "type" "store4")
2172+ (set_attr "predicable" "yes")])
2173+
2174+(define_insn "*stm4_ib_update"
2175+ [(match_parallel 0 "store_multiple_operation"
2176+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2177+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 16)))
2178+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2179+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2180+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2181+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2182+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2183+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2184+ (set (mem:SI (plus:SI (match_dup 2) (const_int 16)))
2185+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2186+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2187+ "stm%(ib%)\t%1!, {%3, %4, %5, %6}"
2188+ [(set_attr "type" "store4")
2189+ (set_attr "predicable" "yes")])
2190+
2191+(define_insn "*ldm4_da"
2192+ [(match_parallel 0 "load_multiple_operation"
2193+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2194+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2195+ (const_int -12))))
2196+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2197+ (mem:SI (plus:SI (match_dup 1)
2198+ (const_int -8))))
2199+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2200+ (mem:SI (plus:SI (match_dup 1)
2201+ (const_int -4))))
2202+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2203+ (mem:SI (match_dup 1)))])]
2204+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2205+ "ldm%(da%)\t%1, {%2, %3, %4, %5}"
2206+ [(set_attr "type" "load4")
2207+ (set_attr "predicable" "yes")])
2208+
2209+(define_insn "*ldm4_da_update"
2210+ [(match_parallel 0 "load_multiple_operation"
2211+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2212+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2213+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2214+ (mem:SI (plus:SI (match_dup 2)
2215+ (const_int -12))))
2216+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2217+ (mem:SI (plus:SI (match_dup 2)
2218+ (const_int -8))))
2219+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2220+ (mem:SI (plus:SI (match_dup 2)
2221+ (const_int -4))))
2222+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2223+ (mem:SI (match_dup 2)))])]
2224+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2225+ "ldm%(da%)\t%1!, {%3, %4, %5, %6}"
2226+ [(set_attr "type" "load4")
2227+ (set_attr "predicable" "yes")])
2228+
2229+(define_insn "*stm4_da"
2230+ [(match_parallel 0 "store_multiple_operation"
2231+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -12)))
2232+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2233+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2234+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2235+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2236+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2237+ (set (mem:SI (match_dup 1))
2238+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2239+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2240+ "stm%(da%)\t%1, {%2, %3, %4, %5}"
2241+ [(set_attr "type" "store4")
2242+ (set_attr "predicable" "yes")])
2243+
2244+(define_insn "*stm4_da_update"
2245+ [(match_parallel 0 "store_multiple_operation"
2246+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2247+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2248+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2249+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2250+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2251+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2252+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2253+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2254+ (set (mem:SI (match_dup 2))
2255+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2256+ "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
2257+ "stm%(da%)\t%1!, {%3, %4, %5, %6}"
2258+ [(set_attr "type" "store4")
2259+ (set_attr "predicable" "yes")])
2260+
2261+(define_insn "*ldm4_db"
2262+ [(match_parallel 0 "load_multiple_operation"
2263+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2264+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2265+ (const_int -16))))
2266+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2267+ (mem:SI (plus:SI (match_dup 1)
2268+ (const_int -12))))
2269+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2270+ (mem:SI (plus:SI (match_dup 1)
2271+ (const_int -8))))
2272+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2273+ (mem:SI (plus:SI (match_dup 1)
2274+ (const_int -4))))])]
2275+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2276+ "ldm%(db%)\t%1, {%2, %3, %4, %5}"
2277+ [(set_attr "type" "load4")
2278+ (set_attr "predicable" "yes")])
2279+
2280+(define_insn "*ldm4_db_update"
2281+ [(match_parallel 0 "load_multiple_operation"
2282+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2283+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2284+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2285+ (mem:SI (plus:SI (match_dup 2)
2286+ (const_int -16))))
2287+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2288+ (mem:SI (plus:SI (match_dup 2)
2289+ (const_int -12))))
2290+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2291+ (mem:SI (plus:SI (match_dup 2)
2292+ (const_int -8))))
2293+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
2294+ (mem:SI (plus:SI (match_dup 2)
2295+ (const_int -4))))])]
2296+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2297+ "ldm%(db%)\t%1!, {%3, %4, %5, %6}"
2298+ [(set_attr "type" "load4")
2299+ (set_attr "predicable" "yes")])
2300+
2301+(define_insn "*stm4_db"
2302+ [(match_parallel 0 "store_multiple_operation"
2303+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -16)))
2304+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2305+ (set (mem:SI (plus:SI (match_dup 1) (const_int -12)))
2306+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2307+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2308+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2309+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2310+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2311+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2312+ "stm%(db%)\t%1, {%2, %3, %4, %5}"
2313+ [(set_attr "type" "store4")
2314+ (set_attr "predicable" "yes")])
2315+
2316+(define_insn "*stm4_db_update"
2317+ [(match_parallel 0 "store_multiple_operation"
2318+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2319+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -16)))
2320+ (set (mem:SI (plus:SI (match_dup 2) (const_int -16)))
2321+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2322+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2323+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2324+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2325+ (match_operand:SI 5 "arm_hard_register_operand" ""))
2326+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2327+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
2328+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
2329+ "stm%(db%)\t%1!, {%3, %4, %5, %6}"
2330+ [(set_attr "type" "store4")
2331+ (set_attr "predicable" "yes")])
2332+
2333+(define_peephole2
2334+ [(set (match_operand:SI 0 "s_register_operand" "")
2335+ (match_operand:SI 4 "memory_operand" ""))
2336+ (set (match_operand:SI 1 "s_register_operand" "")
2337+ (match_operand:SI 5 "memory_operand" ""))
2338+ (set (match_operand:SI 2 "s_register_operand" "")
2339+ (match_operand:SI 6 "memory_operand" ""))
2340+ (set (match_operand:SI 3 "s_register_operand" "")
2341+ (match_operand:SI 7 "memory_operand" ""))]
2342+ ""
2343+ [(const_int 0)]
2344+{
2345+ if (gen_ldm_seq (operands, 4, false))
2346+ DONE;
2347+ else
2348+ FAIL;
2349+})
2350+
2351+(define_peephole2
2352+ [(set (match_operand:SI 0 "s_register_operand" "")
2353+ (match_operand:SI 4 "memory_operand" ""))
2354+ (parallel
2355+ [(set (match_operand:SI 1 "s_register_operand" "")
2356+ (match_operand:SI 5 "memory_operand" ""))
2357+ (set (match_operand:SI 2 "s_register_operand" "")
2358+ (match_operand:SI 6 "memory_operand" ""))
2359+ (set (match_operand:SI 3 "s_register_operand" "")
2360+ (match_operand:SI 7 "memory_operand" ""))])]
2361+ ""
2362+ [(const_int 0)]
2363+{
2364+ if (gen_ldm_seq (operands, 4, false))
2365+ DONE;
2366+ else
2367+ FAIL;
2368+})
2369+
2370+(define_peephole2
2371+ [(set (match_operand:SI 0 "s_register_operand" "")
2372+ (match_operand:SI 8 "const_int_operand" ""))
2373+ (set (match_operand:SI 4 "memory_operand" "")
2374+ (match_dup 0))
2375+ (set (match_operand:SI 1 "s_register_operand" "")
2376+ (match_operand:SI 9 "const_int_operand" ""))
2377+ (set (match_operand:SI 5 "memory_operand" "")
2378+ (match_dup 1))
2379+ (set (match_operand:SI 2 "s_register_operand" "")
2380+ (match_operand:SI 10 "const_int_operand" ""))
2381+ (set (match_operand:SI 6 "memory_operand" "")
2382+ (match_dup 2))
2383+ (set (match_operand:SI 3 "s_register_operand" "")
2384+ (match_operand:SI 11 "const_int_operand" ""))
2385+ (set (match_operand:SI 7 "memory_operand" "")
2386+ (match_dup 3))]
2387+ ""
2388+ [(const_int 0)]
2389+{
2390+ if (gen_const_stm_seq (operands, 4))
2391+ DONE;
2392+ else
2393+ FAIL;
2394+})
2395+
2396+(define_peephole2
2397+ [(set (match_operand:SI 0 "s_register_operand" "")
2398+ (match_operand:SI 8 "const_int_operand" ""))
2399+ (set (match_operand:SI 1 "s_register_operand" "")
2400+ (match_operand:SI 9 "const_int_operand" ""))
2401+ (set (match_operand:SI 2 "s_register_operand" "")
2402+ (match_operand:SI 10 "const_int_operand" ""))
2403+ (set (match_operand:SI 3 "s_register_operand" "")
2404+ (match_operand:SI 11 "const_int_operand" ""))
2405+ (set (match_operand:SI 4 "memory_operand" "")
2406+ (match_dup 0))
2407+ (set (match_operand:SI 5 "memory_operand" "")
2408+ (match_dup 1))
2409+ (set (match_operand:SI 6 "memory_operand" "")
2410+ (match_dup 2))
2411+ (set (match_operand:SI 7 "memory_operand" "")
2412+ (match_dup 3))]
2413+ ""
2414+ [(const_int 0)]
2415+{
2416+ if (gen_const_stm_seq (operands, 4))
2417+ DONE;
2418+ else
2419+ FAIL;
2420+})
2421+
2422+(define_peephole2
2423+ [(set (match_operand:SI 4 "memory_operand" "")
2424+ (match_operand:SI 0 "s_register_operand" ""))
2425+ (set (match_operand:SI 5 "memory_operand" "")
2426+ (match_operand:SI 1 "s_register_operand" ""))
2427+ (set (match_operand:SI 6 "memory_operand" "")
2428+ (match_operand:SI 2 "s_register_operand" ""))
2429+ (set (match_operand:SI 7 "memory_operand" "")
2430+ (match_operand:SI 3 "s_register_operand" ""))]
2431+ ""
2432+ [(const_int 0)]
2433+{
2434+ if (gen_stm_seq (operands, 4))
2435+ DONE;
2436+ else
2437+ FAIL;
2438+})
2439+
2440+(define_insn "*ldm3_ia"
2441+ [(match_parallel 0 "load_multiple_operation"
2442+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2443+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2444+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2445+ (mem:SI (plus:SI (match_dup 1)
2446+ (const_int 4))))
2447+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2448+ (mem:SI (plus:SI (match_dup 1)
2449+ (const_int 8))))])]
2450+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2451+ "ldm%(ia%)\t%1, {%2, %3, %4}"
2452+ [(set_attr "type" "load3")
2453+ (set_attr "predicable" "yes")])
2454+
2455+(define_insn "*thumb_ldm3_ia"
2456+ [(match_parallel 0 "load_multiple_operation"
2457+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2458+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2459+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2460+ (mem:SI (plus:SI (match_dup 1)
2461+ (const_int 4))))
2462+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2463+ (mem:SI (plus:SI (match_dup 1)
2464+ (const_int 8))))])]
2465+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2466+ "ldm%(ia%)\t%1, {%2, %3, %4}"
2467+ [(set_attr "type" "load3")])
2468+
2469+(define_insn "*ldm3_ia_update"
2470+ [(match_parallel 0 "load_multiple_operation"
2471+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2472+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2473+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2474+ (mem:SI (match_dup 2)))
2475+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2476+ (mem:SI (plus:SI (match_dup 2)
2477+ (const_int 4))))
2478+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2479+ (mem:SI (plus:SI (match_dup 2)
2480+ (const_int 8))))])]
2481+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2482+ "ldm%(ia%)\t%1!, {%3, %4, %5}"
2483+ [(set_attr "type" "load3")
2484+ (set_attr "predicable" "yes")])
2485+
2486+(define_insn "*thumb_ldm3_ia_update"
2487+ [(match_parallel 0 "load_multiple_operation"
2488+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2489+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2490+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2491+ (mem:SI (match_dup 2)))
2492+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2493+ (mem:SI (plus:SI (match_dup 2)
2494+ (const_int 4))))
2495+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2496+ (mem:SI (plus:SI (match_dup 2)
2497+ (const_int 8))))])]
2498+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2499+ "ldm%(ia%)\t%1!, {%3, %4, %5}"
2500+ [(set_attr "type" "load3")])
2501+
2502+(define_insn "*stm3_ia"
2503+ [(match_parallel 0 "store_multiple_operation"
2504+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2505+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2506+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2507+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2508+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2509+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2510+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2511+ "stm%(ia%)\t%1, {%2, %3, %4}"
2512+ [(set_attr "type" "store3")
2513+ (set_attr "predicable" "yes")])
2514+
2515+(define_insn "*stm3_ia_update"
2516+ [(match_parallel 0 "store_multiple_operation"
2517+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2518+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2519+ (set (mem:SI (match_dup 2))
2520+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2521+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2522+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2523+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2524+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2525+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2526+ "stm%(ia%)\t%1!, {%3, %4, %5}"
2527+ [(set_attr "type" "store3")
2528+ (set_attr "predicable" "yes")])
2529+
2530+(define_insn "*thumb_stm3_ia_update"
2531+ [(match_parallel 0 "store_multiple_operation"
2532+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2533+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2534+ (set (mem:SI (match_dup 2))
2535+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2536+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2537+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2538+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2539+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2540+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
2541+ "stm%(ia%)\t%1!, {%3, %4, %5}"
2542+ [(set_attr "type" "store3")])
2543+
2544+(define_insn "*ldm3_ib"
2545+ [(match_parallel 0 "load_multiple_operation"
2546+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2547+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2548+ (const_int 4))))
2549+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2550+ (mem:SI (plus:SI (match_dup 1)
2551+ (const_int 8))))
2552+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2553+ (mem:SI (plus:SI (match_dup 1)
2554+ (const_int 12))))])]
2555+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2556+ "ldm%(ib%)\t%1, {%2, %3, %4}"
2557+ [(set_attr "type" "load3")
2558+ (set_attr "predicable" "yes")])
2559+
2560+(define_insn "*ldm3_ib_update"
2561+ [(match_parallel 0 "load_multiple_operation"
2562+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2563+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2564+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2565+ (mem:SI (plus:SI (match_dup 2)
2566+ (const_int 4))))
2567+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2568+ (mem:SI (plus:SI (match_dup 2)
2569+ (const_int 8))))
2570+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2571+ (mem:SI (plus:SI (match_dup 2)
2572+ (const_int 12))))])]
2573+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2574+ "ldm%(ib%)\t%1!, {%3, %4, %5}"
2575+ [(set_attr "type" "load3")
2576+ (set_attr "predicable" "yes")])
2577+
2578+(define_insn "*stm3_ib"
2579+ [(match_parallel 0 "store_multiple_operation"
2580+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2581+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2582+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2583+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2584+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
2585+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2586+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2587+ "stm%(ib%)\t%1, {%2, %3, %4}"
2588+ [(set_attr "type" "store3")
2589+ (set_attr "predicable" "yes")])
2590+
2591+(define_insn "*stm3_ib_update"
2592+ [(match_parallel 0 "store_multiple_operation"
2593+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2594+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 12)))
2595+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2596+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2597+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2598+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2599+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
2600+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2601+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2602+ "stm%(ib%)\t%1!, {%3, %4, %5}"
2603+ [(set_attr "type" "store3")
2604+ (set_attr "predicable" "yes")])
2605+
2606+(define_insn "*ldm3_da"
2607+ [(match_parallel 0 "load_multiple_operation"
2608+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2609+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2610+ (const_int -8))))
2611+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2612+ (mem:SI (plus:SI (match_dup 1)
2613+ (const_int -4))))
2614+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2615+ (mem:SI (match_dup 1)))])]
2616+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2617+ "ldm%(da%)\t%1, {%2, %3, %4}"
2618+ [(set_attr "type" "load3")
2619+ (set_attr "predicable" "yes")])
2620+
2621+(define_insn "*ldm3_da_update"
2622+ [(match_parallel 0 "load_multiple_operation"
2623+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2624+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2625+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2626+ (mem:SI (plus:SI (match_dup 2)
2627+ (const_int -8))))
2628+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2629+ (mem:SI (plus:SI (match_dup 2)
2630+ (const_int -4))))
2631+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2632+ (mem:SI (match_dup 2)))])]
2633+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2634+ "ldm%(da%)\t%1!, {%3, %4, %5}"
2635+ [(set_attr "type" "load3")
2636+ (set_attr "predicable" "yes")])
2637+
2638+(define_insn "*stm3_da"
2639+ [(match_parallel 0 "store_multiple_operation"
2640+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -8)))
2641+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2642+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2643+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2644+ (set (mem:SI (match_dup 1))
2645+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2646+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2647+ "stm%(da%)\t%1, {%2, %3, %4}"
2648+ [(set_attr "type" "store3")
2649+ (set_attr "predicable" "yes")])
2650+
2651+(define_insn "*stm3_da_update"
2652+ [(match_parallel 0 "store_multiple_operation"
2653+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2654+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2655+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2656+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2657+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2658+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2659+ (set (mem:SI (match_dup 2))
2660+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2661+ "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
2662+ "stm%(da%)\t%1!, {%3, %4, %5}"
2663+ [(set_attr "type" "store3")
2664+ (set_attr "predicable" "yes")])
2665+
2666+(define_insn "*ldm3_db"
2667+ [(match_parallel 0 "load_multiple_operation"
2668+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2669+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2670+ (const_int -12))))
2671+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2672+ (mem:SI (plus:SI (match_dup 1)
2673+ (const_int -8))))
2674+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2675+ (mem:SI (plus:SI (match_dup 1)
2676+ (const_int -4))))])]
2677+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2678+ "ldm%(db%)\t%1, {%2, %3, %4}"
2679+ [(set_attr "type" "load3")
2680+ (set_attr "predicable" "yes")])
2681+
2682+(define_insn "*ldm3_db_update"
2683+ [(match_parallel 0 "load_multiple_operation"
2684+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2685+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2686+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2687+ (mem:SI (plus:SI (match_dup 2)
2688+ (const_int -12))))
2689+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2690+ (mem:SI (plus:SI (match_dup 2)
2691+ (const_int -8))))
2692+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
2693+ (mem:SI (plus:SI (match_dup 2)
2694+ (const_int -4))))])]
2695+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2696+ "ldm%(db%)\t%1!, {%3, %4, %5}"
2697+ [(set_attr "type" "load3")
2698+ (set_attr "predicable" "yes")])
2699+
2700+(define_insn "*stm3_db"
2701+ [(match_parallel 0 "store_multiple_operation"
2702+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -12)))
2703+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2704+ (set (mem:SI (plus:SI (match_dup 1) (const_int -8)))
2705+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2706+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
2707+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2708+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2709+ "stm%(db%)\t%1, {%2, %3, %4}"
2710+ [(set_attr "type" "store3")
2711+ (set_attr "predicable" "yes")])
2712+
2713+(define_insn "*stm3_db_update"
2714+ [(match_parallel 0 "store_multiple_operation"
2715+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2716+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -12)))
2717+ (set (mem:SI (plus:SI (match_dup 2) (const_int -12)))
2718+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2719+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
2720+ (match_operand:SI 4 "arm_hard_register_operand" ""))
2721+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
2722+ (match_operand:SI 5 "arm_hard_register_operand" ""))])]
2723+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
2724+ "stm%(db%)\t%1!, {%3, %4, %5}"
2725+ [(set_attr "type" "store3")
2726+ (set_attr "predicable" "yes")])
2727+
2728+(define_peephole2
2729+ [(set (match_operand:SI 0 "s_register_operand" "")
2730+ (match_operand:SI 3 "memory_operand" ""))
2731+ (set (match_operand:SI 1 "s_register_operand" "")
2732+ (match_operand:SI 4 "memory_operand" ""))
2733+ (set (match_operand:SI 2 "s_register_operand" "")
2734+ (match_operand:SI 5 "memory_operand" ""))]
2735+ ""
2736+ [(const_int 0)]
2737+{
2738+ if (gen_ldm_seq (operands, 3, false))
2739+ DONE;
2740+ else
2741+ FAIL;
2742+})
2743+
2744+(define_peephole2
2745+ [(set (match_operand:SI 0 "s_register_operand" "")
2746+ (match_operand:SI 3 "memory_operand" ""))
2747+ (parallel
2748+ [(set (match_operand:SI 1 "s_register_operand" "")
2749+ (match_operand:SI 4 "memory_operand" ""))
2750+ (set (match_operand:SI 2 "s_register_operand" "")
2751+ (match_operand:SI 5 "memory_operand" ""))])]
2752+ ""
2753+ [(const_int 0)]
2754+{
2755+ if (gen_ldm_seq (operands, 3, false))
2756+ DONE;
2757+ else
2758+ FAIL;
2759+})
2760+
2761+(define_peephole2
2762+ [(set (match_operand:SI 0 "s_register_operand" "")
2763+ (match_operand:SI 6 "const_int_operand" ""))
2764+ (set (match_operand:SI 3 "memory_operand" "")
2765+ (match_dup 0))
2766+ (set (match_operand:SI 1 "s_register_operand" "")
2767+ (match_operand:SI 7 "const_int_operand" ""))
2768+ (set (match_operand:SI 4 "memory_operand" "")
2769+ (match_dup 1))
2770+ (set (match_operand:SI 2 "s_register_operand" "")
2771+ (match_operand:SI 8 "const_int_operand" ""))
2772+ (set (match_operand:SI 5 "memory_operand" "")
2773+ (match_dup 2))]
2774+ ""
2775+ [(const_int 0)]
2776+{
2777+ if (gen_const_stm_seq (operands, 3))
2778+ DONE;
2779+ else
2780+ FAIL;
2781+})
2782+
2783+(define_peephole2
2784+ [(set (match_operand:SI 0 "s_register_operand" "")
2785+ (match_operand:SI 6 "const_int_operand" ""))
2786+ (set (match_operand:SI 1 "s_register_operand" "")
2787+ (match_operand:SI 7 "const_int_operand" ""))
2788+ (set (match_operand:SI 2 "s_register_operand" "")
2789+ (match_operand:SI 8 "const_int_operand" ""))
2790+ (set (match_operand:SI 3 "memory_operand" "")
2791+ (match_dup 0))
2792+ (set (match_operand:SI 4 "memory_operand" "")
2793+ (match_dup 1))
2794+ (set (match_operand:SI 5 "memory_operand" "")
2795+ (match_dup 2))]
2796+ ""
2797+ [(const_int 0)]
2798+{
2799+ if (gen_const_stm_seq (operands, 3))
2800+ DONE;
2801+ else
2802+ FAIL;
2803+})
2804+
2805+(define_peephole2
2806+ [(set (match_operand:SI 3 "memory_operand" "")
2807+ (match_operand:SI 0 "s_register_operand" ""))
2808+ (set (match_operand:SI 4 "memory_operand" "")
2809+ (match_operand:SI 1 "s_register_operand" ""))
2810+ (set (match_operand:SI 5 "memory_operand" "")
2811+ (match_operand:SI 2 "s_register_operand" ""))]
2812+ ""
2813+ [(const_int 0)]
2814+{
2815+ if (gen_stm_seq (operands, 3))
2816+ DONE;
2817+ else
2818+ FAIL;
2819+})
2820+
2821+(define_insn "*ldm2_ia"
2822+ [(match_parallel 0 "load_multiple_operation"
2823+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2824+ (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
2825+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2826+ (mem:SI (plus:SI (match_dup 1)
2827+ (const_int 4))))])]
2828+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
2829+ "ldm%(ia%)\t%1, {%2, %3}"
2830+ [(set_attr "type" "load2")
2831+ (set_attr "predicable" "yes")])
2832+
2833+(define_insn "*thumb_ldm2_ia"
2834+ [(match_parallel 0 "load_multiple_operation"
2835+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2836+ (mem:SI (match_operand:SI 1 "s_register_operand" "l")))
2837+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2838+ (mem:SI (plus:SI (match_dup 1)
2839+ (const_int 4))))])]
2840+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 2"
2841+ "ldm%(ia%)\t%1, {%2, %3}"
2842+ [(set_attr "type" "load2")])
2843+
2844+(define_insn "*ldm2_ia_update"
2845+ [(match_parallel 0 "load_multiple_operation"
2846+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2847+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2848+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2849+ (mem:SI (match_dup 2)))
2850+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2851+ (mem:SI (plus:SI (match_dup 2)
2852+ (const_int 4))))])]
2853+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2854+ "ldm%(ia%)\t%1!, {%3, %4}"
2855+ [(set_attr "type" "load2")
2856+ (set_attr "predicable" "yes")])
2857+
2858+(define_insn "*thumb_ldm2_ia_update"
2859+ [(match_parallel 0 "load_multiple_operation"
2860+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2861+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2862+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2863+ (mem:SI (match_dup 2)))
2864+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2865+ (mem:SI (plus:SI (match_dup 2)
2866+ (const_int 4))))])]
2867+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2868+ "ldm%(ia%)\t%1!, {%3, %4}"
2869+ [(set_attr "type" "load2")])
2870+
2871+(define_insn "*stm2_ia"
2872+ [(match_parallel 0 "store_multiple_operation"
2873+ [(set (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))
2874+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2875+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
2876+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
2877+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
2878+ "stm%(ia%)\t%1, {%2, %3}"
2879+ [(set_attr "type" "store2")
2880+ (set_attr "predicable" "yes")])
2881+
2882+(define_insn "*stm2_ia_update"
2883+ [(match_parallel 0 "store_multiple_operation"
2884+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2885+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2886+ (set (mem:SI (match_dup 2))
2887+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2888+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2889+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2890+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
2891+ "stm%(ia%)\t%1!, {%3, %4}"
2892+ [(set_attr "type" "store2")
2893+ (set_attr "predicable" "yes")])
2894+
2895+(define_insn "*thumb_stm2_ia_update"
2896+ [(match_parallel 0 "store_multiple_operation"
2897+ [(set (match_operand:SI 1 "s_register_operand" "=l")
2898+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2899+ (set (mem:SI (match_dup 2))
2900+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2901+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2902+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2903+ "TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
2904+ "stm%(ia%)\t%1!, {%3, %4}"
2905+ [(set_attr "type" "store2")])
2906+
2907+(define_insn "*ldm2_ib"
2908+ [(match_parallel 0 "load_multiple_operation"
2909+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2910+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2911+ (const_int 4))))
2912+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2913+ (mem:SI (plus:SI (match_dup 1)
2914+ (const_int 8))))])]
2915+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2916+ "ldm%(ib%)\t%1, {%2, %3}"
2917+ [(set_attr "type" "load2")
2918+ (set_attr "predicable" "yes")])
2919+
2920+(define_insn "*ldm2_ib_update"
2921+ [(match_parallel 0 "load_multiple_operation"
2922+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2923+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2924+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2925+ (mem:SI (plus:SI (match_dup 2)
2926+ (const_int 4))))
2927+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2928+ (mem:SI (plus:SI (match_dup 2)
2929+ (const_int 8))))])]
2930+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2931+ "ldm%(ib%)\t%1!, {%3, %4}"
2932+ [(set_attr "type" "load2")
2933+ (set_attr "predicable" "yes")])
2934+
2935+(define_insn "*stm2_ib"
2936+ [(match_parallel 0 "store_multiple_operation"
2937+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int 4)))
2938+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2939+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
2940+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
2941+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2942+ "stm%(ib%)\t%1, {%2, %3}"
2943+ [(set_attr "type" "store2")
2944+ (set_attr "predicable" "yes")])
2945+
2946+(define_insn "*stm2_ib_update"
2947+ [(match_parallel 0 "store_multiple_operation"
2948+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2949+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int 8)))
2950+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
2951+ (match_operand:SI 3 "arm_hard_register_operand" ""))
2952+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
2953+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
2954+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2955+ "stm%(ib%)\t%1!, {%3, %4}"
2956+ [(set_attr "type" "store2")
2957+ (set_attr "predicable" "yes")])
2958+
2959+(define_insn "*ldm2_da"
2960+ [(match_parallel 0 "load_multiple_operation"
2961+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
2962+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
2963+ (const_int -4))))
2964+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2965+ (mem:SI (match_dup 1)))])]
2966+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2967+ "ldm%(da%)\t%1, {%2, %3}"
2968+ [(set_attr "type" "load2")
2969+ (set_attr "predicable" "yes")])
2970+
2971+(define_insn "*ldm2_da_update"
2972+ [(match_parallel 0 "load_multiple_operation"
2973+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2974+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
2975+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
2976+ (mem:SI (plus:SI (match_dup 2)
2977+ (const_int -4))))
2978+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
2979+ (mem:SI (match_dup 2)))])]
2980+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
2981+ "ldm%(da%)\t%1!, {%3, %4}"
2982+ [(set_attr "type" "load2")
2983+ (set_attr "predicable" "yes")])
2984+
2985+(define_insn "*stm2_da"
2986+ [(match_parallel 0 "store_multiple_operation"
2987+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -4)))
2988+ (match_operand:SI 2 "arm_hard_register_operand" ""))
2989+ (set (mem:SI (match_dup 1))
2990+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
2991+ "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
2992+ "stm%(da%)\t%1, {%2, %3}"
2993+ [(set_attr "type" "store2")
2994+ (set_attr "predicable" "yes")])
2995+
2996+(define_insn "*stm2_da_update"
2997+ [(match_parallel 0 "store_multiple_operation"
2998+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
2999+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3000+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
3001+ (match_operand:SI 3 "arm_hard_register_operand" ""))
3002+ (set (mem:SI (match_dup 2))
3003+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
3004+ "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
3005+ "stm%(da%)\t%1!, {%3, %4}"
3006+ [(set_attr "type" "store2")
3007+ (set_attr "predicable" "yes")])
3008+
3009+(define_insn "*ldm2_db"
3010+ [(match_parallel 0 "load_multiple_operation"
3011+ [(set (match_operand:SI 2 "arm_hard_register_operand" "")
3012+ (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
3013+ (const_int -8))))
3014+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
3015+ (mem:SI (plus:SI (match_dup 1)
3016+ (const_int -4))))])]
3017+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
3018+ "ldm%(db%)\t%1, {%2, %3}"
3019+ [(set_attr "type" "load2")
3020+ (set_attr "predicable" "yes")])
3021+
3022+(define_insn "*ldm2_db_update"
3023+ [(match_parallel 0 "load_multiple_operation"
3024+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
3025+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3026+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
3027+ (mem:SI (plus:SI (match_dup 2)
3028+ (const_int -8))))
3029+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
3030+ (mem:SI (plus:SI (match_dup 2)
3031+ (const_int -4))))])]
3032+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
3033+ "ldm%(db%)\t%1!, {%3, %4}"
3034+ [(set_attr "type" "load2")
3035+ (set_attr "predicable" "yes")])
3036+
3037+(define_insn "*stm2_db"
3038+ [(match_parallel 0 "store_multiple_operation"
3039+ [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") (const_int -8)))
3040+ (match_operand:SI 2 "arm_hard_register_operand" ""))
3041+ (set (mem:SI (plus:SI (match_dup 1) (const_int -4)))
3042+ (match_operand:SI 3 "arm_hard_register_operand" ""))])]
3043+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
3044+ "stm%(db%)\t%1, {%2, %3}"
3045+ [(set_attr "type" "store2")
3046+ (set_attr "predicable" "yes")])
3047+
3048+(define_insn "*stm2_db_update"
3049+ [(match_parallel 0 "store_multiple_operation"
3050+ [(set (match_operand:SI 1 "s_register_operand" "=rk")
3051+ (plus:SI (match_operand:SI 2 "s_register_operand" "1") (const_int -8)))
3052+ (set (mem:SI (plus:SI (match_dup 2) (const_int -8)))
3053+ (match_operand:SI 3 "arm_hard_register_operand" ""))
3054+ (set (mem:SI (plus:SI (match_dup 2) (const_int -4)))
3055+ (match_operand:SI 4 "arm_hard_register_operand" ""))])]
3056+ "TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
3057+ "stm%(db%)\t%1!, {%3, %4}"
3058+ [(set_attr "type" "store2")
3059+ (set_attr "predicable" "yes")])
3060+
3061+(define_peephole2
3062+ [(set (match_operand:SI 0 "s_register_operand" "")
3063+ (match_operand:SI 2 "memory_operand" ""))
3064+ (set (match_operand:SI 1 "s_register_operand" "")
3065+ (match_operand:SI 3 "memory_operand" ""))]
3066+ ""
3067+ [(const_int 0)]
3068+{
3069+ if (gen_ldm_seq (operands, 2, false))
3070+ DONE;
3071+ else
3072+ FAIL;
3073+})
3074+
3075+(define_peephole2
3076+ [(set (match_operand:SI 0 "s_register_operand" "")
3077+ (match_operand:SI 4 "const_int_operand" ""))
3078+ (set (match_operand:SI 2 "memory_operand" "")
3079+ (match_dup 0))
3080+ (set (match_operand:SI 1 "s_register_operand" "")
3081+ (match_operand:SI 5 "const_int_operand" ""))
3082+ (set (match_operand:SI 3 "memory_operand" "")
3083+ (match_dup 1))]
3084+ ""
3085+ [(const_int 0)]
3086+{
3087+ if (gen_const_stm_seq (operands, 2))
3088+ DONE;
3089+ else
3090+ FAIL;
3091+})
3092+
3093+(define_peephole2
3094+ [(set (match_operand:SI 0 "s_register_operand" "")
3095+ (match_operand:SI 4 "const_int_operand" ""))
3096+ (set (match_operand:SI 1 "s_register_operand" "")
3097+ (match_operand:SI 5 "const_int_operand" ""))
3098+ (set (match_operand:SI 2 "memory_operand" "")
3099+ (match_dup 0))
3100+ (set (match_operand:SI 3 "memory_operand" "")
3101+ (match_dup 1))]
3102+ ""
3103+ [(const_int 0)]
3104+{
3105+ if (gen_const_stm_seq (operands, 2))
3106+ DONE;
3107+ else
3108+ FAIL;
3109+})
3110+
3111+(define_peephole2
3112+ [(set (match_operand:SI 2 "memory_operand" "")
3113+ (match_operand:SI 0 "s_register_operand" ""))
3114+ (set (match_operand:SI 3 "memory_operand" "")
3115+ (match_operand:SI 1 "s_register_operand" ""))]
3116+ ""
3117+ [(const_int 0)]
3118+{
3119+ if (gen_stm_seq (operands, 2))
3120+ DONE;
3121+ else
3122+ FAIL;
3123+})
3124+
3125+(define_peephole2
3126+ [(set (match_operand:SI 0 "s_register_operand" "")
3127+ (match_operand:SI 2 "memory_operand" ""))
3128+ (set (match_operand:SI 1 "s_register_operand" "")
3129+ (match_operand:SI 3 "memory_operand" ""))
3130+ (parallel
3131+ [(set (match_operand:SI 4 "s_register_operand" "")
3132+ (match_operator:SI 5 "commutative_binary_operator"
3133+ [(match_operand:SI 6 "s_register_operand" "")
3134+ (match_operand:SI 7 "s_register_operand" "")]))
3135+ (clobber (reg:CC CC_REGNUM))])]
3136+ "(((operands[6] == operands[0] && operands[7] == operands[1])
3137+ || (operands[7] == operands[0] && operands[6] == operands[1]))
3138+ && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[1]))"
3139+ [(parallel
3140+ [(set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))
3141+ (clobber (reg:CC CC_REGNUM))])]
3142+{
3143+ if (!gen_ldm_seq (operands, 2, true))
3144+ FAIL;
3145+})
3146+
3147+(define_peephole2
3148+ [(set (match_operand:SI 0 "s_register_operand" "")
3149+ (match_operand:SI 2 "memory_operand" ""))
3150+ (set (match_operand:SI 1 "s_register_operand" "")
3151+ (match_operand:SI 3 "memory_operand" ""))
3152+ (set (match_operand:SI 4 "s_register_operand" "")
3153+ (match_operator:SI 5 "commutative_binary_operator"
3154+ [(match_operand:SI 6 "s_register_operand" "")
3155+ (match_operand:SI 7 "s_register_operand" "")]))]
3156+ "(((operands[6] == operands[0] && operands[7] == operands[1])
3157+ || (operands[7] == operands[0] && operands[6] == operands[1]))
3158+ && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[1]))"
3159+ [(set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))]
3160+{
3161+ if (!gen_ldm_seq (operands, 2, true))
3162+ FAIL;
3163+})
3164+
3165Index: gcc-4_5-branch/gcc/config/arm/predicates.md
3166===================================================================
3167--- gcc-4_5-branch.orig/gcc/config/arm/predicates.md
3168+++ gcc-4_5-branch/gcc/config/arm/predicates.md
3169@@ -211,6 +211,11 @@
3170 (and (match_code "ior,xor,and")
3171 (match_test "mode == GET_MODE (op)")))
3172
3173+;; True for commutative operators
3174+(define_special_predicate "commutative_binary_operator"
3175+ (and (match_code "ior,xor,and,plus")
3176+ (match_test "mode == GET_MODE (op)")))
3177+
3178 ;; True for shift operators.
3179 (define_special_predicate "shift_operator"
3180 (and (ior (ior (and (match_code "mult")
3181@@ -334,16 +339,20 @@
3182 (match_code "parallel")
3183 {
3184 HOST_WIDE_INT count = XVECLEN (op, 0);
3185- int dest_regno;
3186+ unsigned dest_regno;
3187 rtx src_addr;
3188 HOST_WIDE_INT i = 1, base = 0;
3189+ HOST_WIDE_INT offset = 0;
3190 rtx elt;
3191+ bool addr_reg_loaded = false;
3192+ bool update = false;
3193
3194 if (low_irq_latency)
3195 return false;
3196
3197 if (count <= 1
3198- || GET_CODE (XVECEXP (op, 0, 0)) != SET)
3199+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
3200+ || !REG_P (SET_DEST (XVECEXP (op, 0, 0))))
3201 return false;
3202
3203 /* Check to see if this might be a write-back. */
3204@@ -351,6 +360,7 @@
3205 {
3206 i++;
3207 base = 1;
3208+ update = true;
3209
3210 /* Now check it more carefully. */
3211 if (GET_CODE (SET_DEST (elt)) != REG
3212@@ -369,6 +379,15 @@
3213
3214 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
3215 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
3216+ if (GET_CODE (src_addr) == PLUS)
3217+ {
3218+ if (GET_CODE (XEXP (src_addr, 1)) != CONST_INT)
3219+ return false;
3220+ offset = INTVAL (XEXP (src_addr, 1));
3221+ src_addr = XEXP (src_addr, 0);
3222+ }
3223+ if (!REG_P (src_addr))
3224+ return false;
3225
3226 for (; i < count; i++)
3227 {
3228@@ -377,16 +396,28 @@
3229 if (GET_CODE (elt) != SET
3230 || GET_CODE (SET_DEST (elt)) != REG
3231 || GET_MODE (SET_DEST (elt)) != SImode
3232- || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
3233+ || REGNO (SET_DEST (elt)) <= dest_regno
3234 || GET_CODE (SET_SRC (elt)) != MEM
3235 || GET_MODE (SET_SRC (elt)) != SImode
3236- || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
3237- || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
3238- || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
3239- || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4)
3240+ || ((GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
3241+ || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
3242+ || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
3243+ || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != offset + (i - base) * 4)
3244+ && (!REG_P (XEXP (SET_SRC (elt), 0))
3245+ || offset + (i - base) * 4 != 0)))
3246 return false;
3247+ dest_regno = REGNO (SET_DEST (elt));
3248+ if (dest_regno == REGNO (src_addr))
3249+ addr_reg_loaded = true;
3250 }
3251-
3252+ /* For Thumb, we only have updating instructions. If the pattern does
3253+ not describe an update, it must be because the address register is
3254+ in the list of loaded registers - on the hardware, this has the effect
3255+ of overriding the update. */
3256+ if (update && addr_reg_loaded)
3257+ return false;
3258+ if (TARGET_THUMB1)
3259+ return update || addr_reg_loaded;
3260 return true;
3261 })
3262
3263@@ -394,9 +425,9 @@
3264 (match_code "parallel")
3265 {
3266 HOST_WIDE_INT count = XVECLEN (op, 0);
3267- int src_regno;
3268+ unsigned src_regno;
3269 rtx dest_addr;
3270- HOST_WIDE_INT i = 1, base = 0;
3271+ HOST_WIDE_INT i = 1, base = 0, offset = 0;
3272 rtx elt;
3273
3274 if (low_irq_latency)
3275@@ -430,6 +461,16 @@
3276 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
3277 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
3278
3279+ if (GET_CODE (dest_addr) == PLUS)
3280+ {
3281+ if (GET_CODE (XEXP (dest_addr, 1)) != CONST_INT)
3282+ return false;
3283+ offset = INTVAL (XEXP (dest_addr, 1));
3284+ dest_addr = XEXP (dest_addr, 0);
3285+ }
3286+ if (!REG_P (dest_addr))
3287+ return false;
3288+
3289 for (; i < count; i++)
3290 {
3291 elt = XVECEXP (op, 0, i);
3292@@ -437,14 +478,17 @@
3293 if (GET_CODE (elt) != SET
3294 || GET_CODE (SET_SRC (elt)) != REG
3295 || GET_MODE (SET_SRC (elt)) != SImode
3296- || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
3297+ || REGNO (SET_SRC (elt)) <= src_regno
3298 || GET_CODE (SET_DEST (elt)) != MEM
3299 || GET_MODE (SET_DEST (elt)) != SImode
3300- || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
3301- || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
3302- || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
3303- || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4)
3304+ || ((GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
3305+ || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
3306+ || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
3307+ || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != offset + (i - base) * 4)
3308+ && (!REG_P (XEXP (SET_DEST (elt), 0))
3309+ || offset + (i - base) * 4 != 0)))
3310 return false;
3311+ src_regno = REGNO (SET_SRC (elt));
3312 }
3313
3314 return true;
3315Index: gcc-4_5-branch/gcc/config/i386/i386.md
3316===================================================================
3317--- gcc-4_5-branch.orig/gcc/config/i386/i386.md
3318+++ gcc-4_5-branch/gcc/config/i386/i386.md
3319@@ -4934,6 +4934,7 @@
3320 (set (match_operand:SSEMODEI24 2 "register_operand" "")
3321 (fix:SSEMODEI24 (match_dup 0)))]
3322 "TARGET_SHORTEN_X87_SSE
3323+ && !(TARGET_AVOID_VECTOR_DECODE && optimize_insn_for_speed_p ())
3324 && peep2_reg_dead_p (2, operands[0])"
3325 [(set (match_dup 2) (fix:SSEMODEI24 (match_dup 1)))]
3326 "")
3327@@ -20036,15 +20037,14 @@
3328 ;; leal (%edx,%eax,4), %eax
3329
3330 (define_peephole2
3331- [(parallel [(set (match_operand 0 "register_operand" "")
3332+ [(match_scratch:P 5 "r")
3333+ (parallel [(set (match_operand 0 "register_operand" "")
3334 (ashift (match_operand 1 "register_operand" "")
3335 (match_operand 2 "const_int_operand" "")))
3336 (clobber (reg:CC FLAGS_REG))])
3337- (set (match_operand 3 "register_operand")
3338- (match_operand 4 "x86_64_general_operand" ""))
3339- (parallel [(set (match_operand 5 "register_operand" "")
3340- (plus (match_operand 6 "register_operand" "")
3341- (match_operand 7 "register_operand" "")))
3342+ (parallel [(set (match_operand 3 "register_operand" "")
3343+ (plus (match_dup 0)
3344+ (match_operand 4 "x86_64_general_operand" "")))
3345 (clobber (reg:CC FLAGS_REG))])]
3346 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 3
3347 /* Validate MODE for lea. */
3348@@ -20053,31 +20053,27 @@
3349 || GET_MODE (operands[0]) == HImode))
3350 || GET_MODE (operands[0]) == SImode
3351 || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
3352+ && (rtx_equal_p (operands[0], operands[3])
3353+ || peep2_reg_dead_p (2, operands[0]))
3354 /* We reorder load and the shift. */
3355- && !rtx_equal_p (operands[1], operands[3])
3356- && !reg_overlap_mentioned_p (operands[0], operands[4])
3357- /* Last PLUS must consist of operand 0 and 3. */
3358- && !rtx_equal_p (operands[0], operands[3])
3359- && (rtx_equal_p (operands[3], operands[6])
3360- || rtx_equal_p (operands[3], operands[7]))
3361- && (rtx_equal_p (operands[0], operands[6])
3362- || rtx_equal_p (operands[0], operands[7]))
3363- /* The intermediate operand 0 must die or be same as output. */
3364- && (rtx_equal_p (operands[0], operands[5])
3365- || peep2_reg_dead_p (3, operands[0]))"
3366- [(set (match_dup 3) (match_dup 4))
3367+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
3368+ [(set (match_dup 5) (match_dup 4))
3369 (set (match_dup 0) (match_dup 1))]
3370 {
3371- enum machine_mode mode = GET_MODE (operands[5]) == DImode ? DImode : SImode;
3372+ enum machine_mode mode = GET_MODE (operands[1]) == DImode ? DImode : SImode;
3373 int scale = 1 << INTVAL (operands[2]);
3374 rtx index = gen_lowpart (Pmode, operands[1]);
3375- rtx base = gen_lowpart (Pmode, operands[3]);
3376- rtx dest = gen_lowpart (mode, operands[5]);
3377+ rtx base = gen_lowpart (Pmode, operands[5]);
3378+ rtx dest = gen_lowpart (mode, operands[3]);
3379
3380 operands[1] = gen_rtx_PLUS (Pmode, base,
3381 gen_rtx_MULT (Pmode, index, GEN_INT (scale)));
3382+ operands[5] = base;
3383 if (mode != Pmode)
3384- operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
3385+ {
3386+ operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
3387+ operands[5] = gen_rtx_SUBREG (mode, operands[5], 0);
3388+ }
3389 operands[0] = dest;
3390 })
3391
3392Index: gcc-4_5-branch/gcc/df-problems.c
3393===================================================================
3394--- gcc-4_5-branch.orig/gcc/df-problems.c
3395+++ gcc-4_5-branch/gcc/df-problems.c
3396@@ -3748,9 +3748,22 @@ df_simulate_find_defs (rtx insn, bitmap
3397 for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
3398 {
3399 df_ref def = *def_rec;
3400- /* If the def is to only part of the reg, it does
3401- not kill the other defs that reach here. */
3402- if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
3403+ bitmap_set_bit (defs, DF_REF_REGNO (def));
3404+ }
3405+}
3406+
3407+/* Find the set of real DEFs, which are not clobbers, for INSN. */
3408+
3409+void
3410+df_simulate_find_noclobber_defs (rtx insn, bitmap defs)
3411+{
3412+ df_ref *def_rec;
3413+ unsigned int uid = INSN_UID (insn);
3414+
3415+ for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
3416+ {
3417+ df_ref def = *def_rec;
3418+ if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER)))
3419 bitmap_set_bit (defs, DF_REF_REGNO (def));
3420 }
3421 }
3422@@ -3921,7 +3934,7 @@ df_simulate_initialize_forwards (basic_b
3423 {
3424 df_ref def = *def_rec;
3425 if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
3426- bitmap_clear_bit (live, DF_REF_REGNO (def));
3427+ bitmap_set_bit (live, DF_REF_REGNO (def));
3428 }
3429 }
3430
3431@@ -3942,7 +3955,7 @@ df_simulate_one_insn_forwards (basic_blo
3432 while here the scan is performed forwards! So, first assume that the
3433 def is live, and if this is not true REG_UNUSED notes will rectify the
3434 situation. */
3435- df_simulate_find_defs (insn, live);
3436+ df_simulate_find_noclobber_defs (insn, live);
3437
3438 /* Clear all of the registers that go dead. */
3439 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
3440Index: gcc-4_5-branch/gcc/df.h
3441===================================================================
3442--- gcc-4_5-branch.orig/gcc/df.h
3443+++ gcc-4_5-branch/gcc/df.h
3444@@ -978,6 +978,7 @@ extern void df_note_add_problem (void);
3445 extern void df_md_add_problem (void);
3446 extern void df_md_simulate_artificial_defs_at_top (basic_block, bitmap);
3447 extern void df_md_simulate_one_insn (basic_block, rtx, bitmap);
3448+extern void df_simulate_find_noclobber_defs (rtx, bitmap);
3449 extern void df_simulate_find_defs (rtx, bitmap);
3450 extern void df_simulate_defs (rtx, bitmap);
3451 extern void df_simulate_uses (rtx, bitmap);
3452Index: gcc-4_5-branch/gcc/fwprop.c
3453===================================================================
3454--- gcc-4_5-branch.orig/gcc/fwprop.c
3455+++ gcc-4_5-branch/gcc/fwprop.c
3456@@ -228,7 +228,10 @@ single_def_use_enter_block (struct dom_w
3457
3458 process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP);
3459 process_defs (df_get_artificial_defs (bb_index), DF_REF_AT_TOP);
3460- df_simulate_initialize_forwards (bb, local_lr);
3461+
3462+ /* We don't call df_simulate_initialize_forwards, as it may overestimate
3463+ the live registers if there are unused artificial defs. We prefer
3464+ liveness to be underestimated. */
3465
3466 FOR_BB_INSNS (bb, insn)
3467 if (INSN_P (insn))
3468Index: gcc-4_5-branch/gcc/genoutput.c
3469===================================================================
3470--- gcc-4_5-branch.orig/gcc/genoutput.c
3471+++ gcc-4_5-branch/gcc/genoutput.c
3472@@ -266,6 +266,8 @@ output_operand_data (void)
3473
3474 printf (" %d,\n", d->strict_low);
3475
3476+ printf (" %d,\n", d->constraint == NULL ? 1 : 0);
3477+
3478 printf (" %d\n", d->eliminable);
3479
3480 printf(" },\n");
3481Index: gcc-4_5-branch/gcc/genrecog.c
3482===================================================================
3483--- gcc-4_5-branch.orig/gcc/genrecog.c
3484+++ gcc-4_5-branch/gcc/genrecog.c
3485@@ -1782,20 +1782,11 @@ change_state (const char *oldpos, const
3486 int odepth = strlen (oldpos);
3487 int ndepth = strlen (newpos);
3488 int depth;
3489- int old_has_insn, new_has_insn;
3490
3491 /* Pop up as many levels as necessary. */
3492 for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
3493 continue;
3494
3495- /* Hunt for the last [A-Z] in both strings. */
3496- for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
3497- if (ISUPPER (oldpos[old_has_insn]))
3498- break;
3499- for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
3500- if (ISUPPER (newpos[new_has_insn]))
3501- break;
3502-
3503 /* Go down to desired level. */
3504 while (depth < ndepth)
3505 {
3506Index: gcc-4_5-branch/gcc/ifcvt.c
3507===================================================================
3508--- gcc-4_5-branch.orig/gcc/ifcvt.c
3509+++ gcc-4_5-branch/gcc/ifcvt.c
3510@@ -4011,6 +4011,7 @@ dead_or_predicable (basic_block test_bb,
3511 basic_block new_dest = dest_edge->dest;
3512 rtx head, end, jump, earliest = NULL_RTX, old_dest;
3513 bitmap merge_set = NULL;
3514+ bitmap merge_set_noclobber = NULL;
3515 /* Number of pending changes. */
3516 int n_validated_changes = 0;
3517 rtx new_dest_label;
3518@@ -4169,6 +4170,7 @@ dead_or_predicable (basic_block test_bb,
3519 end of the block. */
3520
3521 merge_set = BITMAP_ALLOC (&reg_obstack);
3522+ merge_set_noclobber = BITMAP_ALLOC (&reg_obstack);
3523
3524 /* If we allocated new pseudos (e.g. in the conditional move
3525 expander called from noce_emit_cmove), we must resize the
3526@@ -4187,6 +4189,7 @@ dead_or_predicable (basic_block test_bb,
3527 df_ref def = *def_rec;
3528 bitmap_set_bit (merge_set, DF_REF_REGNO (def));
3529 }
3530+ df_simulate_find_noclobber_defs (insn, merge_set_noclobber);
3531 }
3532 }
3533
3534@@ -4197,7 +4200,7 @@ dead_or_predicable (basic_block test_bb,
3535 unsigned i;
3536 bitmap_iterator bi;
3537
3538- EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
3539+ EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi)
3540 {
3541 if (i < FIRST_PSEUDO_REGISTER
3542 && ! fixed_regs[i]
3543@@ -4233,7 +4236,7 @@ dead_or_predicable (basic_block test_bb,
3544 TEST_SET & DF_LIVE_IN (merge_bb)
3545 are empty. */
3546
3547- if (bitmap_intersect_p (merge_set, test_set)
3548+ if (bitmap_intersect_p (merge_set_noclobber, test_set)
3549 || bitmap_intersect_p (merge_set, test_live)
3550 || bitmap_intersect_p (test_set, df_get_live_in (merge_bb)))
3551 intersect = true;
3552@@ -4320,6 +4323,7 @@ dead_or_predicable (basic_block test_bb,
3553 remove_reg_equal_equiv_notes_for_regno (i);
3554
3555 BITMAP_FREE (merge_set);
3556+ BITMAP_FREE (merge_set_noclobber);
3557 }
3558
3559 reorder_insns (head, end, PREV_INSN (earliest));
3560@@ -4340,7 +4344,10 @@ dead_or_predicable (basic_block test_bb,
3561 cancel_changes (0);
3562 fail:
3563 if (merge_set)
3564- BITMAP_FREE (merge_set);
3565+ {
3566+ BITMAP_FREE (merge_set);
3567+ BITMAP_FREE (merge_set_noclobber);
3568+ }
3569 return FALSE;
3570 }
3571
3572Index: gcc-4_5-branch/gcc/recog.c
3573===================================================================
3574--- gcc-4_5-branch.orig/gcc/recog.c
3575+++ gcc-4_5-branch/gcc/recog.c
3576@@ -2082,6 +2082,7 @@ extract_insn (rtx insn)
3577 recog_data.operand_loc,
3578 recog_data.constraints,
3579 recog_data.operand_mode, NULL);
3580+ memset (recog_data.is_operator, 0, sizeof recog_data.is_operator);
3581 if (noperands > 0)
3582 {
3583 const char *p = recog_data.constraints[0];
3584@@ -2111,6 +2112,7 @@ extract_insn (rtx insn)
3585 for (i = 0; i < noperands; i++)
3586 {
3587 recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
3588+ recog_data.is_operator[i] = insn_data[icode].operand[i].is_operator;
3589 recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
3590 /* VOIDmode match_operands gets mode from their real operand. */
3591 if (recog_data.operand_mode[i] == VOIDmode)
3592@@ -2909,6 +2911,10 @@ struct peep2_insn_data
3593
3594 static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
3595 static int peep2_current;
3596+
3597+static bool peep2_do_rebuild_jump_labels;
3598+static bool peep2_do_cleanup_cfg;
3599+
3600 /* The number of instructions available to match a peep2. */
3601 int peep2_current_count;
3602
3603@@ -2917,6 +2923,16 @@ int peep2_current_count;
3604 DF_LIVE_OUT for the block. */
3605 #define PEEP2_EOB pc_rtx
3606
3607+/* Wrap N to fit into the peep2_insn_data buffer. */
3608+
3609+static int
3610+peep2_buf_position (int n)
3611+{
3612+ if (n >= MAX_INSNS_PER_PEEP2 + 1)
3613+ n -= MAX_INSNS_PER_PEEP2 + 1;
3614+ return n;
3615+}
3616+
3617 /* Return the Nth non-note insn after `current', or return NULL_RTX if it
3618 does not exist. Used by the recognizer to find the next insn to match
3619 in a multi-insn pattern. */
3620@@ -2926,9 +2942,7 @@ peep2_next_insn (int n)
3621 {
3622 gcc_assert (n <= peep2_current_count);
3623
3624- n += peep2_current;
3625- if (n >= MAX_INSNS_PER_PEEP2 + 1)
3626- n -= MAX_INSNS_PER_PEEP2 + 1;
3627+ n = peep2_buf_position (peep2_current + n);
3628
3629 return peep2_insn_data[n].insn;
3630 }
3631@@ -2941,9 +2955,7 @@ peep2_regno_dead_p (int ofs, int regno)
3632 {
3633 gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3634
3635- ofs += peep2_current;
3636- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
3637- ofs -= MAX_INSNS_PER_PEEP2 + 1;
3638+ ofs = peep2_buf_position (peep2_current + ofs);
3639
3640 gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3641
3642@@ -2959,9 +2971,7 @@ peep2_reg_dead_p (int ofs, rtx reg)
3643
3644 gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3645
3646- ofs += peep2_current;
3647- if (ofs >= MAX_INSNS_PER_PEEP2 + 1)
3648- ofs -= MAX_INSNS_PER_PEEP2 + 1;
3649+ ofs = peep2_buf_position (peep2_current + ofs);
3650
3651 gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3652
3653@@ -2996,12 +3006,8 @@ peep2_find_free_register (int from, int
3654 gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
3655 gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
3656
3657- from += peep2_current;
3658- if (from >= MAX_INSNS_PER_PEEP2 + 1)
3659- from -= MAX_INSNS_PER_PEEP2 + 1;
3660- to += peep2_current;
3661- if (to >= MAX_INSNS_PER_PEEP2 + 1)
3662- to -= MAX_INSNS_PER_PEEP2 + 1;
3663+ from = peep2_buf_position (peep2_current + from);
3664+ to = peep2_buf_position (peep2_current + to);
3665
3666 gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3667 REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
3668@@ -3010,8 +3016,7 @@ peep2_find_free_register (int from, int
3669 {
3670 HARD_REG_SET this_live;
3671
3672- if (++from >= MAX_INSNS_PER_PEEP2 + 1)
3673- from = 0;
3674+ from = peep2_buf_position (from + 1);
3675 gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3676 REG_SET_TO_HARD_REG_SET (this_live, peep2_insn_data[from].live_before);
3677 IOR_HARD_REG_SET (live, this_live);
3678@@ -3104,19 +3109,234 @@ peep2_reinit_state (regset live)
3679 COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
3680 }
3681
3682+/* While scanning basic block BB, we found a match of length MATCH_LEN,
3683+ starting at INSN. Perform the replacement, removing the old insns and
3684+ replacing them with ATTEMPT. Returns the last insn emitted. */
3685+
3686+static rtx
3687+peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt)
3688+{
3689+ int i;
3690+ rtx last, note, before_try, x;
3691+ bool was_call = false;
3692+
3693+ /* If we are splitting a CALL_INSN, look for the CALL_INSN
3694+ in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
3695+ cfg-related call notes. */
3696+ for (i = 0; i <= match_len; ++i)
3697+ {
3698+ int j;
3699+ rtx old_insn, new_insn, note;
3700+
3701+ j = peep2_buf_position (peep2_current + i);
3702+ old_insn = peep2_insn_data[j].insn;
3703+ if (!CALL_P (old_insn))
3704+ continue;
3705+ was_call = true;
3706+
3707+ new_insn = attempt;
3708+ while (new_insn != NULL_RTX)
3709+ {
3710+ if (CALL_P (new_insn))
3711+ break;
3712+ new_insn = NEXT_INSN (new_insn);
3713+ }
3714+
3715+ gcc_assert (new_insn != NULL_RTX);
3716+
3717+ CALL_INSN_FUNCTION_USAGE (new_insn)
3718+ = CALL_INSN_FUNCTION_USAGE (old_insn);
3719+
3720+ for (note = REG_NOTES (old_insn);
3721+ note;
3722+ note = XEXP (note, 1))
3723+ switch (REG_NOTE_KIND (note))
3724+ {
3725+ case REG_NORETURN:
3726+ case REG_SETJMP:
3727+ add_reg_note (new_insn, REG_NOTE_KIND (note),
3728+ XEXP (note, 0));
3729+ break;
3730+ default:
3731+ /* Discard all other reg notes. */
3732+ break;
3733+ }
3734+
3735+ /* Croak if there is another call in the sequence. */
3736+ while (++i <= match_len)
3737+ {
3738+ j = peep2_buf_position (peep2_current + i);
3739+ old_insn = peep2_insn_data[j].insn;
3740+ gcc_assert (!CALL_P (old_insn));
3741+ }
3742+ break;
3743+ }
3744+
3745+ i = peep2_buf_position (peep2_current + match_len);
3746+
3747+ note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX);
3748+
3749+ /* Replace the old sequence with the new. */
3750+ last = emit_insn_after_setloc (attempt,
3751+ peep2_insn_data[i].insn,
3752+ INSN_LOCATOR (peep2_insn_data[i].insn));
3753+ before_try = PREV_INSN (insn);
3754+ delete_insn_chain (insn, peep2_insn_data[i].insn, false);
3755+
3756+ /* Re-insert the EH_REGION notes. */
3757+ if (note || (was_call && nonlocal_goto_handler_labels))
3758+ {
3759+ edge eh_edge;
3760+ edge_iterator ei;
3761+
3762+ FOR_EACH_EDGE (eh_edge, ei, bb->succs)
3763+ if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
3764+ break;
3765+
3766+ if (note)
3767+ copy_reg_eh_region_note_backward (note, last, before_try);
3768+
3769+ if (eh_edge)
3770+ for (x = last; x != before_try; x = PREV_INSN (x))
3771+ if (x != BB_END (bb)
3772+ && (can_throw_internal (x)
3773+ || can_nonlocal_goto (x)))
3774+ {
3775+ edge nfte, nehe;
3776+ int flags;
3777+
3778+ nfte = split_block (bb, x);
3779+ flags = (eh_edge->flags
3780+ & (EDGE_EH | EDGE_ABNORMAL));
3781+ if (CALL_P (x))
3782+ flags |= EDGE_ABNORMAL_CALL;
3783+ nehe = make_edge (nfte->src, eh_edge->dest,
3784+ flags);
3785+
3786+ nehe->probability = eh_edge->probability;
3787+ nfte->probability
3788+ = REG_BR_PROB_BASE - nehe->probability;
3789+
3790+ peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
3791+ bb = nfte->src;
3792+ eh_edge = nehe;
3793+ }
3794+
3795+ /* Converting possibly trapping insn to non-trapping is
3796+ possible. Zap dummy outgoing edges. */
3797+ peep2_do_cleanup_cfg |= purge_dead_edges (bb);
3798+ }
3799+
3800+ /* If we generated a jump instruction, it won't have
3801+ JUMP_LABEL set. Recompute after we're done. */
3802+ for (x = last; x != before_try; x = PREV_INSN (x))
3803+ if (JUMP_P (x))
3804+ {
3805+ peep2_do_rebuild_jump_labels = true;
3806+ break;
3807+ }
3808+
3809+ return last;
3810+}
3811+
3812+/* After performing a replacement in basic block BB, fix up the life
3813+ information in our buffer. LAST is the last of the insns that we
3814+ emitted as a replacement. PREV is the insn before the start of
3815+ the replacement. MATCH_LEN is the number of instructions that were
3816+ matched, and which now need to be replaced in the buffer. */
3817+
3818+static void
3819+peep2_update_life (basic_block bb, int match_len, rtx last, rtx prev)
3820+{
3821+ int i = peep2_buf_position (peep2_current + match_len + 1);
3822+ rtx x;
3823+ regset_head live;
3824+
3825+ INIT_REG_SET (&live);
3826+ COPY_REG_SET (&live, peep2_insn_data[i].live_before);
3827+
3828+ gcc_assert (peep2_current_count >= match_len + 1);
3829+ peep2_current_count -= match_len + 1;
3830+
3831+ x = last;
3832+ do
3833+ {
3834+ if (INSN_P (x))
3835+ {
3836+ df_insn_rescan (x);
3837+ if (peep2_current_count < MAX_INSNS_PER_PEEP2)
3838+ {
3839+ peep2_current_count++;
3840+ if (--i < 0)
3841+ i = MAX_INSNS_PER_PEEP2;
3842+ peep2_insn_data[i].insn = x;
3843+ df_simulate_one_insn_backwards (bb, x, &live);
3844+ COPY_REG_SET (peep2_insn_data[i].live_before, &live);
3845+ }
3846+ }
3847+ x = PREV_INSN (x);
3848+ }
3849+ while (x != prev);
3850+ CLEAR_REG_SET (&live);
3851+
3852+ peep2_current = i;
3853+}
3854+
3855+/* Add INSN, which is in BB, at the end of the peep2 insn buffer if possible.
3856+ Return true if we added it, false otherwise. The caller will try to match
3857+ peepholes against the buffer if we return false; otherwise it will try to
3858+ add more instructions to the buffer. */
3859+
3860+static bool
3861+peep2_fill_buffer (basic_block bb, rtx insn, regset live)
3862+{
3863+ int pos;
3864+
3865+ /* Once we have filled the maximum number of insns the buffer can hold,
3866+ allow the caller to match the insns against peepholes. We wait until
3867+ the buffer is full in case the target has similar peepholes of different
3868+ length; we always want to match the longest if possible. */
3869+ if (peep2_current_count == MAX_INSNS_PER_PEEP2)
3870+ return false;
3871+
3872+ /* If an insn has RTX_FRAME_RELATED_P set, peephole substitution would lose
3873+ the REG_FRAME_RELATED_EXPR that is attached. */
3874+ if (RTX_FRAME_RELATED_P (insn))
3875+ {
3876+ /* Let the buffer drain first. */
3877+ if (peep2_current_count > 0)
3878+ return false;
3879+ /* Step over the insn then return true without adding the insn
3880+ to the buffer; this will cause us to process the next
3881+ insn. */
3882+ df_simulate_one_insn_forwards (bb, insn, live);
3883+ return true;
3884+ }
3885+
3886+ pos = peep2_buf_position (peep2_current + peep2_current_count);
3887+ peep2_insn_data[pos].insn = insn;
3888+ COPY_REG_SET (peep2_insn_data[pos].live_before, live);
3889+ peep2_current_count++;
3890+
3891+ df_simulate_one_insn_forwards (bb, insn, live);
3892+ return true;
3893+}
3894+
3895 /* Perform the peephole2 optimization pass. */
3896
3897 static void
3898 peephole2_optimize (void)
3899 {
3900- rtx insn, prev;
3901+ rtx insn;
3902 bitmap live;
3903 int i;
3904 basic_block bb;
3905- bool do_cleanup_cfg = false;
3906- bool do_rebuild_jump_labels = false;
3907+
3908+ peep2_do_cleanup_cfg = false;
3909+ peep2_do_rebuild_jump_labels = false;
3910
3911 df_set_flags (DF_LR_RUN_DCE);
3912+ df_note_add_problem ();
3913 df_analyze ();
3914
3915 /* Initialize the regsets we're going to use. */
3916@@ -3126,214 +3346,59 @@ peephole2_optimize (void)
3917
3918 FOR_EACH_BB_REVERSE (bb)
3919 {
3920+ bool past_end = false;
3921+ int pos;
3922+
3923 rtl_profile_for_bb (bb);
3924
3925 /* Start up propagation. */
3926- bitmap_copy (live, DF_LR_OUT (bb));
3927- df_simulate_initialize_backwards (bb, live);
3928+ bitmap_copy (live, DF_LR_IN (bb));
3929+ df_simulate_initialize_forwards (bb, live);
3930 peep2_reinit_state (live);
3931
3932- for (insn = BB_END (bb); ; insn = prev)
3933+ insn = BB_HEAD (bb);
3934+ for (;;)
3935 {
3936- prev = PREV_INSN (insn);
3937- if (NONDEBUG_INSN_P (insn))
3938- {
3939- rtx attempt, before_try, x;
3940- int match_len;
3941- rtx note;
3942- bool was_call = false;
3943-
3944- /* Record this insn. */
3945- if (--peep2_current < 0)
3946- peep2_current = MAX_INSNS_PER_PEEP2;
3947- if (peep2_current_count < MAX_INSNS_PER_PEEP2
3948- && peep2_insn_data[peep2_current].insn == NULL_RTX)
3949- peep2_current_count++;
3950- peep2_insn_data[peep2_current].insn = insn;
3951- df_simulate_one_insn_backwards (bb, insn, live);
3952- COPY_REG_SET (peep2_insn_data[peep2_current].live_before, live);
3953-
3954- if (RTX_FRAME_RELATED_P (insn))
3955- {
3956- /* If an insn has RTX_FRAME_RELATED_P set, peephole
3957- substitution would lose the
3958- REG_FRAME_RELATED_EXPR that is attached. */
3959- peep2_reinit_state (live);
3960- attempt = NULL;
3961- }
3962- else
3963- /* Match the peephole. */
3964- attempt = peephole2_insns (PATTERN (insn), insn, &match_len);
3965-
3966- if (attempt != NULL)
3967- {
3968- /* If we are splitting a CALL_INSN, look for the CALL_INSN
3969- in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
3970- cfg-related call notes. */
3971- for (i = 0; i <= match_len; ++i)
3972- {
3973- int j;
3974- rtx old_insn, new_insn, note;
3975+ rtx attempt, head;
3976+ int match_len;
3977
3978- j = i + peep2_current;
3979- if (j >= MAX_INSNS_PER_PEEP2 + 1)
3980- j -= MAX_INSNS_PER_PEEP2 + 1;
3981- old_insn = peep2_insn_data[j].insn;
3982- if (!CALL_P (old_insn))
3983- continue;
3984- was_call = true;
3985-
3986- new_insn = attempt;
3987- while (new_insn != NULL_RTX)
3988- {
3989- if (CALL_P (new_insn))
3990- break;
3991- new_insn = NEXT_INSN (new_insn);
3992- }
3993-
3994- gcc_assert (new_insn != NULL_RTX);
3995-
3996- CALL_INSN_FUNCTION_USAGE (new_insn)
3997- = CALL_INSN_FUNCTION_USAGE (old_insn);
3998-
3999- for (note = REG_NOTES (old_insn);
4000- note;
4001- note = XEXP (note, 1))
4002- switch (REG_NOTE_KIND (note))
4003- {
4004- case REG_NORETURN:
4005- case REG_SETJMP:
4006- add_reg_note (new_insn, REG_NOTE_KIND (note),
4007- XEXP (note, 0));
4008- break;
4009- default:
4010- /* Discard all other reg notes. */
4011- break;
4012- }
4013-
4014- /* Croak if there is another call in the sequence. */
4015- while (++i <= match_len)
4016- {
4017- j = i + peep2_current;
4018- if (j >= MAX_INSNS_PER_PEEP2 + 1)
4019- j -= MAX_INSNS_PER_PEEP2 + 1;
4020- old_insn = peep2_insn_data[j].insn;
4021- gcc_assert (!CALL_P (old_insn));
4022- }
4023- break;
4024- }
4025-
4026- i = match_len + peep2_current;
4027- if (i >= MAX_INSNS_PER_PEEP2 + 1)
4028- i -= MAX_INSNS_PER_PEEP2 + 1;
4029-
4030- note = find_reg_note (peep2_insn_data[i].insn,
4031- REG_EH_REGION, NULL_RTX);
4032-
4033- /* Replace the old sequence with the new. */
4034- attempt = emit_insn_after_setloc (attempt,
4035- peep2_insn_data[i].insn,
4036- INSN_LOCATOR (peep2_insn_data[i].insn));
4037- before_try = PREV_INSN (insn);
4038- delete_insn_chain (insn, peep2_insn_data[i].insn, false);
4039-
4040- /* Re-insert the EH_REGION notes. */
4041- if (note || (was_call && nonlocal_goto_handler_labels))
4042- {
4043- edge eh_edge;
4044- edge_iterator ei;
4045-
4046- FOR_EACH_EDGE (eh_edge, ei, bb->succs)
4047- if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
4048- break;
4049-
4050- if (note)
4051- copy_reg_eh_region_note_backward (note, attempt,
4052- before_try);
4053-
4054- if (eh_edge)
4055- for (x = attempt ; x != before_try ; x = PREV_INSN (x))
4056- if (x != BB_END (bb)
4057- && (can_throw_internal (x)
4058- || can_nonlocal_goto (x)))
4059- {
4060- edge nfte, nehe;
4061- int flags;
4062-
4063- nfte = split_block (bb, x);
4064- flags = (eh_edge->flags
4065- & (EDGE_EH | EDGE_ABNORMAL));
4066- if (CALL_P (x))
4067- flags |= EDGE_ABNORMAL_CALL;
4068- nehe = make_edge (nfte->src, eh_edge->dest,
4069- flags);
4070-
4071- nehe->probability = eh_edge->probability;
4072- nfte->probability
4073- = REG_BR_PROB_BASE - nehe->probability;
4074-
4075- do_cleanup_cfg |= purge_dead_edges (nfte->dest);
4076- bb = nfte->src;
4077- eh_edge = nehe;
4078- }
4079-
4080- /* Converting possibly trapping insn to non-trapping is
4081- possible. Zap dummy outgoing edges. */
4082- do_cleanup_cfg |= purge_dead_edges (bb);
4083- }
4084+ if (!past_end && !NONDEBUG_INSN_P (insn))
4085+ {
4086+ next_insn:
4087+ insn = NEXT_INSN (insn);
4088+ if (insn == NEXT_INSN (BB_END (bb)))
4089+ past_end = true;
4090+ continue;
4091+ }
4092+ if (!past_end && peep2_fill_buffer (bb, insn, live))
4093+ goto next_insn;
4094
4095- if (targetm.have_conditional_execution ())
4096- {
4097- for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
4098- peep2_insn_data[i].insn = NULL_RTX;
4099- peep2_insn_data[peep2_current].insn = PEEP2_EOB;
4100- peep2_current_count = 0;
4101- }
4102- else
4103- {
4104- /* Back up lifetime information past the end of the
4105- newly created sequence. */
4106- if (++i >= MAX_INSNS_PER_PEEP2 + 1)
4107- i = 0;
4108- bitmap_copy (live, peep2_insn_data[i].live_before);
4109-
4110- /* Update life information for the new sequence. */
4111- x = attempt;
4112- do
4113- {
4114- if (INSN_P (x))
4115- {
4116- if (--i < 0)
4117- i = MAX_INSNS_PER_PEEP2;
4118- if (peep2_current_count < MAX_INSNS_PER_PEEP2
4119- && peep2_insn_data[i].insn == NULL_RTX)
4120- peep2_current_count++;
4121- peep2_insn_data[i].insn = x;
4122- df_insn_rescan (x);
4123- df_simulate_one_insn_backwards (bb, x, live);
4124- bitmap_copy (peep2_insn_data[i].live_before,
4125- live);
4126- }
4127- x = PREV_INSN (x);
4128- }
4129- while (x != prev);
4130+ /* If we did not fill an empty buffer, it signals the end of the
4131+ block. */
4132+ if (peep2_current_count == 0)
4133+ break;
4134
4135- peep2_current = i;
4136- }
4137+ /* The buffer filled to the current maximum, so try to match. */
4138
4139- /* If we generated a jump instruction, it won't have
4140- JUMP_LABEL set. Recompute after we're done. */
4141- for (x = attempt; x != before_try; x = PREV_INSN (x))
4142- if (JUMP_P (x))
4143- {
4144- do_rebuild_jump_labels = true;
4145- break;
4146- }
4147- }
4148+ pos = peep2_buf_position (peep2_current + peep2_current_count);
4149+ peep2_insn_data[pos].insn = PEEP2_EOB;
4150+ COPY_REG_SET (peep2_insn_data[pos].live_before, live);
4151+
4152+ /* Match the peephole. */
4153+ head = peep2_insn_data[peep2_current].insn;
4154+ attempt = peephole2_insns (PATTERN (head), head, &match_len);
4155+ if (attempt != NULL)
4156+ {
4157+ rtx last;
4158+ last = peep2_attempt (bb, head, match_len, attempt);
4159+ peep2_update_life (bb, match_len, last, PREV_INSN (attempt));
4160+ }
4161+ else
4162+ {
4163+ /* If no match, advance the buffer by one insn. */
4164+ peep2_current = peep2_buf_position (peep2_current + 1);
4165+ peep2_current_count--;
4166 }
4167-
4168- if (insn == BB_HEAD (bb))
4169- break;
4170 }
4171 }
4172
4173@@ -3341,7 +3406,7 @@ peephole2_optimize (void)
4174 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
4175 BITMAP_FREE (peep2_insn_data[i].live_before);
4176 BITMAP_FREE (live);
4177- if (do_rebuild_jump_labels)
4178+ if (peep2_do_rebuild_jump_labels)
4179 rebuild_jump_labels (get_insns ());
4180 }
4181 #endif /* HAVE_peephole2 */
4182Index: gcc-4_5-branch/gcc/recog.h
4183===================================================================
4184--- gcc-4_5-branch.orig/gcc/recog.h
4185+++ gcc-4_5-branch/gcc/recog.h
4186@@ -194,6 +194,9 @@ struct recog_data
4187 /* Gives the constraint string for operand N. */
4188 const char *constraints[MAX_RECOG_OPERANDS];
4189
4190+ /* Nonzero if operand N is a match_operator or a match_parallel. */
4191+ char is_operator[MAX_RECOG_OPERANDS];
4192+
4193 /* Gives the mode of operand N. */
4194 enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
4195
4196@@ -260,6 +263,8 @@ struct insn_operand_data
4197
4198 const char strict_low;
4199
4200+ const char is_operator;
4201+
4202 const char eliminable;
4203 };
4204
4205Index: gcc-4_5-branch/gcc/reload.c
4206===================================================================
4207--- gcc-4_5-branch.orig/gcc/reload.c
4208+++ gcc-4_5-branch/gcc/reload.c
4209@@ -3631,7 +3631,7 @@ find_reloads (rtx insn, int replace, int
4210 || modified[j] != RELOAD_WRITE)
4211 && j != i
4212 /* Ignore things like match_operator operands. */
4213- && *recog_data.constraints[j] != 0
4214+ && !recog_data.is_operator[j]
4215 /* Don't count an input operand that is constrained to match
4216 the early clobber operand. */
4217 && ! (this_alternative_matches[j] == i
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99478.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99478.patch
new file mode 100644
index 0000000000..38463a9b40
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99478.patch
@@ -0,0 +1,74 @@
12011-01-11 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
2
3 * config/arm/t-arm: Fix up last commit.
4
52011-01-11 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
6
7 * config/arm/t-arm: Update MD_INCLUDES to include
8 all the files correctly.
9 * config/arm/arm.md: Update comments.
10
11=== modified file 'gcc/config/arm/arm.md'
12--- old/gcc/config/arm/arm.md 2011-02-22 11:38:56 +0000
13+++ new/gcc/config/arm/arm.md 2011-03-01 14:32:39 +0000
14@@ -11246,6 +11246,7 @@
15 "
16 )
17
18+;; Make sure that the includes are reflected in MD_INCLUDES.
19 ;; Load the load/store multiple patterns
20 (include "ldmstm.md")
21 ;; Load the FPA co-processor patterns
22
23=== modified file 'gcc/config/arm/t-arm'
24--- old/gcc/config/arm/t-arm 2010-08-16 09:41:58 +0000
25+++ new/gcc/config/arm/t-arm 2011-01-11 21:01:30 +0000
26@@ -18,20 +18,33 @@
27 # along with GCC; see the file COPYING3. If not see
28 # <http://www.gnu.org/licenses/>.
29
30-MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
31- $(srcdir)/config/arm/predicates.md \
32- $(srcdir)/config/arm/arm-generic.md \
33- $(srcdir)/config/arm/arm1020e.md \
34- $(srcdir)/config/arm/arm1026ejs.md \
35- $(srcdir)/config/arm/arm1136jfs.md \
36- $(srcdir)/config/arm/arm926ejs.md \
37- $(srcdir)/config/arm/cirrus.md \
38- $(srcdir)/config/arm/fpa.md \
39- $(srcdir)/config/arm/vec-common.md \
40- $(srcdir)/config/arm/iwmmxt.md \
41- $(srcdir)/config/arm/vfp.md \
42- $(srcdir)/config/arm/neon.md \
43- $(srcdir)/config/arm/thumb2.md
44+MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
45+ $(srcdir)/config/arm/predicates.md \
46+ $(srcdir)/config/arm/arm-generic.md \
47+ $(srcdir)/config/arm/arm1020e.md \
48+ $(srcdir)/config/arm/arm1026ejs.md \
49+ $(srcdir)/config/arm/arm1136jfs.md \
50+ $(srcdir)/config/arm/arm926ejs.md \
51+ $(srcdir)/config/arm/cirrus.md \
52+ $(srcdir)/config/arm/fpa.md \
53+ $(srcdir)/config/arm/vec-common.md \
54+ $(srcdir)/config/arm/iwmmxt.md \
55+ $(srcdir)/config/arm/vfp.md \
56+ $(srcdir)/config/arm/cortex-a5.md \
57+ $(srcdir)/config/arm/cortex-a8.md \
58+ $(srcdir)/config/arm/cortex-a9.md \
59+ $(srcdir)/config/arm/cortex-a9-neon.md \
60+ $(srcdir)/config/arm/cortex-r4.md \
61+ $(srcdir)/config/arm/cortex-r4f.md \
62+ $(srcdir)/config/arm/cortex-m4.md \
63+ $(srcdir)/config/arm/cortex-m4-fpu.md \
64+ $(srcdir)/config/arm/vfp11.md \
65+ $(srcdir)/config/arm/ldmstm.md \
66+ $(srcdir)/config/arm/thumb2.md \
67+ $(srcdir)/config/arm/neon.md \
68+ $(srcdir)/config/arm/sync.md \
69+ $(srcdir)/config/arm/cortex-a8-neon.md \
70+ $(srcdir)/config/arm/constraints.md
71
72 LIB1ASMSRC = arm/lib1funcs.asm
73 LIB1ASMFUNCS = _thumb1_case_sqi _thumb1_case_uqi _thumb1_case_shi \
74
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99479.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99479.patch
new file mode 100644
index 0000000000..2920466d8f
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99479.patch
@@ -0,0 +1,101 @@
12011-02-24 Chung-Lin Tang <cltang@codesourcery.com>
2
3 Backport from FSF mainline:
4
5 2010-08-10 Bernd Schmidt <bernds@codesourcery.com>
6
7 PR bootstrap/45177
8 * config/arm/arm.c (multiple_operation_profitable_p): Move xscale
9 test here from arm_gen_load_multiple_1.
10 (arm_gen_load_multiple_1, arm_gen_store_multiple_1): Use
11 multiple_operation_profitable_p.
12
13=== modified file 'gcc/config/arm/arm.c'
14--- old/gcc/config/arm/arm.c 2011-02-22 11:38:56 +0000
15+++ new/gcc/config/arm/arm.c 2011-02-24 17:30:32 +0000
16@@ -9728,6 +9728,36 @@
17 if (nops == 2 && arm_ld_sched && add_offset != 0)
18 return false;
19
20+ /* XScale has load-store double instructions, but they have stricter
21+ alignment requirements than load-store multiple, so we cannot
22+ use them.
23+
24+ For XScale ldm requires 2 + NREGS cycles to complete and blocks
25+ the pipeline until completion.
26+
27+ NREGS CYCLES
28+ 1 3
29+ 2 4
30+ 3 5
31+ 4 6
32+
33+ An ldr instruction takes 1-3 cycles, but does not block the
34+ pipeline.
35+
36+ NREGS CYCLES
37+ 1 1-3
38+ 2 2-6
39+ 3 3-9
40+ 4 4-12
41+
42+ Best case ldr will always win. However, the more ldr instructions
43+ we issue, the less likely we are to be able to schedule them well.
44+ Using ldr instructions also increases code size.
45+
46+ As a compromise, we use ldr for counts of 1 or 2 regs, and ldm
47+ for counts of 3 or 4 regs. */
48+ if (nops <= 2 && arm_tune_xscale && !optimize_size)
49+ return false;
50 return true;
51 }
52
53@@ -10086,35 +10116,7 @@
54 int i = 0, j;
55 rtx result;
56
57- /* XScale has load-store double instructions, but they have stricter
58- alignment requirements than load-store multiple, so we cannot
59- use them.
60-
61- For XScale ldm requires 2 + NREGS cycles to complete and blocks
62- the pipeline until completion.
63-
64- NREGS CYCLES
65- 1 3
66- 2 4
67- 3 5
68- 4 6
69-
70- An ldr instruction takes 1-3 cycles, but does not block the
71- pipeline.
72-
73- NREGS CYCLES
74- 1 1-3
75- 2 2-6
76- 3 3-9
77- 4 4-12
78-
79- Best case ldr will always win. However, the more ldr instructions
80- we issue, the less likely we are to be able to schedule them well.
81- Using ldr instructions also increases code size.
82-
83- As a compromise, we use ldr for counts of 1 or 2 regs, and ldm
84- for counts of 3 or 4 regs. */
85- if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size))
86+ if (low_irq_latency || !multiple_operation_profitable_p (false, count, 0))
87 {
88 rtx seq;
89
90@@ -10166,9 +10168,7 @@
91 if (GET_CODE (basereg) == PLUS)
92 basereg = XEXP (basereg, 0);
93
94- /* See arm_gen_load_multiple_1 for discussion of
95- the pros/cons of ldm/stm usage for XScale. */
96- if (low_irq_latency || (arm_tune_xscale && count <= 2 && ! optimize_size))
97+ if (low_irq_latency || !multiple_operation_profitable_p (false, count, 0))
98 {
99 rtx seq;
100
101
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99480.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99480.patch
new file mode 100644
index 0000000000..76d3c9565c
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99480.patch
@@ -0,0 +1,64 @@
12011-02-02 Richard Sandiford <richard.sandiford@linaro.org>
2
3
4 gcc/
5 PR target/47551
6 * config/arm/arm.c (coproc_secondary_reload_class): Handle
7 structure modes. Don't check neon_vector_mem_operand for
8 vector or structure modes.
9
10 gcc/testsuite/
11 PR target/47551
12 * gcc.target/arm/neon-modes-2.c: New test.
13
14=== modified file 'gcc/config/arm/arm.c'
15--- old/gcc/config/arm/arm.c 2011-02-24 17:30:32 +0000
16+++ new/gcc/config/arm/arm.c 2011-03-02 11:29:06 +0000
17@@ -9303,11 +9303,14 @@
18 return GENERAL_REGS;
19 }
20
21+ /* The neon move patterns handle all legitimate vector and struct
22+ addresses. */
23 if (TARGET_NEON
24+ && MEM_P (x)
25 && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
26- || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
27- && neon_vector_mem_operand (x, 0))
28- return NO_REGS;
29+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
30+ || VALID_NEON_STRUCT_MODE (mode)))
31+ return NO_REGS;
32
33 if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode))
34 return NO_REGS;
35
36=== added file 'gcc/testsuite/gcc.target/arm/neon-modes-2.c'
37--- old/gcc/testsuite/gcc.target/arm/neon-modes-2.c 1970-01-01 00:00:00 +0000
38+++ new/gcc/testsuite/gcc.target/arm/neon-modes-2.c 2011-02-02 13:48:10 +0000
39@@ -0,0 +1,24 @@
40+/* { dg-do compile } */
41+/* { dg-require-effective-target arm_neon_ok } */
42+/* { dg-options "-O1" } */
43+/* { dg-add-options arm_neon } */
44+
45+#include "arm_neon.h"
46+
47+#define SETUP(A) x##A = vld3_u32 (ptr + A * 0x20)
48+#define MODIFY(A) x##A = vld3_lane_u32 (ptr + A * 0x20 + 0x10, x##A, 1)
49+#define STORE(A) vst3_u32 (ptr + A * 0x20, x##A)
50+
51+#define MANY(A) A (0), A (1), A (2), A (3), A (4), A (5)
52+
53+void
54+bar (uint32_t *ptr, int y)
55+{
56+ uint32x2x3_t MANY (SETUP);
57+ int *x = __builtin_alloca (y);
58+ int z[0x1000];
59+ foo (x, z);
60+ MANY (MODIFY);
61+ foo (x, z);
62+ MANY (STORE);
63+}
64
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99481.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99481.patch
new file mode 100644
index 0000000000..db53255de8
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99481.patch
@@ -0,0 +1,40 @@
1 2011-02-02 Richard Sandiford <richard.sandiford@linaro.org>
2
3 gcc/testsuite/
4 PR target/47553
5 * gcc.target/arm/neon-vld-1.c: New test.
6 gcc/
7 PR target/47553
8 * config/arm/predicates.md (neon_lane_number): Accept 0..15.
9
10=== modified file 'gcc/config/arm/predicates.md'
11--- old/gcc/config/arm/predicates.md 2011-02-08 12:07:29 +0000
12+++ new/gcc/config/arm/predicates.md 2011-03-02 12:28:41 +0000
13@@ -607,7 +607,7 @@
14 ;; TODO: We could check lane numbers more precisely based on the mode.
15 (define_predicate "neon_lane_number"
16 (and (match_code "const_int")
17- (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
18+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 15")))
19 ;; Predicates for named expanders that overlap multiple ISAs.
20
21 (define_predicate "cmpdi_operand"
22
23=== added file 'gcc/testsuite/gcc.target/arm/neon-vld-1.c'
24--- old/gcc/testsuite/gcc.target/arm/neon-vld-1.c 1970-01-01 00:00:00 +0000
25+++ new/gcc/testsuite/gcc.target/arm/neon-vld-1.c 2011-02-02 13:57:54 +0000
26@@ -0,0 +1,13 @@
27+/* { dg-do compile } */
28+/* { dg-require-effective-target arm_neon_ok } */
29+/* { dg-options "-O1" } */
30+/* { dg-add-options arm_neon } */
31+
32+#include <arm_neon.h>
33+
34+uint8x16_t
35+foo (uint8_t *a, uint8x16_t b)
36+{
37+ vst1q_lane_u8 (a, b, 14);
38+ return vld1q_lane_u8 (a + 0x100, b, 15);
39+}
40
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99482.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99482.patch
new file mode 100644
index 0000000000..334ac4ec1a
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99482.patch
@@ -0,0 +1,84 @@
1 2011-02-02 Richard Sandiford <richard.sandiford@linaro.org>
2
3 gcc/
4 Backport from mainline:
5
6 2011-01-23 Bernd Schmidt <bernds@codesourcery.com>
7 Richard Sandiford <rdsandiford@googlemail.com>
8
9 PR rtl-optimization/47166
10 * reload1.c (emit_reload_insns): Disable the spill_reg_store
11 mechanism for PRE_MODIFY and POST_MODIFY.
12 (inc_for_reload): For PRE_MODIFY, return the insn that sets the
13 reloadreg.
14
15 gcc/testsuite/
16 * gcc.c-torture/execute/postmod-1.c: New test.
17
18=== added file 'gcc/testsuite/gcc.c-torture/execute/postmod-1.c'
19--- old/gcc/testsuite/gcc.c-torture/execute/postmod-1.c 1970-01-01 00:00:00 +0000
20+++ new/gcc/testsuite/gcc.c-torture/execute/postmod-1.c 2011-02-02 14:23:10 +0000
21@@ -0,0 +1,62 @@
22+#define DECLARE_ARRAY(A) array##A[0x10]
23+#define DECLARE_COUNTER(A) counter##A = 0
24+#define DECLARE_POINTER(A) *pointer##A = array##A + x
25+/* Create a loop that allows post-modification of pointerA, followed by
26+ a use of the post-modified address. */
27+#define BEFORE(A) counter##A += *pointer##A, pointer##A += 3
28+#define AFTER(A) counter##A += pointer##A[x]
29+
30+/* Set up the arrays so that one iteration of the loop sets the counter
31+ to 3.0f. */
32+#define INIT_ARRAY(A) array##A[1] = 1.0f, array##A[5] = 2.0f
33+
34+/* Check that the loop worked correctly for all values. */
35+#define CHECK_ARRAY(A) exit_code |= (counter##A != 3.0f)
36+
37+/* Having 6 copies triggered the bug for ARM and Thumb. */
38+#define MANY(A) A (0), A (1), A (2), A (3), A (4), A (5)
39+
40+/* Each addendA should be allocated a register. */
41+#define INIT_VOLATILE(A) addend##A = vol
42+#define ADD_VOLATILE(A) vol += addend##A
43+
44+/* Having 5 copies triggered the bug for ARM and Thumb. */
45+#define MANY2(A) A (0), A (1), A (2), A (3), A (4)
46+
47+float MANY (DECLARE_ARRAY);
48+float MANY (DECLARE_COUNTER);
49+
50+volatile int stop = 1;
51+volatile int vol;
52+
53+void __attribute__((noinline))
54+foo (int x)
55+{
56+ float MANY (DECLARE_POINTER);
57+ int i;
58+
59+ do
60+ {
61+ MANY (BEFORE);
62+ MANY (AFTER);
63+ /* Create an inner loop that should ensure the code above
64+ has registers free for reload inheritance. */
65+ {
66+ int MANY2 (INIT_VOLATILE);
67+ for (i = 0; i < 10; i++)
68+ MANY2 (ADD_VOLATILE);
69+ }
70+ }
71+ while (!stop);
72+}
73+
74+int
75+main (void)
76+{
77+ int exit_code = 0;
78+
79+ MANY (INIT_ARRAY);
80+ foo (1);
81+ MANY (CHECK_ARRAY);
82+ return exit_code;
83+}
84
diff --git a/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99483.patch b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99483.patch
new file mode 100644
index 0000000000..c0be4a03b1
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99483.patch
@@ -0,0 +1,63 @@
12011-02-11 Richard Sandiford <richard.sandiford@linaro.org>
2
3 gcc/
4 * cse.c (count_reg_usage): Check side_effects_p. Remove the
5 separate check for volatile asms.
6
7 gcc/testsuite/
8 * gcc.dg/torture/volatile-pic-1.c: New test.
9
10=== modified file 'gcc/cse.c'
11--- old/gcc/cse.c 2010-11-26 12:03:32 +0000
12+++ new/gcc/cse.c 2011-02-11 09:27:19 +0000
13@@ -6634,9 +6634,10 @@
14 case CALL_INSN:
15 case INSN:
16 case JUMP_INSN:
17- /* We expect dest to be NULL_RTX here. If the insn may trap, mark
18- this fact by setting DEST to pc_rtx. */
19- if (insn_could_throw_p (x))
20+ /* We expect dest to be NULL_RTX here. If the insn may trap,
21+ or if it cannot be deleted due to side-effects, mark this fact
22+ by setting DEST to pc_rtx. */
23+ if (insn_could_throw_p (x) || side_effects_p (PATTERN (x)))
24 dest = pc_rtx;
25 if (code == CALL_INSN)
26 count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, dest, incr);
27@@ -6676,10 +6677,6 @@
28 return;
29
30 case ASM_OPERANDS:
31- /* If the asm is volatile, then this insn cannot be deleted,
32- and so the inputs *must* be live. */
33- if (MEM_VOLATILE_P (x))
34- dest = NULL_RTX;
35 /* Iterate over just the inputs, not the constraints as well. */
36 for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
37 count_reg_usage (ASM_OPERANDS_INPUT (x, i), counts, dest, incr);
38
39=== added file 'gcc/testsuite/gcc.dg/torture/volatile-pic-1.c'
40--- old/gcc/testsuite/gcc.dg/torture/volatile-pic-1.c 1970-01-01 00:00:00 +0000
41+++ new/gcc/testsuite/gcc.dg/torture/volatile-pic-1.c 2011-02-11 09:27:19 +0000
42@@ -0,0 +1,20 @@
43+/* { dg-do run } */
44+/* { dg-require-visibility "" } */
45+/* { dg-require-effective-target fpic } */
46+/* { dg-options "-fPIC" } */
47+
48+volatile int x __attribute__((visibility("hidden")));
49+
50+void __attribute__((noinline)) bar (void)
51+{
52+#if defined (__arm__)
53+ asm volatile ("mov r3,%0" :: "r" (0xdeadbeef) : "r3");
54+#endif
55+ (void) x;
56+}
57+
58+int main (void)
59+{
60+ bar ();
61+ return 0;
62+}
63
diff --git a/recipes-devtools/gcc/gcc-4.5/more-epilogues.patch b/recipes-devtools/gcc/gcc-4.5/more-epilogues.patch
new file mode 100644
index 0000000000..64f1cf3751
--- /dev/null
+++ b/recipes-devtools/gcc/gcc-4.5/more-epilogues.patch
@@ -0,0 +1,83 @@
1Index: a/gcc/cfgcleanup.c
2===================================================================
3--- a/gcc/cfgcleanup.c (revision 315947)
4+++ b/gcc/cfgcleanup.c (working copy)
5@@ -1179,13 +1179,19 @@ flow_find_head_matching_sequence (basic_
6
7 while (true)
8 {
9-
10- /* Ignore notes. */
11+ /* Ignore notes, except NOTE_INSN_EPILOGUE_BEG. */
12 while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1))
13- i1 = NEXT_INSN (i1);
14-
15+ {
16+ if (NOTE_P (i1) && NOTE_KIND (i1) == NOTE_INSN_EPILOGUE_BEG)
17+ break;
18+ i1 = NEXT_INSN (i1);
19+ }
20 while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2))
21- i2 = NEXT_INSN (i2);
22+ {
23+ if (NOTE_P (i2) && NOTE_KIND (i2) == NOTE_INSN_EPILOGUE_BEG)
24+ break;
25+ i2 = NEXT_INSN (i2);
26+ }
27
28 if (NOTE_P (i1) || NOTE_P (i2)
29 || JUMP_P (i1) || JUMP_P (i2))
30Index: a/gcc/cfglayout.c
31===================================================================
32--- a/gcc/cfglayout.c (revision 315947)
33+++ b/gcc/cfglayout.c (working copy)
34@@ -1295,6 +1295,16 @@ cfg_layout_initialize (unsigned int flag
35 bb->flags |= BB_NON_LOCAL_GOTO_TARGET;
36 }
37
38+ FOR_EACH_BB (bb)
39+ {
40+ rtx insn;
41+ FOR_BB_INSNS (bb, insn)
42+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG)
43+ {
44+ bb->flags |= BB_EPILOGUE_BEGIN;
45+ break;
46+ }
47+ }
48 cleanup_cfg (CLEANUP_CFGLAYOUT | flags);
49 }
50
51Index: a/gcc/basic-block.h
52===================================================================
53--- a/gcc/basic-block.h (revision 315947)
54+++ b/gcc/basic-block.h (working copy)
55@@ -332,7 +332,11 @@ enum bb_flags
56
57 /* Set on blocks that cannot be threaded through.
58 Only used in cfgcleanup.c. */
59- BB_NONTHREADABLE_BLOCK = 1 << 11
60+ BB_NONTHREADABLE_BLOCK = 1 << 11,
61+
62+ /* Set on blocks that have a NOTE_INSN_EPILOGUE_BEGIN.
63+ Only used in cfglayout mode. */
64+ BB_EPILOGUE_BEGIN = 1 << 12
65 };
66
67 /* Dummy flag for convenience in the hot/cold partitioning code. */
68Index: a/gcc/cfgrtl.c
69===================================================================
70--- a/gcc/cfgrtl.c (revision 315947)
71+++ b/gcc/cfgrtl.c (working copy)
72@@ -2707,7 +2707,10 @@ cfg_layout_can_merge_blocks_p (basic_blo
73 not allow us to redirect an edge by replacing a table jump. */
74 && (!JUMP_P (BB_END (a))
75 || ((!optimize || reload_completed)
76- ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a)))));
77+ ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a))))
78+ /* Don't separate a NOTE_INSN_EPILOGUE_BEG from its returnjump. */
79+ && (!(b->flags & BB_EPILOGUE_BEGIN)
80+ || returnjump_p (BB_END (b))));
81 }
82
83 /* Merge block A and B. The blocks must be mergeable. */
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
deleted file mode 100644
index 9ae01c3fc7..0000000000
--- a/recipes-devtools/gcc/gcc/gcc-4.5.1/GPLUSPLUS_INCLUDE_DIR_with_sysroot.patch
+++ /dev/null
@@ -1,33 +0,0 @@
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. */