-diff -ruN gcc-3.3.1/gcc/Makefile.in gcc-3.3.1.pp/gcc/Makefile.in
+diff -urN gcc-3.3.1/gcc/Makefile.in gcc-3.3.1-pp/gcc/Makefile.in
--- gcc-3.3.1/gcc/Makefile.in 2003-08-03 15:48:36.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/Makefile.in 2003-09-05 12:00:02.000000000 +0000
++++ gcc-3.3.1-pp/gcc/Makefile.in 2003-09-12 13:40:28.000000000 +0000
@@ -387,7 +387,7 @@
# Options to use when compiling libgcc2.a.
#
$(out_object_file): $(out_file) $(CONFIG_H) $(TREE_H) $(GGC_H) \
$(RTL_H) $(REGS_H) hard-reg-set.h real.h insn-config.h conditions.h \
-diff -ruN gcc-3.3.1/gcc/Makefile.in.orig gcc-3.3.1.pp/gcc/Makefile.in.orig
---- gcc-3.3.1/gcc/Makefile.in.orig 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/Makefile.in.orig 2003-09-05 11:58:58.000000000 +0000
-@@ -0,0 +1,3754 @@
-+# Makefile for GNU C compiler.
-+# Copyright (C) 1987, 1988, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
-+# 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-+
-+#This file is part of GCC.
-+
-+#GCC is free software; you can redistribute it and/or modify
-+#it under the terms of the GNU General Public License as published by
-+#the Free Software Foundation; either version 2, or (at your option)
-+#any later version.
-+
-+#GCC is distributed in the hope that it will be useful,
-+#but WITHOUT ANY WARRANTY; without even the implied warranty of
-+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+#GNU General Public License for more details.
-+
-+#You should have received a copy of the GNU General Public License
-+#along with GCC; see the file COPYING. If not, write to
-+#the Free Software Foundation, 59 Temple Place - Suite 330,
-+#Boston MA 02111-1307, USA.
-+
-+# The targets for external use include:
-+# all, doc, proto, install, install-cross, install-cross-rest,
-+# uninstall, TAGS, mostlyclean, clean, distclean, maintainer-clean,
-+# stage1, stage2, stage3, stage4.
-+
-+# This is the default target.
-+all:
-+
-+# Suppress smart makes who think they know how to automake Yacc files
-+.y.c:
-+
-+# Directory where sources are, from where we are.
-+srcdir = @srcdir@
-+VPATH = @srcdir@
-+
-+# Pointer to the GCC Project website
-+website=http://gcc.gnu.org
-+
-+# Variables that exist for you to override.
-+# See below for how to change them for certain systems.
-+
-+# List of language subdirectories.
-+# This is overridden by configure.
-+SUBDIRS =@subdirs@
-+
-+# Selection of languages to be made.
-+# This is overridden by configure.
-+CONFIG_LANGUAGES = @all_languages@
-+LANGUAGES = c gcov$(exeext) $(CONFIG_LANGUAGES)
-+
-+# Selection of languages to be made during stage1 build.
-+# This is overridden by configure.
-+BOOT_LANGUAGES = c @all_boot_languages@
-+
-+# Various ways of specifying flags for compilations:
-+# CFLAGS is for the user to override to, e.g., do a cross build with -O2.
-+# For recursive bootstrap builds CFLAGS is used to pass in STAGE1_CFLAGS
-+# or BOOT_CFLAGS
-+# STAGE1_CFLAGS is set by configure on some targets or passed from toplevel
-+# and sets the CFLAGS passed to stage1 of a bootstrap compilation.
-+# BOOT_CFLAGS is the value of CFLAGS to pass to the stage2, stage3 and stage4
-+# bootstrap compilations.
-+# XCFLAGS is used for most compilations but not when using the GCC just built.
-+# TCFLAGS is used for compilations with the GCC just built.
-+XCFLAGS =
-+TCFLAGS =
-+CFLAGS = -g
-+STAGE1_CFLAGS = -g @stage1_cflags@
-+BOOT_CFLAGS = -g -O2
-+
-+# Flags to determine code coverage. When coverage is disabled, this will
-+# contain the optimization flags, as you normally want code coverage
-+# without optimization. The -dumpbase $@ makes sure that the auxilary
-+# files end up near the object files.
-+COVERAGE_FLAGS = @coverage_flags@
-+coverageexts = .{da,bb,bbg}
-+
-+# The warning flags are separate from BOOT_CFLAGS because people tend to
-+# override optimization flags and we'd like them to still have warnings
-+# turned on. These flags are also used to pass other stage dependent
-+# flags from configure. The user is free to explicitly turn these flags
-+# off if they wish.
-+# LOOSE_WARN are the warning flags to use when compiling something
-+# which is only compiled with gcc, such as libgcc and the frontends
-+# other than C.
-+# STRICT_WARN and STRICT2_WARN are the additional warning flags to
-+# apply to the back end and the C front end, which may be compiled
-+# with other compilers. This is partially controlled by configure in
-+# stage1, as not all versions of gcc understand -Wno-long-long.
-+LOOSE_WARN = -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
-+STRICT_WARN = -Wtraditional @strict1_warn@
-+STRICT2_WARN = -Wtraditional -pedantic -Wno-long-long
-+
-+# This is set by --enable-checking. The idea is to catch forgotten
-+# "extern" tags in header files.
-+NOCOMMON_FLAG = @nocommon_flag@
-+
-+# These are set by --enable-checking=valgrind.
-+RUN_GEN = @valgrind_command@
-+VALGRIND_DRIVER_DEFINES = @valgrind_path_defines@
-+
-+# This is how we control whether or not the additional warnings are applied.
-+.-warn = $(STRICT_WARN)
-+GCC_WARN_CFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG)
-+
-+# All warnings have to be shut off in stage1 if the compiler used then
-+# isn't gcc; configure determines that. WARN_CFLAGS will be either
-+# $(GCC_WARN_CFLAGS), or nothing.
-+WARN_CFLAGS = @warn_cflags@
-+
-+# These exists to be overridden by the x-* and t-* files, respectively.
-+X_CFLAGS =
-+T_CFLAGS =
-+
-+X_CPPFLAGS =
-+T_CPPFLAGS =
-+
-+ADAC = @ADAC@
-+AWK = @AWK@
-+CC = @CC@
-+BISON = @BISON@
-+BISONFLAGS =
-+FLEX = @FLEX@
-+FLEXFLAGS =
-+AR = ar
-+AR_FLAGS = rc
-+DLLTOOL = dlltool
-+RANLIB = @RANLIB@
-+SHELL = @SHELL@
-+# pwd command to use. Allow user to override default by setting PWDCMD in
-+# the environment to account for automounters. The make variable must not
-+# be called PWDCMD, otherwise the value set here is passed to make
-+# subprocesses and overrides the setting from the user's environment.
-+# Don't use PWD since it is a common shell environment variable and we
-+# don't want to corrupt it.
-+PWD_COMMAND = $${PWDCMD-pwd}
-+# on sysV, define this as cp.
-+INSTALL = @INSTALL@
-+# Some systems may be missing symbolic links, regular links, or both.
-+# Allow configure to check this and use "ln -s", "ln", or "cp" as appropriate.
-+LN=@LN@
-+LN_S=@LN_S@
-+# These permit overriding just for certain files.
-+INSTALL_PROGRAM = @INSTALL_PROGRAM@
-+INSTALL_DATA = @INSTALL_DATA@
-+INSTALL_SCRIPT = @INSTALL@
-+MAKEINFO = @MAKEINFO@
-+MAKEINFOFLAGS =
-+TEXI2DVI = texi2dvi
-+TEXI2POD = perl $(srcdir)/../contrib/texi2pod.pl
-+POD2MAN = pod2man --center="GNU" --release="gcc-$(version)"
-+# For GNUmake: let us decide what gets passed to recursive makes.
-+MAKEOVERRIDES =
-+@SET_MAKE@
-+# Some compilers can't handle cc -c blah.c -o foo/blah.o.
-+# In stage2 and beyond, we force this to "-o $@" since we know we're using gcc.
-+OUTPUT_OPTION = @OUTPUT_OPTION@
-+
-+# Some versions of `touch' (such as the version on Solaris 2.8)
-+# do not correctly set the timestamp due to buggy versions of `utime'
-+# in the kernel. So, we use `echo' instead.
-+STAMP = echo timestamp >
-+
-+# This is where we get zlib from. zlibdir is -L../zlib and zlibinc is
-+# -I../zlib, unless we were configured with --with-system-zlib, in which
-+# case both are empty.
-+ZLIB = @zlibdir@ -lz
-+ZLIBINC = @zlibinc@
-+
-+# Substitution type for target's getgroups 2nd arg.
-+TARGET_GETGROUPS_T = @TARGET_GETGROUPS_T@
-+
-+# Target to use when installing include directory. Either
-+# install-headers-tar, install-headers-cpio or install-headers-cp.
-+INSTALL_HEADERS_DIR = @build_install_headers_dir@
-+
-+# Header files that are made available under the same name
-+# to programs compiled with GCC.
-+USER_H = $(srcdir)/ginclude/float.h \
-+ $(srcdir)/ginclude/iso646.h \
-+ $(srcdir)/ginclude/stdarg.h \
-+ $(srcdir)/ginclude/stdbool.h \
-+ $(srcdir)/ginclude/stddef.h \
-+ $(srcdir)/ginclude/varargs.h \
-+ $(srcdir)/unwind.h \
-+ $(EXTRA_HEADERS)
-+
-+# The GCC to use for compiling libgcc.a and crt*.o.
-+# Usually the one we just built.
-+# Don't use this as a dependency--use $(GCC_PASSES) or $(GCC_PARTS).
-+GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include
-+
-+# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
-+# It omits XCFLAGS, and specifies -B./.
-+# It also specifies -isystem ./include to find, e.g., stddef.h.
-+GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(LOOSE_WARN) -isystem ./include $(TCFLAGS)
-+
-+# Sed command to transform gcc to installed name. Overwritten by configure.
-+program_transform_name = @program_transform_name@
-+program_transform_cross_name = s,^,$(target_alias)-,
-+
-+build_canonical = @build_canonical@
-+host_canonical = @host_canonical@
-+
-+# Tools to use when building a cross-compiler.
-+# These are used because `configure' appends `cross-make'
-+# to the makefile when making a cross-compiler.
-+
-+# Use the tools from the build tree, if they are available.
-+
-+# objdir is set by configure.
-+objdir = @objdir@
-+
-+AR_FOR_TARGET = ` \
-+ if [ -f $(objdir)/../binutils/ar ] ; then \
-+ echo $(objdir)/../binutils/ar ; \
-+ else \
-+ if [ "$(host_canonical)" = "$(target)" ] ; then \
-+ echo ar; \
-+ else \
-+ t='$(program_transform_cross_name)'; echo ar | sed -e $$t ; \
-+ fi; \
-+ fi`
-+AR_FLAGS_FOR_TARGET =
-+AR_CREATE_FOR_TARGET = $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) rc
-+AR_EXTRACT_FOR_TARGET = $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) x
-+RANLIB_FOR_TARGET = ` \
-+ if [ -f $(objdir)/../binutils/ranlib ] ; then \
-+ echo $(objdir)/../binutils/ranlib ; \
-+ else \
-+ if [ "$(host_canonical)" = "$(target)" ] ; then \
-+ echo ranlib; \
-+ else \
-+ t='$(program_transform_cross_name)'; echo ranlib | sed -e $$t ; \
-+ fi; \
-+ fi`
-+RANLIB_TEST_FOR_TARGET = \
-+ [ -f $(RANLIB_FOR_TARGET) ] \
-+ || ( [ "$(host_canonical)" = "$(target)" ] \
-+ && [ -f /usr/bin/ranlib -o -f /bin/ranlib ] )
-+NM_FOR_TARGET = ` \
-+ if [ -f ./nm ] ; then \
-+ echo ./nm ; \
-+ elif [ -f $(objdir)/../binutils/nm-new ] ; then \
-+ echo $(objdir)/../binutils/nm-new ; \
-+ else \
-+ if [ "$(host_canonical)" = "$(target)" ] ; then \
-+ echo nm; \
-+ else \
-+ t='$(program_transform_cross_name)'; echo nm | sed -e $$t ; \
-+ fi; \
-+ fi`
-+
-+# Where to find some libiberty headers.
-+HASHTAB_H = $(srcdir)/../include/hashtab.h
-+OBSTACK_H = $(srcdir)/../include/obstack.h
-+SPLAY_TREE_H= $(srcdir)/../include/splay-tree.h
-+FIBHEAP_H = $(srcdir)/../include/fibheap.h
-+PARTITION_H = $(srcdir)/../include/partition.h
-+
-+# Default native SYSTEM_HEADER_DIR, to be overridden by targets.
-+NATIVE_SYSTEM_HEADER_DIR = /usr/include
-+# Default cross SYSTEM_HEADER_DIR, to be overridden by targets.
-+CROSS_SYSTEM_HEADER_DIR = $(build_tooldir)/sys-include
-+
-+# autoconf sets SYSTEM_HEADER_DIR to one of the above.
-+SYSTEM_HEADER_DIR = @SYSTEM_HEADER_DIR@
-+
-+# Control whether to run fixproto and fixincludes.
-+STMP_FIXPROTO = @STMP_FIXPROTO@
-+STMP_FIXINC = @STMP_FIXINC@
-+
-+# Test to see whether <limits.h> exists in the system header files.
-+LIMITS_H_TEST = [ -f $(SYSTEM_HEADER_DIR)/limits.h ]
-+
-+target=@target@
-+target_alias=@target_alias@
-+xmake_file=@dep_host_xmake_file@
-+tmake_file=@dep_tmake_file@
-+out_file=$(srcdir)/config/@out_file@
-+out_object_file=@out_object_file@
-+md_file=$(srcdir)/config/@md_file@
-+tm_defines=@tm_defines@
-+tm_p_file_list=@tm_p_file_list@
-+tm_p_file=@tm_p_file@
-+build_xm_file_list=@build_xm_file_list@
-+build_xm_file=@build_xm_file@
-+build_xm_defines=@build_xm_defines@
-+host_xm_file_list=@host_xm_file_list@
-+host_xm_file=@host_xm_file@
-+host_xm_defines=@host_xm_defines@
-+xm_file=@xm_file@
-+xm_defines=@xm_defines@
-+lang_specs_files=@lang_specs_files@
-+lang_options_files=@lang_options_files@
-+lang_tree_files=@lang_tree_files@
-+target_cpu_default=@target_cpu_default@
-+GCC_THREAD_FILE=@thread_file@
-+OBJC_BOEHM_GC=@objc_boehm_gc@
-+GTHREAD_FLAGS=@gthread_flags@
-+# Be prepared for gcc2 merges.
-+gcc_version=@gcc_version@
-+gcc_version_trigger=@gcc_version_trigger@
-+version=$(gcc_version)
-+mainversion=`grep version_string $(srcdir)/version.c | sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/'`
-+
-+# Common prefix for installation directories.
-+# NOTE: This directory must exist when you start installation.
-+prefix = @prefix@
-+# Directory in which to put localized header files. On the systems with
-+# gcc as the native cc, `local_prefix' may not be `prefix' which is
-+# `/usr'.
-+# NOTE: local_prefix *should not* default from prefix.
-+local_prefix = @local_prefix@
-+# Directory in which to put host dependent programs and libraries
-+exec_prefix = @exec_prefix@
-+# Directory in which to put the executable for the command `gcc'
-+bindir = @bindir@
-+# Directory in which to put the directories used by the compiler.
-+libdir = @libdir@
-+# Directory in which the compiler finds executables, libraries, etc.
-+libsubdir = $(libdir)/gcc-lib/$(target_alias)/$(version)
-+# Used to produce a relative $(gcc_tooldir) in gcc.o
-+unlibsubdir = ../../..
-+# Directory in which to find other cross-compilation tools and headers.
-+dollar = @dollar@
-+# Used in install-cross.
-+gcc_tooldir = @gcc_tooldir@
-+# Used to install the shared libgcc.
-+slibdir = @slibdir@
-+# Since gcc_tooldir does not exist at build-time, use -B$(build_tooldir)/bin/
-+build_tooldir = $(exec_prefix)/$(target_alias)
-+# Directory in which the compiler finds target-independent g++ includes.
-+gcc_gxx_include_dir = @gcc_gxx_include_dir@
-+# Directory to search for site-specific includes.
-+local_includedir = $(local_prefix)/include
-+includedir = $(prefix)/include
-+# where the info files go
-+infodir = @infodir@
-+# Where cpp should go besides $prefix/bin if necessary
-+cpp_install_dir = @cpp_install_dir@
-+# where the locale files go
-+datadir = @datadir@
-+localedir = $(datadir)/locale
-+# Extension (if any) to put in installed man-page filename.
-+man1ext = .1
-+man7ext = .7
-+objext = .o
-+exeext = @host_exeext@
-+build_exeext = @build_exeext@
-+
-+# Directory in which to put man pages.
-+mandir = @mandir@
-+man1dir = $(mandir)/man1
-+man7dir = $(mandir)/man7
-+# Dir for temp files.
-+tmpdir = /tmp
-+
-+# Top build directory, relative to here.
-+top_builddir = .
-+
-+# Whether we were configured with NLS.
-+USE_NLS = @USE_NLS@
-+
-+# Internationalization library.
-+INTLLIBS = @INTLLIBS@
-+INTLDEPS = @INTLDEPS@
-+
-+# Character encoding conversion library.
-+LIBICONV = @LIBICONV@
-+
-+# List of internationalization subdirectories.
-+INTL_SUBDIRS = intl
-+
-+# The GC method to be used on this system.
-+GGC=@GGC@.o
-+
-+# If a supplementary library is being used for the GC.
-+GGC_LIB=
-+
-+# libgcc.a may be built directly or via stmp-multilib,
-+# and installed likewise. Overridden by t-fragment.
-+LIBGCC = libgcc.a
-+INSTALL_LIBGCC = install-libgcc
-+
-+# Options to use when compiling libgcc2.a.
-+#
-+LIBGCC2_DEBUG_CFLAGS = -g
-+LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED @inhibit_libc@
-+
-+# Additional options to use when compiling libgcc2.a.
-+# Some targets override this to -isystem include
-+LIBGCC2_INCLUDES =
-+
-+# Additional target-dependent options for compiling libgcc2.a.
-+TARGET_LIBGCC2_CFLAGS =
-+
-+# Options to use when compiling crtbegin/end.
-+CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-+ -finhibit-size-directive -fno-inline-functions -fno-exceptions \
-+ -fno-zero-initialized-in-bss
-+
-+# Additional sources to handle exceptions; overridden on ia64.
-+LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
-+ $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
-+LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
-+
-+# nm flags to list global symbols in libgcc object files.
-+SHLIB_NM_FLAGS = -pg
-+
-+# List of extra executables that should be compiled for this target machine
-+# that are used for compiling from source code to object code.
-+# The rules for compiling them should be in the t-* file for the machine.
-+EXTRA_PASSES =@extra_passes@
-+
-+# Like EXTRA_PASSES, but these are used when linking.
-+EXTRA_PROGRAMS = @extra_programs@
-+
-+# List of extra object files that should be compiled for this target machine.
-+# The rules for compiling them should be in the t-* file for the machine.
-+EXTRA_PARTS = @extra_parts@
-+
-+# List of extra object files that should be compiled and linked with
-+# compiler proper (cc1, cc1obj, cc1plus).
-+EXTRA_OBJS = @extra_objs@
-+
-+# List of extra object files that should be compiled and linked with
-+# the gcc driver.
-+EXTRA_GCC_OBJS =@host_extra_gcc_objs@
-+
-+# List of additional header files to install.
-+# Often this is edited directly by `configure'.
-+EXTRA_HEADERS =@extra_headers_list@
-+
-+# It is convenient for configure to add the assignment at the beginning,
-+# so don't override it here.
-+USE_COLLECT2 = collect2$(exeext)
-+
-+# List of extra C and assembler files to add to static and shared libgcc2.
-+# Assembler files should have names ending in `.asm'.
-+LIB2FUNCS_EXTRA =
-+
-+# List of extra C and assembler files to add to static libgcc2.
-+# Assembler files should have names ending in `.asm'.
-+LIB2FUNCS_STATIC_EXTRA =
-+
-+# Program to convert libraries.
-+LIBCONVERT =
-+
-+# Control whether header files are installed.
-+INSTALL_HEADERS=install-headers install-mkheaders
-+
-+# Control whether Info documentation is built and installed.
-+BUILD_INFO = @BUILD_INFO@
-+
-+# Control whether manpages generated by texi2pod.pl can be rebuilt.
-+GENERATED_MANPAGES = @GENERATED_MANPAGES@
-+
-+# Additional directories of header files to run fixincludes on.
-+# These should be directories searched automatically by default
-+# just as /usr/include is.
-+# *Do not* use this for directories that happen to contain
-+# header files, but are not searched automatically by default.
-+# On most systems, this is empty.
-+OTHER_FIXINCLUDES_DIRS=
-+
-+# A list of all the language-specific executables.
-+# This is overridden by configure.
-+COMPILERS = cc1$(exeext) @all_compilers@
-+
-+# List of things which should already be built whenever we try to use xgcc
-+# to compile anything (without linking).
-+GCC_PASSES=xgcc$(exeext) cc1$(exeext) specs $(EXTRA_PASSES)
-+
-+# List of things which should already be built whenever we try to use xgcc
-+# to link anything.
-+GCC_PARTS=$(GCC_PASSES) $(LIBGCC) $(EXTRA_PROGRAMS) $(USE_COLLECT2) $(EXTRA_PARTS)
-+
-+# Directory to link to, when using the target `maketest'.
-+DIR = ../gcc
-+
-+# Flags to use when cross-building GCC.
-+# Prefix to apply to names of object files when using them
-+# to run on the machine we are compiling on.
-+BUILD_PREFIX = @BUILD_PREFIX@
-+# Prefix to apply to names of object files when compiling them
-+# to run on the machine we are compiling on.
-+# The default for this variable is chosen to keep these rules
-+# out of the way of the other rules for compiling the same source files.
-+BUILD_PREFIX_1 = @BUILD_PREFIX_1@
-+# Native compiler for the build machine and its switches.
-+HOST_CC = @HOST_CC@
-+HOST_CFLAGS= @HOST_CFLAGS@ -DGENERATOR_FILE
-+
-+# Native linker and preprocessor flags. For x-fragment overrides.
-+HOST_LDFLAGS=$(LDFLAGS)
-+HOST_CPPFLAGS=$(ALL_CPPFLAGS)
-+
-+# Actual name to use when installing a native compiler.
-+GCC_INSTALL_NAME = `echo gcc|sed '$(program_transform_name)'`
-+GCC_TARGET_INSTALL_NAME = $(target_alias)-`echo gcc|sed '$(program_transform_name)'`
-+CPP_INSTALL_NAME = `echo cpp|sed '$(program_transform_name)'`
-+PROTOIZE_INSTALL_NAME = `echo protoize|sed '$(program_transform_name)'`
-+UNPROTOIZE_INSTALL_NAME = `echo unprotoize|sed '$(program_transform_name)'`
-+GCOV_INSTALL_NAME = `echo gcov|sed '$(program_transform_name)'`
-+GCCBUG_INSTALL_NAME = `echo gccbug|sed '$(program_transform_name)'`
-+
-+# Actual name to use when installing a cross-compiler.
-+GCC_CROSS_NAME = `echo gcc|sed '$(program_transform_cross_name)'`
-+CPP_CROSS_NAME = `echo cpp|sed '$(program_transform_cross_name)'`
-+PROTOIZE_CROSS_NAME = `echo protoize|sed '$(program_transform_cross_name)'`
-+UNPROTOIZE_CROSS_NAME = `echo unprotoize|sed '$(program_transform_cross_name)'`
-+
-+# Set by autoconf to "all.internal" for a native build, or
-+# "all.cross" to build a cross compiler.
-+ALL = @ALL@
-+
-+# Setup the testing framework, if you have one
-+EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \
-+ echo $${rootme}/../expect/expect ; \
-+ else echo expect ; fi`
-+
-+RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \
-+ echo $${srcdir}/../dejagnu/runtest ; \
-+ else echo runtest; fi`
-+RUNTESTFLAGS =
-+
-+# Extra symbols for fixproto to define when parsing headers.
-+FIXPROTO_DEFINES =
-+
-+# Extra flags to use when compiling crt{begin,end}.o.
-+CRTSTUFF_T_CFLAGS =
-+
-+# Extra flags to use when compiling [m]crt0.o.
-+CRT0STUFF_T_CFLAGS =
-+
-+# "t" or nothing, for building multilibbed versions of, say, crtbegin.o.
-+T =
-+
-+# Should T contain a `=', libgcc.mk will make T_TARGET, setting
-+# $(T_TARGET) to the name of the actual target filename.
-+T_TARGET =
-+T_TARGET : $(T_TARGET)
-+
-+# End of variables for you to override.
-+
-+# Definition of `all' is here so that new rules inserted by sed
-+# do not specify the default target.
-+# The real definition is under `all.internal' (for native compilers)
-+# or `all.cross' (for cross compilers).
-+all: all.indirect
-+
-+# This tells GNU Make version 3 not to put all variables in the environment.
-+.NOEXPORT:
-+
-+# GCONFIG_H lists the config files that the generator files depend on, while
-+# CONFIG_H lists the ones ordinary gcc files depend on, which includes
-+# several files generated by those generators.
-+GCONFIG_H = config.h $(host_xm_file_list)
-+HCONFIG_H = hconfig.h $(build_xm_file_list)
-+CONFIG_H = $(GCONFIG_H) insn-constants.h insn-flags.h
-+TCONFIG_H = tconfig.h $(xm_file_list)
-+TARGET_H = target.h
-+HOOKS_H = hooks.h
-+LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
-+TARGET_DEF_H = target-def.h $(HOOKS_H)
-+TM_P_H = tm_p.h $(tm_p_file_list) tm-preds.h
-+
-+MACHMODE_H = machmode.h machmode.def @extra_modes_file@
-+RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H)
-+RTL_H = $(RTL_BASE_H) genrtl.h
-+PARAMS_H = params.h params.def
-+TREE_H = tree.h tree.def $(MACHMODE_H) tree-check.h version.h builtins.def \
-+ location.h
-+BASIC_BLOCK_H = basic-block.h bitmap.h sbitmap.h varray.h $(PARTITION_H) \
-+ hard-reg-set.h
-+DEMANGLE_H = $(srcdir)/../include/demangle.h
-+RECOG_H = recog.h
-+EXPR_H = expr.h
-+OPTABS_H = optabs.h insn-codes.h
-+REGS_H = regs.h varray.h $(MACHMODE_H)
-+INTEGRATE_H = integrate.h varray.h
-+LOOP_H = loop.h varray.h bitmap.h
-+GCC_H = gcc.h version.h
-+GGC_H = ggc.h varray.h gtype-desc.h
-+TIMEVAR_H = timevar.h timevar.def
-+INSN_ATTR_H = insn-attr.h $(srcdir)/insn-addr.h $(srcdir)/varray.h
-+C_COMMON_H = c-common.h $(SPLAY_TREE_H) $(CPPLIB_H)
-+C_TREE_H = c-tree.h $(C_COMMON_H)
-+SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h
-+PREDICT_H = predict.h predict.def
-+CPPLIB_H = cpplib.h line-map.h
-+
-+# sed inserts variable overrides after the following line.
-+####target overrides
-+@target_overrides@
-+
-+####host overrides
-+@host_overrides@
-+#\f
-+# Now figure out from those variables how to compile and link.
-+
-+all.indirect: $(ALL)
-+
-+# IN_GCC distinguishes between code compiled into GCC itself and other
-+# programs built during a bootstrap.
-+# autoconf inserts -DCROSS_COMPILE if we are building a cross compiler.
-+INTERNAL_CFLAGS = -DIN_GCC @CROSS@
-+
-+# This is the variable actually used when we compile.
-+# If you change this line, you probably also need to change the definition
-+# of HOST_CFLAGS in build-make to match.
-+ALL_CFLAGS = $(X_CFLAGS) $(T_CFLAGS) \
-+ $(CFLAGS) $(INTERNAL_CFLAGS) $(COVERAGE_FLAGS) $(WARN_CFLAGS) $(XCFLAGS) @DEFS@
-+
-+# Likewise.
-+ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
-+
-+# Build and host support libraries. FORBUILD is either
-+# .. or ../$(build_alias) depending on whether host != build.
-+LIBIBERTY = ../libiberty/libiberty.a
-+BUILD_LIBIBERTY = @FORBUILD@/libiberty/libiberty.a
-+
-+# Dependencies on the intl and portability libraries.
-+LIBDEPS= $(INTLDEPS) $(LIBIBERTY)
-+
-+# Likewise, for use in the tools that must run on this machine
-+# even if we are cross-building GCC.
-+HOST_LIBDEPS= $(BUILD_LIBIBERTY)
-+
-+# How to link with both our special library facilities
-+# and the system's installed libraries.
-+LIBS = $(INTLLIBS) @LIBS@ $(LIBIBERTY)
-+
-+# Any system libraries needed just for GNAT.
-+SYSLIBS = @GNAT_LIBEXC@
-+
-+# Libs needed (at present) just for jcf-dump.
-+LDEXP_LIB = @LDEXP_LIB@
-+
-+# Likewise, for use in the tools that must run on this machine
-+# even if we are cross-building GCC.
-+HOST_LIBS = $(BUILD_LIBIBERTY)
-+
-+HOST_RTL = $(BUILD_PREFIX)rtl.o read-rtl.o $(BUILD_PREFIX)bitmap.o \
-+ $(BUILD_PREFIX)ggc-none.o
-+HOST_SUPPORT = gensupport.o insn-conditions.o
-+HOST_EARLY_SUPPORT = gensupport.o dummy-conditions.o
-+
-+HOST_PRINT = print-rtl1.o
-+HOST_ERRORS = $(BUILD_PREFIX)errors.o
-+HOST_VARRAY = $(BUILD_PREFIX)varray.o
-+
-+# Specify the directories to be searched for header files.
-+# Both . and srcdir are used, in that order,
-+# so that *config.h will be found in the compilation
-+# subdirectory rather than in the source directory.
-+# -I$(@D) and -I$(srcdir)/$(@D) cause the subdirectory of the file
-+# currently being compiled, in both source trees, to be examined as well.
-+INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
-+ -I$(srcdir)/config -I$(srcdir)/../include
-+
-+# Always use -I$(srcdir)/config when compiling.
-+.c.o:
-+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-+
-+# This tells GNU make version 3 not to export all the variables
-+# defined in this file into the environment.
-+.NOEXPORT:
-+#\f
-+# Support for additional languages (other than c and objc).
-+# ??? objc can be supported this way too (leave for later).
-+
-+# These next lines are overridden by configure.
-+LANG_MAKEFILES = @all_lang_makefiles@
-+LANG_STAGESTUFF = @all_stagestuff@
-+
-+# Flags to pass to recursive makes.
-+# CC is set by configure. Hosts without symlinks need special handling
-+# because we need CC="stage1/xgcc -Bstage1/" to work in the language
-+# subdirectories.
-+# ??? The choices here will need some experimenting with.
-+ORDINARY_FLAGS_TO_PASS = \
-+ "AR=$(AR)" \
-+ "AR_FLAGS_FOR_TARGET=$(AR_FLAGS_FOR_TARGET)" \
-+ "AR_CREATE_FOR_TARGET=$(AR_CREATE_FOR_TARGET)" \
-+ "AR_EXTRACT_FOR_TARGET=$(AR_EXTRACT_FOR_TARGET)" \
-+ "AR_FOR_TARGET=$(AR_FOR_TARGET)" \
-+ "BISON=$(BISON)" \
-+ "BISONFLAGS=$(BISONFLAGS)" \
-+ "CFLAGS=$(CFLAGS) $(WARN_CFLAGS)" \
-+ "DESTDIR=$(DESTDIR)" \
-+ "GCC_FOR_TARGET=$(GCC_FOR_TARGET)" \
-+ "LDFLAGS=$(LDFLAGS)" \
-+ "FLEX=$(FLEX)" \
-+ "FLEXFLAGS=$(FLEXFLAGS)" \
-+ "LN=$(LN)" \
-+ "LN_S=$(LN_S)" \
-+ "MAKEINFO=$(MAKEINFO)" \
-+ "MAKEINFOFLAGS=$(MAKEINFOFLAGS)" \
-+ "MAKEOVERRIDES=" \
-+ "RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET)" \
-+ "RANLIB_TEST_FOR_TARGET=$(RANLIB_TEST_FOR_TARGET)" \
-+ "SHELL=$(SHELL)" \
-+ "exeext=$(exeext)" \
-+ "build_exeext=$(build_exeext)" \
-+ "objext=$(objext)" \
-+ "exec_prefix=$(exec_prefix)" \
-+ "prefix=$(prefix)" \
-+ "local_prefix=$(local_prefix)" \
-+ "gxx_include_dir=$(gcc_gxx_include_dir)" \
-+ "build_tooldir=$(build_tooldir)" \
-+ "gcc_tooldir=$(gcc_tooldir)" \
-+ "bindir=$(bindir)" \
-+ "libsubdir=$(libsubdir)" \
-+ "datadir=$(datadir)" \
-+ "localedir=$(localedir)"
-+FLAGS_TO_PASS = $(ORDINARY_FLAGS_TO_PASS) "CC=@cc_set_by_configure@" \
-+ "STAGE_PREFIX=@stage_prefix_set_by_configure@"
-+PREPEND_DOTDOT_TO_RELATIVE_PATHS = sed \
-+ -e 's|^ *[^ /][^ /]*/|%&|' \
-+ -e 's| -B| -B%|g' \
-+ -e 's|% *[^- /]|%&|g' \
-+ -e 's|%% *|../|g' \
-+ -e 's|%||g'
-+SUBDIR_FLAGS_TO_PASS = $(ORDINARY_FLAGS_TO_PASS) \
-+ "CC=`echo @quoted_cc_set_by_configure@ | $(PREPEND_DOTDOT_TO_RELATIVE_PATHS)`" \
-+ "STAGE_PREFIX=`echo @quoted_stage_prefix_set_by_configure@ | $(PREPEND_DOTDOT_TO_RELATIVE_PATHS)`"
-+#\f
-+# Lists of files for various purposes.
-+
-+# Target specific, C specific object file
-+C_TARGET_OBJS=@c_target_objs@
-+
-+# Target specific, C++ specific object file
-+CXX_TARGET_OBJS=@cxx_target_objs@
-+
-+# Language-specific object files for C and Objective C.
-+C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
-+ c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
-+ c-objc-common.o c-dump.o libcpp.a $(C_TARGET_OBJS)
-+
-+# Language-specific object files for C.
-+C_OBJS = c-parse.o c-lang.o c-pretty-print.o $(C_AND_OBJC_OBJS)
-+
-+# Language-independent object files.
-+
-+OBJS = alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
-+ cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
-+ cfgrtl.o combine.o conflict.o convert.o cse.o cselib.o dbxout.o \
-+ debug.o df.o diagnostic.o doloop.o dominance.o \
-+ dwarf2asm.o dwarf2out.o dwarfout.o emit-rtl.o except.o explow.o \
-+ expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \
-+ genrtl.o ggc-common.o global.o graph.o gtype-desc.o \
-+ haifa-sched.o hashtable.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o \
-+ insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o \
-+ integrate.o intl.o jump.o langhooks.o lcm.o lists.o local-alloc.o \
-+ loop.o mbchar.o optabs.o params.o predict.o print-rtl.o print-tree.o \
-+ profile.o ra.o ra-build.o ra-colorize.o ra-debug.o ra-rewrite.o \
-+ real.o recog.o reg-stack.o regclass.o regmove.o regrename.o \
-+ reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o rtl-error.o \
-+ sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o \
-+ sibcall.o simplify-rtx.o ssa.o ssa-ccp.o ssa-dce.o stmt.o \
-+ stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
-+ tree-inline.o unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o \
-+ et-forest.o protector.o $(GGC) $(out_object_file) $(EXTRA_OBJS)
-+
-+BACKEND = main.o libbackend.a
-+
-+# Files to be copied away after each stage in building.
-+STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
-+ insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \
-+ insn-attr.h insn-attrtab.c insn-opinit.c insn-constants.h tm-preds.h \
-+ tree-check.h insn-conditions.c \
-+ s-flags s-config s-codes s-mlib s-genrtl s-gtype gtyp-gen.h \
-+ s-output s-recog s-emit s-extract s-peep s-check s-conditions \
-+ s-attr s-attrtab s-opinit s-preds s-constants s-crt0 \
-+ genemit$(build_exeext) genoutput$(build_exeext) genrecog$(build_exeext) \
-+ genextract$(build_exeext) genflags$(build_exeext) gencodes$(build_exeext) \
-+ genconfig$(build_exeext) genpeep$(build_exeext) genattrtab$(build_exeext) \
-+ genattr$(build_exeext) genopinit$(build_exeext) gengenrtl$(build_exeext) \
-+ gencheck$(build_exeext) genpreds$(build_exeext) genconstants$(build_exeext) \
-+ gengtype$(build_exeext) genconditions$(build_exeext) \
-+ genrtl.c genrtl.h gt-*.h gtype-*.h gtype-desc.c \
-+ xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \
-+ $(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) cc1obj$(exeext) \
-+ protoize$(exeext) unprotoize$(exeext) \
-+ specs collect2$(exeext) $(USE_COLLECT2) \
-+ gcov$(exeext) *.[0-9][0-9].* *.[si] libcpp.a libbackend.a libgcc.mk \
-+ $(LANG_STAGESTUFF)
-+
-+# Library members defined in libgcc2.c.
-+# Variable length limited to 255 charactes when passed to a shell script.
-+LIB2FUNCS_1 = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _ffsdi2 _clz \
-+ _cmpdi2 _ucmpdi2 _floatdidf _floatdisf _fixunsdfsi _fixunssfsi \
-+ _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi _fixxfdi _fixunsxfdi
-+
-+LIB2FUNCS_2 = _floatdixf _fixunsxfsi _fixtfdi _fixunstfdi _floatditf \
-+ _clear_cache _trampoline __main _exit _absvsi2 _absvdi2 _addvsi3 \
-+ _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors _stack_smash_handler
-+
-+# Defined in libgcc2.c, included only in the static library.
-+LIB2FUNCS_ST = _eprintf _bb __gcc_bcmp
-+
-+FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
-+ _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
-+ _lt_sf _le_sf _unord_sf _si_to_sf _sf_to_si _negate_sf _make_sf \
-+ _sf_to_df _sf_to_tf _thenan_sf _sf_to_usi _usi_to_sf
-+
-+DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \
-+ _fpcmp_parts_df _compare_df _eq_df _ne_df _gt_df _ge_df \
-+ _lt_df _le_df _unord_df _si_to_df _df_to_si _negate_df _make_df \
-+ _df_to_sf _df_to_tf _thenan_df _df_to_usi _usi_to_df
-+
-+TPBIT_FUNCS = _pack_tf _unpack_tf _addsub_tf _mul_tf _div_tf \
-+ _fpcmp_parts_tf _compare_tf _eq_tf _ne_tf _gt_tf _ge_tf \
-+ _lt_tf _le_tf _unord_tf _si_to_tf _tf_to_si _negate_tf _make_tf \
-+ _tf_to_df _tf_to_sf _thenan_tf _tf_to_usi _usi_to_tf
-+
-+# These might cause a divide overflow trap and so are compiled with
-+# unwinder info.
-+LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4
-+
-+# The only suffixes we want for implicit rules are .c and .o, so clear
-+# the list and add them. This speeds up GNU Make, and allows -r to work.
-+# For i18n support, we also need .gmo, .po, .pox.
-+# This must come before the language makefile fragments to allow them to
-+# add suffixes and rules of their own.
-+.SUFFIXES:
-+.SUFFIXES: .c .o .po .pox .gmo
-+
-+#\f
-+# Language makefile fragments.
-+
-+# The following targets define the interface between us and the languages.
-+#
-+# all.cross, start.encap, rest.encap,
-+# info, dvi,
-+# install-normal, install-common, install-info, install-man,
-+# uninstall,
-+# mostlyclean, clean, distclean, extraclean, maintainer-clean,
-+# stage1, stage2, stage3, stage4
-+#
-+# Each language is linked in with a series of hooks (since we can't use `::'
-+# targets). The name of each hooked is "lang.${target_name}" (eg: lang.info).
-+# Configure computes and adds these here.
-+
-+####language hooks
-+@language_hooks@
-+
-+# sed inserts language fragments after the following line.
-+####language fragments
-+@language_fragments@
-+
-+# End of language makefile fragments.
-+#\f
-+
-+Makefile: $(srcdir)/Makefile.in config.status $(srcdir)/version.c \
-+ $(xmake_file) $(tmake_file) $(LANG_MAKEFILES)
-+ $(SHELL) $(srcdir)/configure.frag $(srcdir) "$(SUBDIRS)" \
-+ "$(xmake_file)" "$(tmake_file)"
-+ cp config.status config.run
-+ LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.run
-+ rm -f config.run
-+
-+config.h: cs-config.h ; @true
-+hconfig.h: cs-hconfig.h ; @true
-+tconfig.h: cs-tconfig.h ; @true
-+tm_p.h: cs-tm_p.h ; @true
-+
-+cs-config.h: Makefile
-+ TM_DEFINES="$(tm_defines)" \
-+ HEADERS="$(host_xm_file)" XM_DEFINES="$(host_xm_defines)" \
-+ TARGET_CPU_DEFAULT="$(target_cpu_default)" \
-+ $(SHELL) $(srcdir)/mkconfig.sh config.h
-+
-+cs-hconfig.h: Makefile
-+ TM_DEFINES="$(tm_defines)" \
-+ HEADERS="$(build_xm_file)" XM_DEFINES="$(build_xm_defines)" \
-+ TARGET_CPU_DEFAULT="$(target_cpu_default)" \
-+ $(SHELL) $(srcdir)/mkconfig.sh hconfig.h
-+
-+cs-tconfig.h: Makefile
-+ TM_DEFINES="$(tm_defines)" \
-+ HEADERS="$(xm_file)" XM_DEFINES="$(xm_defines)" \
-+ TARGET_CPU_DEFAULT="" \
-+ $(SHELL) $(srcdir)/mkconfig.sh tconfig.h
-+
-+cs-tm_p.h: Makefile
-+ TM_DEFINES="" \
-+ HEADERS="$(tm_p_file)" XM_DEFINES="" TARGET_CPU_DEFAULT="" \
-+ $(SHELL) $(srcdir)/mkconfig.sh tm_p.h
-+
-+# Don't automatically run autoconf, since configure.in might be accidentally
-+# newer than configure. Also, this writes into the source directory which
-+# might be on a read-only file system. If configured for maintainer mode
-+# then do allow autoconf to be run.
-+
-+$(srcdir)/configure: @MAINT@ $(srcdir)/configure.in
-+ (cd $(srcdir) && autoconf)
-+
-+gccbug: $(srcdir)/gccbug.in
-+ CONFIG_FILES=gccbug CONFIG_HEADERS= ./config.status
-+
-+mklibgcc: $(srcdir)/mklibgcc.in
-+ CONFIG_FILES=mklibgcc CONFIG_HEADERS= ./config.status
-+
-+mkheaders: $(srcdir)/mkheaders.in
-+ CONFIG_FILES=mkheaders CONFIG_HEADERS= ./config.status
-+
-+# cstamp-h.in controls rebuilding of config.in.
-+# It is named cstamp-h.in and not stamp-h.in so the mostlyclean rule doesn't
-+# delete it. A stamp file is needed as autoheader won't update the file if
-+# nothing has changed.
-+# It remains in the source directory and is part of the distribution.
-+# This follows what is done in shellutils, fileutils, etc.
-+# "echo timestamp" is used instead of touch to be consistent with other
-+# packages that use autoconf (??? perhaps also to avoid problems with patch?).
-+# ??? Newer versions have a maintainer mode that may be useful here.
-+
-+# Don't run autoheader automatically either.
-+# Only run it if maintainer mode is enabled.
-+@MAINT@ $(srcdir)/config.in: $(srcdir)/cstamp-h.in
-+@MAINT@ $(srcdir)/cstamp-h.in: $(srcdir)/configure.in $(srcdir)/acconfig.h
-+@MAINT@ (cd $(srcdir) && autoheader)
-+@MAINT@ @rm -f $(srcdir)/cstamp-h.in
-+@MAINT@ echo timestamp > $(srcdir)/cstamp-h.in
-+auto-host.h: cstamp-h ; @true
-+cstamp-h: config.in config.status
-+ CONFIG_HEADERS=auto-host.h:config.in LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status
-+
-+# Really, really stupid make features, such as SUN's KEEP_STATE, may force
-+# a target to build even if it is up-to-date. So we must verify that
-+# config.status does not exist before failing.
-+config.status: $(srcdir)/configure $(srcdir)/config.gcc version.c
-+ @if [ ! -f config.status ] ; then \
-+ echo You must configure gcc. Look at http://gcc.gnu.org/install/ for details.; \
-+ false; \
-+ else \
-+ LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status --recheck; \
-+ fi
-+
-+all.internal: start.encap rest.encap doc
-+# This is what to compile if making a cross-compiler.
-+all.cross: native gcc-cross cpp$(exeext) specs \
-+ $(LIBGCC) $(EXTRA_PARTS) lang.all.cross doc
-+# This is what must be made before installing GCC and converting libraries.
-+start.encap: native xgcc$(exeext) cpp$(exeext) specs \
-+ xlimits.h lang.start.encap
-+# These can't be made until after GCC can run.
-+rest.encap: $(STMP_FIXPROTO) $(LIBGCC) $(EXTRA_PARTS) lang.rest.encap
-+# This is what is made with the host's compiler
-+# whether making a cross compiler or not.
-+native: config.status auto-host.h intl.all build-@POSUB@ $(LANGUAGES) \
-+ $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2)
-+
-+# Define the names for selecting languages in LANGUAGES.
-+C c: cc1$(exeext)
-+PROTO: proto
-+
-+# Tell GNU make these are phony targets.
-+.PHONY: C c PROTO proto
-+
-+# On the target machine, finish building a cross compiler.
-+# This does the things that can't be done on the host machine.
-+rest.cross: $(LIBGCC) specs
-+
-+# Recompile all the language-independent object files.
-+# This is used only if the user explicitly asks for it.
-+compilations: $(BACKEND)
-+
-+# Like libcpp.a, this archive is strictly for the host.
-+libbackend.a: $(OBJS)
-+ -rm -rf libbackend.a
-+ $(AR) $(AR_FLAGS) libbackend.a $(OBJS)
-+ -$(RANLIB) libbackend.a
-+
-+# We call this executable `xgcc' rather than `gcc'
-+# to avoid confusion if the current directory is in the path
-+# and CC is `gcc'. It is renamed to `gcc' when it is installed.
-+xgcc$(exeext): gcc.o gccspec.o version.o intl.o prefix.o \
-+ version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
-+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o gccspec.o intl.o \
-+ prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
-+
-+# cpp is to cpp0 as gcc is to cc1.
-+# The only difference from xgcc is that it's linked with cppspec.o
-+# instead of gccspec.o.
-+cpp$(exeext): gcc.o cppspec.o version.o intl.o prefix.o \
-+ version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
-+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ gcc.o cppspec.o intl.o \
-+ prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
-+
-+# Dump a specs file to make -B./ read these specs over installed ones.
-+specs: xgcc$(exeext)
-+ $(GCC_FOR_TARGET) -dumpspecs > tmp-specs
-+ mv tmp-specs specs
-+
-+# We do want to create an executable named `xgcc', so we can use it to
-+# compile libgcc2.a.
-+# Also create gcc-cross, so that install-common will install properly.
-+gcc-cross: xgcc$(exeext)
-+ cp xgcc$(exeext) gcc-cross$(exeext)
-+
-+cc1$(exeext): $(C_OBJS) $(BACKEND) $(LIBDEPS)
-+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o cc1$(exeext) \
-+ $(C_OBJS) $(BACKEND) $(LIBS)
-+
-+# Build the version of limits.h that we will install.
-+xlimits.h: glimits.h limitx.h limity.h
-+ if $(LIMITS_H_TEST) ; then \
-+ cat $(srcdir)/limitx.h $(srcdir)/glimits.h $(srcdir)/limity.h > tmp-xlimits.h; \
-+ else \
-+ cat $(srcdir)/glimits.h > tmp-xlimits.h; \
-+ fi
-+ mv tmp-xlimits.h xlimits.h
-+#\f
-+# Build libgcc.a.
-+
-+LIB2ADD = $(LIB2FUNCS_EXTRA)
-+LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
-+
-+libgcc.mk: config.status Makefile mklibgcc $(LIB2ADD) $(LIB2ADD_ST) xgcc$(exeext) specs
-+ objext='$(objext)' \
-+ LIB1ASMFUNCS='$(LIB1ASMFUNCS)' \
-+ LIB2FUNCS_1='$(LIB2FUNCS_1)' \
-+ LIB2FUNCS_2='$(LIB2FUNCS_2)' \
-+ LIB2FUNCS_ST='$(LIB2FUNCS_ST)' \
-+ LIB2ADD='$(LIB2ADD)' \
-+ LIB2ADD_ST='$(LIB2ADD_ST)' \
-+ LIB2ADDEH='$(LIB2ADDEH)' \
-+ LIB2ADDEHDEP='$(LIB2ADDEHDEP)' \
-+ FPBIT='$(FPBIT)' \
-+ FPBIT_FUNCS='$(FPBIT_FUNCS)' \
-+ LIB2_DIVMOD_FUNCS='$(LIB2_DIVMOD_FUNCS)' \
-+ DPBIT='$(DPBIT)' \
-+ DPBIT_FUNCS='$(DPBIT_FUNCS)' \
-+ TPBIT='$(TPBIT)' \
-+ TPBIT_FUNCS='$(TPBIT_FUNCS)' \
-+ MULTILIBS=`$(GCC_FOR_TARGET) --print-multi-lib` \
-+ EXTRA_MULTILIB_PARTS='$(EXTRA_MULTILIB_PARTS)' \
-+ SHLIB_LINK='$(SHLIB_LINK)' \
-+ SHLIB_INSTALL='$(SHLIB_INSTALL)' \
-+ SHLIB_EXT='$(SHLIB_EXT)' \
-+ SHLIB_MULTILIB='$(SHLIB_MULTILIB)' \
-+ SHLIB_MKMAP='$(SHLIB_MKMAP)' \
-+ SHLIB_MKMAP_OPTS='$(SHLIB_MKMAP_OPTS)' \
-+ SHLIB_MAPFILES='$(SHLIB_MAPFILES)' \
-+ SHLIB_NM_FLAGS='$(SHLIB_NM_FLAGS)' \
-+ MULTILIB_OSDIRNAMES='$(MULTILIB_OSDIRNAMES)' \
-+ mkinstalldirs='$(SHELL) $(srcdir)/mkinstalldirs' \
-+ $(SHELL) mklibgcc > tmp-libgcc.mk
-+ mv tmp-libgcc.mk libgcc.mk
-+
-+# All the things that might cause us to want to recompile bits of libgcc.
-+LIBGCC_DEPS = $(GCC_PASSES) $(LANGUAGES) stmp-int-hdrs $(STMP_FIXPROTO) \
-+ libgcc.mk $(srcdir)/libgcc2.c $(TCONFIG_H) \
-+ $(MACHMODE_H) longlong.h gbl-ctors.h config.status stmp-int-hdrs \
-+ tsystem.h $(FPBIT) $(DPBIT) $(TPBIT) $(LIB2ADD) \
-+ $(LIB2ADD_ST) $(LIB2ADDEH) $(LIB2ADDEHDEP) $(EXTRA_PARTS) \
-+ $(srcdir)/config/$(LIB1ASMSRC)
-+
-+libgcc.a: $(LIBGCC_DEPS)
-+ $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
-+ BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
-+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
-+ AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \
-+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
-+ CFLAGS="$(CFLAGS) $(WARN_CFLAGS)" \
-+ RANLIB_FOR_TARGET="$(RANLIB_FOR_TARGET)" \
-+ RANLIB_TEST_FOR_TARGET="$(RANLIB_TEST_FOR_TARGET)" \
-+ NM_FOR_TARGET="$(NM_FOR_TARGET)" AWK="$(AWK)" \
-+ LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" \
-+ INCLUDES="$(INCLUDES)" \
-+ CONFIG_H="$(TCONFIG_H)" MACHMODE_H="$(MACHMODE_H)" \
-+ LIB1ASMSRC='$(LIB1ASMSRC)' \
-+ MAKEOVERRIDES= \
-+ -f libgcc.mk all
-+
-+# Use the genmultilib shell script to generate the information the gcc
-+# driver program needs to select the library directory based on the
-+# switches.
-+multilib.h: s-mlib; @true
-+s-mlib: $(srcdir)/genmultilib Makefile
-+ if test @enable_multilib@ = yes \
-+ || test -n "$(MULTILIB_OSDIRNAMES)"; then \
-+ $(SHELL) $(srcdir)/genmultilib \
-+ "$(MULTILIB_OPTIONS)" \
-+ "$(MULTILIB_DIRNAMES)" \
-+ "$(MULTILIB_MATCHES)" \
-+ "$(MULTILIB_EXCEPTIONS)" \
-+ "$(MULTILIB_EXTRA_OPTS)" \
-+ "$(MULTILIB_EXCLUSIONS)" \
-+ "$(MULTILIB_OSDIRNAMES)" \
-+ "@enable_multilib@" \
-+ > tmp-mlib.h; \
-+ else \
-+ $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' no \
-+ > tmp-mlib.h; \
-+ fi
-+ $(SHELL) $(srcdir)/move-if-change tmp-mlib.h multilib.h
-+ $(STAMP) s-mlib
-+
-+# Build multiple copies of libgcc.a, one for each target switch.
-+stmp-multilib: $(LIBGCC_DEPS)
-+ $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
-+ BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
-+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
-+ AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \
-+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
-+ CFLAGS="$(CFLAGS) $(WARN_CFLAGS)" \
-+ RANLIB_FOR_TARGET="$(RANLIB_FOR_TARGET)" \
-+ RANLIB_TEST_FOR_TARGET="$(RANLIB_TEST_FOR_TARGET)" \
-+ NM_FOR_TARGET="$(NM_FOR_TARGET)" AWK="$(AWK)" \
-+ LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" \
-+ INCLUDES="$(INCLUDES)" \
-+ CONFIG_H="$(CONFIG_H)" MACHMODE_H="$(MACHMODE_H)" \
-+ LIB1ASMSRC='$(LIB1ASMSRC)' \
-+ MAKEOVERRIDES= \
-+ -f libgcc.mk all
-+ $(STAMP) stmp-multilib
-+
-+# Compile two additional files that are linked with every program
-+# linked using GCC on systems using COFF or ELF, for the sake of C++
-+# constructors.
-+$(T)crtbegin.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
-+ gbl-ctors.h stmp-int-hdrs tsystem.h
-+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
-+ @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_BEGIN \
-+ -o $(T)crtbegin$(objext)
-+
-+$(T)crtend.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
-+ gbl-ctors.h stmp-int-hdrs tsystem.h
-+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
-+ @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_END \
-+ -o $(T)crtend$(objext)
-+
-+# These are versions of crtbegin and crtend for shared libraries.
-+$(T)crtbeginS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
-+ gbl-ctors.h stmp-int-hdrs tsystem.h
-+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS_S) \
-+ @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFS_O \
-+ -o $(T)crtbeginS$(objext)
-+
-+$(T)crtendS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
-+ gbl-ctors.h stmp-int-hdrs tsystem.h
-+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS_S) \
-+ @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_END -DCRTSTUFFS_O \
-+ -o $(T)crtendS$(objext)
-+
-+# This is a version of crtbegin for -static links.
-+$(T)crtbeginT.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
-+ gbl-ctors.h stmp-int-hdrs tsystem.h
-+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
-+ @inhibit_libc@ -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O \
-+ -o $(T)crtbeginT$(objext)
-+
-+# Compile the start modules crt0.o and mcrt0.o that are linked with
-+# every program
-+crt0.o: s-crt0 ; @true
-+mcrt0.o: s-crt0; @true
-+
-+s-crt0: $(CRT0_S) $(MCRT0_S) $(GCC_PASSES) $(CONFIG_H)
-+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(CRT0STUFF_T_CFLAGS) \
-+ -o crt0.o -c $(CRT0_S)
-+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(CRT0STUFF_T_CFLAGS) \
-+ -o mcrt0.o -c $(MCRT0_S)
-+ $(STAMP) s-crt0
-+#\f
-+# Compiling object files from source files.
-+
-+# Note that dependencies on obstack.h are not written
-+# because that file is not part of GCC.
-+
-+# C language specific files.
-+
-+c-errors.o: c-errors.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) flags.h \
-+ diagnostic.h $(TM_P_H)
-+c-parse.o : $(srcdir)/c-parse.c $(CONFIG_H) $(TREE_H) $(GGC_H) intl.h \
-+ $(C_TREE_H) input.h flags.h $(SYSTEM_H) toplev.h output.h $(CPPLIB_H) \
-+ gt-c-parse.h
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ -c $(srcdir)/c-parse.c $(OUTPUT_OPTION)
-+
-+$(srcdir)/c-parse.c: $(srcdir)/c-parse.y
-+ cd $(srcdir) && \
-+ if $(BISON) $(BISONFLAGS) -o c-p$$$$.c c-parse.y; then \
-+ test -f c-p$$$$.output && mv -f c-p$$$$.output c-parse.output ; \
-+ mv -f c-p$$$$.c c-parse.c ; \
-+ else \
-+ rm -f c-p$$$$.* ; \
-+ false ; \
-+ fi
-+
-+$(srcdir)/c-parse.y: c-parse.in
-+ echo '/*WARNING: This file is automatically generated!*/' >tmp-c-parse.y
-+ sed -e "/^ifobjc$$/,/^end ifobjc$$/d" \
-+ -e "/^ifc$$/d" -e "/^end ifc$$/d" \
-+ $(srcdir)/c-parse.in >>tmp-c-parse.y
-+ $(SHELL) $(srcdir)/move-if-change tmp-c-parse.y $(srcdir)/c-parse.y
-+
-+c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(C_TREE_H) \
-+ $(GGC_H) $(TARGET_H) flags.h function.h output.h $(EXPR_H) \
-+ debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) c-pragma.h \
-+ gt-c-decl.h libfuncs.h except.h
-+c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
-+ $(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H)
-+c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
-+ $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) c-common.h gtype-c.h
-+c-lex.o : c-lex.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \
-+ debug.h $(C_TREE_H) c-common.h real.h \
-+ c-pragma.h input.h intl.h flags.h toplev.h output.h \
-+ mbchar.h $(CPPLIB_H) $(EXPR_H) $(TM_P_H)
-+c-objc-common.o : c-objc-common.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
-+ $(C_TREE_H) $(RTL_H) insn-config.h integrate.h $(EXPR_H) $(C_TREE_H) \
-+ flags.h toplev.h tree-inline.h diagnostic.h integrate.h $(VARRAY_H) \
-+ langhooks.h $(GGC_H) gt-c-objc-common.h $(TARGET_H)
-+c-aux-info.o : c-aux-info.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
-+ flags.h toplev.h
-+c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h toplev.h \
-+ $(C_COMMON_H)
-+c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) function.h \
-+ c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) gt-c-pragma.h
-+mbchar.o: mbchar.c $(CONFIG_H) $(SYSTEM_H) mbchar.h
-+graph.o: graph.c $(CONFIG_H) $(SYSTEM_H) toplev.h flags.h output.h $(RTL_H) \
-+ function.h hard-reg-set.h $(BASIC_BLOCK_H) graph.h
-+sbitmap.o: sbitmap.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h \
-+ $(BASIC_BLOCK_H)
-+
-+COLLECT2_OBJS = collect2.o tlink.o intl.o version.o
-+COLLECT2_LIBS = @COLLECT2_LIBS@
-+collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
-+# Don't try modifying collect2 (aka ld) in place--it might be linking this.
-+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o T$@ \
-+ $(COLLECT2_OBJS) $(LIBS) $(COLLECT2_LIBS)
-+ mv -f T$@ $@
-+
-+collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) gstab.h intl.h \
-+ $(OBSTACK_H) $(DEMANGLE_H) collect2.h version.h
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ -DTARGET_MACHINE=\"$(target_alias)\" \
-+ -c $(srcdir)/collect2.c $(OUTPUT_OPTION)
-+
-+tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) \
-+ $(OBSTACK_H) collect2.h intl.h
-+
-+# A file used by all variants of C.
-+
-+c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \
-+ $(C_COMMON_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
-+ $(EXPR_H) $(TM_P_H) builtin-types.def builtin-attrs.def $(TARGET_H) \
-+ diagnostic.h except.h gt-c-common.h real.h langhooks.h c-tree.h
-+c-pretty-print.o : c-pretty-print.c c-pretty-print.h pretty-print.h \
-+ $(C_COMMON_H) $(CONFIG_H) $(SYSTEM_H) real.h
-+
-+c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_COMMON_H) \
-+ c-pragma.h flags.h toplev.h langhooks.h tree-inline.h diagnostic.h \
-+ intl.h
-+
-+# A file used by all variants of C and some other languages.
-+
-+attribs.o : attribs.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \
-+ toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) $(EXPR_H) $(TM_P_H) \
-+ builtin-types.def $(TARGET_H) langhooks.h
-+
-+c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) langhooks.h \
-+ $(C_COMMON_H) flags.h toplev.h intl.h diagnostic.h
-+
-+c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
-+ flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
-+ $(EXPR_H) $(PREDICT_H)
-+
-+c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) tree-dump.h
-+
-+# Language-independent files.
-+
-+DRIVER_DEFINES = \
-+ -DSTANDARD_STARTFILE_PREFIX=\"$(unlibsubdir)/\" \
-+ -DSTANDARD_EXEC_PREFIX=\"$(libdir)/gcc-lib/\" \
-+ -DDEFAULT_TARGET_VERSION=\"$(version)\" \
-+ -DDEFAULT_TARGET_MACHINE=\"$(target_alias)\" \
-+ -DSTANDARD_BINDIR_PREFIX=\"$(bindir)/\" \
-+ -DTOOLDIR_BASE_PREFIX=\"$(unlibsubdir)/../\" \
-+ $(VALGRIND_DRIVER_DEFINES) \
-+ `test "X$${SHLIB_LINK}" = "X" || test "@enable_shared@" != "yes" || echo "-DENABLE_SHARED_LIBGCC"` \
-+ `test "X$${SHLIB_MULTILIB}" = "X" || echo "-DNO_SHARED_LIBGCC_MULTILIB"`
-+
-+gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) intl.h multilib.h \
-+ Makefile $(lang_specs_files) specs.h prefix.h $(GCC_H)
-+ (SHLIB_LINK='$(SHLIB_LINK)' \
-+ SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ $(DRIVER_DEFINES) \
-+ -c $(srcdir)/gcc.c $(OUTPUT_OPTION))
-+
-+gccspec.o: gccspec.c $(CONFIG_H) $(SYSTEM_H) $(GCC_H)
-+ (SHLIB_LINK='$(SHLIB_LINK)' \
-+ SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ $(DRIVER_DEFINES) \
-+ -c $(srcdir)/gccspec.c $(OUTPUT_OPTION))
-+
-+cppspec.o: cppspec.c $(CONFIG_H) $(SYSTEM_H) $(GCC_H)
-+
-+tree-check.h: s-check ; @true
-+s-check : gencheck$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./gencheck$(build_exeext) > tmp-check.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-check.h tree-check.h
-+ $(STAMP) s-check
-+
-+gencheck$(build_exeext) : gencheck.o $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ gencheck.o $(HOST_LIBS)
-+
-+gencheck.o : gencheck.c gencheck.h tree.def $(HCONFIG_H) $(SYSTEM_H) \
-+ $(lang_tree_files)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
-+ $(srcdir)/gencheck.c $(OUTPUT_OPTION)
-+
-+gencheck.h : s-gencheck ; @true
-+s-gencheck : Makefile
-+ ltf="$(lang_tree_files)"; for f in $$ltf; do \
-+ echo "#include \"$$f\""; \
-+ done | sed 's|$(srcdir)/||' > tmp-gencheck.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-gencheck.h gencheck.h
-+ $(STAMP) s-gencheck
-+
-+options.h : s-options ; @true
-+s-options : Makefile
-+ lof="$(lang_options_files)"; for f in $$lof; do \
-+ echo "#include \"$$f\""; \
-+ done | sed 's|$(srcdir)/||' > tmp-options.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-options.h options.h
-+ $(STAMP) s-options
-+
-+specs.h : s-specs ; @true
-+s-specs : Makefile
-+ lsf="$(lang_specs_files)"; for f in $$lsf; do \
-+ echo "#include \"$$f\""; \
-+ done | sed 's|$(srcdir)/||' > tmp-specs.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-specs.h specs.h
-+ $(STAMP) s-specs
-+
-+dumpvers: dumpvers.c
-+
-+version.o: version.c version.h
-+
-+gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) varray.h $(HASHTAB_H) \
-+ $(TREE_H) $(RTL_H) function.h insn-config.h $(EXPR_H) $(OPTABS_H) \
-+ libfuncs.h debug.h $(GGC_H) bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h \
-+ ssa.h cselib.h insn-addr.h
-+
-+ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
-+ flags.h $(GGC_H) varray.h $(HASHTAB_H) $(TM_P_H) langhooks.h \
-+ $(PARAMS_H)
-+
-+ggc-simple.o: ggc-simple.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ $(GGC_H) varray.h $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H)
-+
-+ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ toplev.h $(GGC_H) $(TIMEVAR_H) $(TM_P_H)
-+
-+stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \
-+ flags.h toplev.h $(GGC_H)
-+
-+hashtable.o: hashtable.c hashtable.h $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H)
-+
-+line-map.o: line-map.c line-map.h intl.h $(CONFIG_H) $(SYSTEM_H)
-+
-+ggc-none.o: ggc-none.c $(GCONFIG_H) $(SYSTEM_H) $(GGC_H)
-+ $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-+
-+prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) Makefile prefix.h
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ -DPREFIX=\"$(prefix)\" \
-+ -c $(srcdir)/prefix.c $(OUTPUT_OPTION)
-+
-+convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h convert.h \
-+ toplev.h langhooks.h
-+
-+langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h \
-+ tree-inline.h $(RTL_H) insn-config.h integrate.h langhooks.h \
-+ $(LANGHOOKS_DEF_H) flags.h
-+tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h function.h toplev.h \
-+ $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
-+ real.h gt-tree.h
-+tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
-+ flags.h langhooks.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
-+ $(EXPR_H) $(SPLAY_TREE_H) tree-dump.h
-+tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \
-+ expr.h flags.h params.h input.h insn-config.h $(INTEGRATE_H) \
-+ $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h langhooks.h \
-+ $(C_COMMON_H) tree-inline.h
-+print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GGC_H) \
-+ langhooks.h real.h
-+stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h \
-+ function.h $(EXPR_H) $(RTL_H) toplev.h $(GGC_H) $(TM_P_H) $(TARGET_H) \
-+ langhooks.h
-+fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h real.h \
-+ toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) $(GGC_H) $(TM_P_H) langhooks.h
-+diagnostic.o : diagnostic.c diagnostic.h real.h diagnostic.def \
-+ $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_P_H) flags.h $(GGC_H) \
-+ input.h toplev.h intl.h langhooks.h $(LANGHOOKS_DEF_H)
-+toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) function.h \
-+ flags.h xcoffout.h input.h $(INSN_ATTR_H) output.h diagnostic.h \
-+ debug.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h \
-+ dwarf2out.h sdbout.h dbxout.h $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) \
-+ graph.h $(LOOP_H) except.h $(REGS_H) $(TIMEVAR_H) $(lang_options_files) \
-+ ssa.h $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) \
-+ langhooks.h insn-flags.h options.h cfglayout.h real.h
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ -DTARGET_NAME=\"$(target_alias)\" \
-+ -c $(srcdir)/toplev.c $(OUTPUT_OPTION)
-+main.o : main.c $(CONFIG_H) $(SYSTEM_H) toplev.h
-+
-+rtl-error.o: rtl-error.c system.h $(RTL_H) $(INSN_ATTR_H) insn-config.h \
-+ input.h toplev.h intl.h diagnostic.h $(CONFIG_H)
-+
-+rtl.o : rtl.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) real.h $(GGC_H) errors.h
-+ $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-+
-+print-rtl.o : print-rtl.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
-+ hard-reg-set.h $(BASIC_BLOCK_H) real.h
-+rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) \
-+ hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) real.h flags.h
-+
-+errors.o : errors.c $(GCONFIG_H) $(SYSTEM_H) errors.h
-+ $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-+
-+varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
-+ function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \
-+ output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
-+ $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h
-+function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ function.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \
-+ insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
-+ $(TM_P_H) langhooks.h gt-function.h
-+stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
-+ insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
-+ $(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H) \
-+ langhooks.h $(PREDICT_H) gt-stmt.h
-+except.o : except.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ except.h function.h $(EXPR_H) libfuncs.h integrate.h langhooks.h \
-+ insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
-+ dwarf2asm.h dwarf2out.h toplev.h $(HASHTAB_H) intl.h $(GGC_H) \
-+ gt-except.h
-+expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
-+ $(REGS_H) $(EXPR_H) $(OPTABS_H) libfuncs.h insn-attr.h insn-config.h \
-+ $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
-+ except.h reload.h $(GGC_H) langhooks.h intl.h $(TM_P_H) real.h
-+builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ $(TARGET_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) insn-config.h \
-+ $(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
-+ except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h
-+calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ $(EXPR_H) langhooks.h $(TARGET_H) \
-+ libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) \
-+ except.h
-+expmed.o : expmed.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) real.h \
-+ toplev.h $(TM_P_H) langhooks.h
-+explow.o : explow.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ hard-reg-set.h insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
-+ toplev.h function.h ggc.h $(TM_P_H) gt-explow.h
-+optabs.o : optabs.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ insn-config.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(RECOG_H) reload.h \
-+ toplev.h $(GGC_H) real.h $(TM_P_H) except.h gt-optabs.h $(BASIC_BLOCK_H)
-+dbxout.o : dbxout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
-+ $(REGS_H) debug.h $(TM_P_H) $(TARGET_H) function.h langhooks.h \
-+ insn-config.h reload.h gstab.h xcoffout.h output.h dbxout.h toplev.h
-+debug.o : debug.c debug.h $(CONFIG_H) $(SYSTEM_H)
-+sdbout.o : sdbout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
-+ function.h $(EXPR_H) output.h hard-reg-set.h $(REGS_H) real.h \
-+ insn-config.h xcoffout.h c-pragma.h ggc.h \
-+ sdbout.h toplev.h $(TM_P_H) except.h debug.h langhooks.h gt-sdbout.h
-+dwarfout.o : dwarfout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) dwarf.h \
-+ flags.h insn-config.h reload.h output.h toplev.h $(TM_P_H) \
-+ debug.h langhooks.h
-+dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) dwarf2.h \
-+ debug.h flags.h insn-config.h reload.h output.h diagnostic.h real.h \
-+ hard-reg-set.h $(REGS_H) $(EXPR_H) libfuncs.h toplev.h dwarf2out.h varray.h \
-+ $(GGC_H) except.h dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) gt-dwarf2out.h
-+dwarf2asm.o : dwarf2asm.c $(CONFIG_H) $(SYSTEM_H) flags.h $(RTL_H) $(TREE_H) \
-+ output.h dwarf2asm.h $(TM_P_H) $(GGC_H)
-+vmsdbgout.o : vmsdbgout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) flags.h \
-+ output.h vmsdbg.h debug.h langhooks.h function.h
-+xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) xcoffout.h \
-+ flags.h toplev.h output.h dbxout.h $(GGC_H) $(TARGET_H)
-+emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ function.h $(REGS_H) insn-config.h $(RECOG_H) real.h $(GGC_H) \
-+ $(EXPR_H) $(srcdir)/../include/obstack.h hard-reg-set.h bitmap.h toplev.h \
-+ $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h
-+real.o : real.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) toplev.h $(TM_P_H)
-+integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ debug.h $(INTEGRATE_H) insn-config.h $(EXPR_H) real.h $(REGS_H) \
-+ intl.h function.h output.h $(RECOG_H) except.h toplev.h $(LOOP_H) \
-+ $(PARAMS_H) $(TM_P_H) $(TARGET_H) langhooks.h gt-integrate.h
-+jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
-+ insn-config.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \
-+ toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h $(PREDICT_H)
-+
-+simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
-+ hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
-+ output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H) $(TREE_H)
-+cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
-+ hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
-+ output.h function.h cselib.h $(GGC_H) $(TM_P_H) gt-cselib.h
-+cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
-+ real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h \
-+ $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H)
-+gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h \
-+ flags.h real.h insn-config.h ggc.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
-+ function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h
-+sibcall.o : sibcall.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) function.h \
-+ hard-reg-set.h flags.h insn-config.h $(RECOG_H) $(BASIC_BLOCK_H)
-+resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \
-+ $(BASIC_BLOCK_H) $(REGS_H) flags.h output.h resource.h function.h toplev.h \
-+ $(INSN_ATTR_H) except.h $(PARAMS_H) $(TM_P_H)
-+lcm.o : lcm.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
-+ real.h insn-config.h $(INSN_ATTR_H) $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
-+ $(TM_P_H) df.h
-+ssa.o : ssa.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) varray.h $(EXPR_H) \
-+ hard-reg-set.h flags.h function.h real.h insn-config.h $(RECOG_H) \
-+ $(BASIC_BLOCK_H) output.h ssa.h
-+ssa-dce.o : ssa-dce.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \
-+ $(BASIC_BLOCK_H) ssa.h insn-config.h $(RECOG_H) output.h
-+ssa-ccp.o : ssa-ccp.c $(CONFIG_H) system.h $(RTL_H) hard-reg-set.h \
-+ $(BASIC_BLOCK_H) ssa.h insn-config.h $(RECOG_H) output.h \
-+ errors.h $(GGC_H) df.h function.h
-+df.o : df.c $(CONFIG_H) system.h $(RTL_H) insn-config.h $(RECOG_H) \
-+ function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h \
-+ $(FIBHEAP_H)
-+conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) $(OBSTACK_H) $(HASHTAB_H) \
-+ $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H)
-+profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ insn-config.h output.h $(REGS_H) $(EXPR_H) function.h \
-+ gcov-io.h toplev.h $(GGC_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TARGET_H) \
-+ langhooks.h profile.h libfuncs.h gt-profile.h
-+loop.o : loop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h $(LOOP_H) \
-+ insn-config.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) \
-+ real.h $(PREDICT_H) $(BASIC_BLOCK_H) function.h \
-+ toplev.h varray.h except.h cselib.h $(OPTABS_H) $(TM_P_H)
-+doloop.o : doloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h $(LOOP_H) \
-+ $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) toplev.h
-+unroll.o : unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h function.h \
-+ $(INTEGRATE_H) $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) $(LOOP_H) toplev.h \
-+ hard-reg-set.h varray.h $(BASIC_BLOCK_H) $(TM_P_H) $(PREDICT_H) $(PARAMS_H)
-+flow.o : flow.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h insn-config.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
-+ function.h except.h $(EXPR_H) ssa.h $(GGC_H) $(TM_P_H)
-+cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
-+ function.h except.h $(GGC_H) $(TM_P_H)
-+cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
-+ function.h except.h $(GGC_H) $(TM_P_H) insn-config.h
-+cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
-+ hard-reg-set.h insn-config.h $(RECOG_H) $(GGC_H) $(TM_P_H)
-+cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h insn-config.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h $(RECOG_H) \
-+ function.h except.h $(GGC_H)
-+cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TIMEVAR_H)\
-+ $(BASIC_BLOCK_H) hard-reg-set.h output.h flags.h $(RECOG_H) toplev.h \
-+ $(GGC_H) insn-config.h cselib.h $(TARGET_H) $(TM_P_H) $(PARAMS_H)
-+cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
-+ $(BASIC_BLOCK_H) hard-reg-set.h
-+dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \
-+ $(BASIC_BLOCK_H) et-forest.h
-+et-forest.o : et-forest.c $(CONFIG_H) $(SYSTEM_H) et-forest.h
-+combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h function.h \
-+ insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
-+ $(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h $(TM_P_H)
-+regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h flags.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(RECOG_H) reload.h real.h \
-+ toplev.h function.h output.h $(GGC_H) $(TM_P_H) $(EXPR_H)
-+local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
-+ output.h function.h $(INSN_ATTR_H) toplev.h except.h $(TM_P_H)
-+bitmap.o : bitmap.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) $(GGC_H)
-+ $(CC) -c $(ALL_CFLAGS) -DGENERATOR_FILE $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-+global.o : global.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h reload.h function.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h \
-+ $(TM_P_H)
-+varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) varray.h $(GGC_H) errors.h
-+ra.o : ra.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_P_H) insn-config.h \
-+ $(RECOG_H) integrate.h function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h \
-+ $(BASIC_BLOCK_H) df.h expr.h output.h toplev.h flags.h reload.h ra.h
-+ra-build.o : ra-build.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_P_H) \
-+ insn-config.h $(RECOG_H) function.h $(REGS_H) hard-reg-set.h \
-+ $(BASIC_BLOCK_H) df.h output.h ggc.h ra.h gt-ra-build.h reload.h
-+ra-colorize.o : ra-colorize.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_P_H) \
-+ function.h $(REGS_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h output.h ra.h
-+ra-debug.o : ra-debug.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h \
-+ $(RECOG_H) function.h hard-reg-set.h $(BASIC_BLOCK_H) df.h output.h ra.h \
-+ $(TM_P_H)
-+ra-rewrite.o : ra-rewrite.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_P_H) \
-+ function.h $(REGS_H) hard-reg-set.h $(BASIC_BLOCK_H) df.h expr.h \
-+ output.h except.h ra.h reload.h insn-config.h
-+reload.o : reload.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h output.h \
-+ $(EXPR_H) $(OPTABS_H) reload.h $(RECOG_H) hard-reg-set.h insn-config.h \
-+ $(REGS_H) function.h real.h toplev.h $(TM_P_H)
-+reload1.o : reload1.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) real.h flags.h \
-+ $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) hard-reg-set.h insn-config.h \
-+ $(BASIC_BLOCK_H) $(RECOG_H) output.h function.h toplev.h cselib.h $(TM_P_H) \
-+ except.h $(TREE_H)
-+caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h \
-+ $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) function.h \
-+ $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H)
-+reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) conditions.h hard-reg-set.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(INSN_ATTR_H) except.h \
-+ $(RECOG_H) function.h flags.h output.h $(EXPR_H) toplev.h $(PARAMS_H) $(TM_P_H)
-+alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h $(EXPR_H) \
-+ $(GGC_H) function.h cselib.h $(TREE_H) $(TM_P_H) langhooks.h $(TARGET_H) \
-+ gt-alias.h
-+regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h \
-+ $(RECOG_H) output.h $(REGS_H) hard-reg-set.h flags.h function.h \
-+ $(EXPR_H) $(BASIC_BLOCK_H) toplev.h $(TM_P_H) except.h reload.h
-+haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
-+ $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H)
-+sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
-+ $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h cselib.h $(PARAMS_H) $(TM_P_H)
-+sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
-+ $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H)
-+sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h function.h \
-+ $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H)
-+sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) sched-int.h \
-+ hard-reg-set.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(REGS_H) $(TM_P_H) \
-+ $(TARGET_H) real.h
-+final.o : final.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h intl.h \
-+ $(REGS_H) $(RECOG_H) conditions.h insn-config.h $(INSN_ATTR_H) function.h \
-+ real.h output.h hard-reg-set.h except.h debug.h xcoffout.h profile.h \
-+ toplev.h reload.h dwarf2out.h $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H)
-+recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) function.h $(BASIC_BLOCK_H) \
-+ $(REGS_H) $(RECOG_H) $(EXPR_H) hard-reg-set.h flags.h insn-config.h \
-+ $(INSN_ATTR_H) real.h toplev.h output.h reload.h $(TM_P_H)
-+reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) $(RECOG_H) \
-+ $(REGS_H) hard-reg-set.h flags.h insn-config.h toplev.h reload.h \
-+ varray.h function.h $(TM_P_H) $(GGC_H) gt-reg-stack.h
-+predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
-+ insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h \
-+ $(RECOG_H) function.h except.h $(EXPR_H) $(TM_P_H) $(PREDICT_H) real.h \
-+ $(PARAMS_H) $(TARGET_H)
-+lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) toplev.h $(RTL_H) $(GGC_H)
-+bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
-+ flags.h $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h $(TARGET_H)
-+tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
-+ $(BASIC_BLOCK_H) hard-reg-set.h output.h cfglayout.h flags.h \
-+ $(PARAMS_H) profile.h
-+cfglayout.o : cfglayout.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) \
-+ insn-config.h $(BASIC_BLOCK_H) hard-reg-set.h output.h function.h \
-+ cfglayout.h
-+timevar.o : timevar.c $(CONFIG_H) $(SYSTEM_H) $(TIMEVAR_H) flags.h intl.h
-+regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) insn-config.h \
-+ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h $(RECOG_H) function.h \
-+ resource.h $(OBSTACK_H) flags.h $(TM_P_H)
-+ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) toplev.h \
-+ flags.h insn-config.h function.h $(RECOG_H) $(BASIC_BLOCK_H) $(EXPR_H) \
-+ output.h except.h $(TM_P_H) real.h
-+params.o : params.c $(CONFIG_H) $(SYSTEM_H) $(PARAMS_H) toplev.h
-+hooks.o: hooks.c $(CONFIG_H) $(SYSTEM_H) $(HOOKS_H)
-+protector.o: protector.c $(CONFIG_H)
-+
-+$(out_object_file): $(out_file) $(CONFIG_H) $(TREE_H) $(GGC_H) \
-+ $(RTL_H) $(REGS_H) hard-reg-set.h real.h insn-config.h conditions.h \
-+ output.h $(INSN_ATTR_H) $(SYSTEM_H) toplev.h $(TARGET_H) libfuncs.h \
-+ $(TARGET_DEF_H) function.h sched-int.h $(TM_P_H) $(EXPR_H) $(OPTABS_H) \
-+ langhooks.h
-+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ $(out_file) $(OUTPUT_OPTION)
-+
-+# Build auxiliary files that support ecoff format.
-+mips-tfile: mips-tfile.o version.o $(LIBDEPS)
-+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tfile.o version.o $(LIBS)
-+
-+mips-tfile.o : mips-tfile.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) version.h
-+
-+mips-tdump: mips-tdump.o version.o $(LIBDEPS)
-+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tdump.o version.o $(LIBS)
-+
-+mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H)
-+
-+#\f
-+# Generate header and source files from the machine description,
-+# and compile them.
-+
-+.PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \
-+ insn-emit.c insn-recog.c insn-extract.c insn-output.c insn-peep.c \
-+ insn-attr.h insn-attrtab.c
-+
-+# The following pair of rules has this effect:
-+# genconfig is run only if the md has changed since genconfig was last run;
-+# but the file insn-config.h is touched only when its contents actually change.
-+
-+# Each of the other insn-* files is handled by a similar pair of rules.
-+
-+# This causes an anomaly in the results of make -n
-+# because insn-* is older than s-*
-+# and thus make -n thinks that insn-* will be updated
-+# and force recompilation of things that depend on it.
-+# We use move-if-change precisely to avoid such recompilation.
-+# But there is no way to teach make -n that it will be avoided.
-+
-+# Each of the insn-*.[ch] rules has a semicolon at the end,
-+# for otherwise the system Make on SunOS 4.1 never tries
-+# to recompile insn-*.o. To avoid problems and extra noise from
-+# versions of make which don't like empty commands (nothing after the
-+# trailing `;'), we call true for each.
-+
-+insn-config.h: s-config ; @true
-+s-config : $(md_file) genconfig$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genconfig$(build_exeext) $(md_file) > tmp-config.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-config.h insn-config.h
-+ $(STAMP) s-config
-+
-+insn-conditions.c: s-conditions ; @true
-+s-conditions : $(md_file) genconditions$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genconditions$(build_exeext) $(md_file) > tmp-conditions.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-conditions.c insn-conditions.c
-+ $(STAMP) s-conditions
-+
-+insn-conditions.o : insn-conditions.c $(GCONFIG_H) $(SYSTEM_H) $(RTL_H) \
-+ $(TM_P_H) $(REGS_H) function.h $(RECOG_H) real.h output.h flags.h \
-+ hard-reg-set.h resource.h toplev.h reload.h gensupport.h insn-constants.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) insn-conditions.c
-+
-+dummy-conditions.o : dummy-conditions.c $(HCONFIG_H) $(SYSTEM_H) gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
-+ $(srcdir)/dummy-conditions.c $(OUTPUT_OPTION)
-+
-+insn-flags.h: s-flags ; @true
-+s-flags : $(md_file) genflags$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genflags$(build_exeext) $(md_file) > tmp-flags.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-flags.h insn-flags.h
-+ $(STAMP) s-flags
-+
-+insn-codes.h: s-codes ; @true
-+s-codes : $(md_file) gencodes$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./gencodes$(build_exeext) $(md_file) > tmp-codes.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-codes.h insn-codes.h
-+ $(STAMP) s-codes
-+
-+insn-constants.h: s-constants ; @true
-+s-constants : $(md_file) genconstants$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genconstants$(build_exeext) $(md_file) > tmp-constants.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-constants.h insn-constants.h
-+ $(STAMP) s-constants
-+
-+insn-emit.o : insn-emit.c $(CONFIG_H) $(RTL_H) $(EXPR_H) real.h output.h \
-+ insn-config.h $(OPTABS_H) $(SYSTEM_H) reload.h $(RECOG_H) toplev.h \
-+ function.h flags.h hard-reg-set.h resource.h $(TM_P_H)
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-emit.c \
-+ $(OUTPUT_OPTION)
-+
-+insn-emit.c: s-emit ; @true
-+s-emit : $(md_file) genemit$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genemit$(build_exeext) $(md_file) > tmp-emit.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-emit.c insn-emit.c
-+ $(STAMP) s-emit
-+
-+insn-recog.o : insn-recog.c $(CONFIG_H) $(RTL_H) insn-config.h $(RECOG_H) \
-+ real.h output.h flags.h $(SYSTEM_H) function.h hard-reg-set.h resource.h \
-+ $(TM_P_H) toplev.h reload.h
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-recog.c \
-+ $(OUTPUT_OPTION)
-+
-+insn-recog.c: s-recog ; @true
-+s-recog : $(md_file) genrecog$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genrecog$(build_exeext) $(md_file) > tmp-recog.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-recog.c insn-recog.c
-+ $(STAMP) s-recog
-+
-+insn-opinit.o : insn-opinit.c $(CONFIG_H) $(RTL_H) \
-+ insn-config.h flags.h $(RECOG_H) $(EXPR_H) $(OPTABS_H) reload.h $(SYSTEM_H)
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-opinit.c \
-+ $(OUTPUT_OPTION)
-+
-+insn-opinit.c: s-opinit ; @true
-+s-opinit : $(md_file) genopinit$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genopinit$(build_exeext) $(md_file) > tmp-opinit.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-opinit.c insn-opinit.c
-+ $(STAMP) s-opinit
-+
-+insn-extract.o : insn-extract.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) toplev.h \
-+ insn-config.h $(RECOG_H)
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-extract.c \
-+ $(OUTPUT_OPTION)
-+
-+insn-extract.c: s-extract ; @true
-+s-extract : $(md_file) genextract$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genextract$(build_exeext) $(md_file) > tmp-extract.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-extract.c insn-extract.c
-+ $(STAMP) s-extract
-+
-+insn-peep.o : insn-peep.c $(CONFIG_H) $(RTL_H) $(REGS_H) output.h real.h \
-+ $(SYSTEM_H) insn-config.h $(RECOG_H) except.h function.h $(TM_P_H)
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-peep.c \
-+ $(OUTPUT_OPTION)
-+
-+insn-peep.c: s-peep ; @true
-+s-peep : $(md_file) genpeep$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genpeep$(build_exeext) $(md_file) > tmp-peep.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-peep.c insn-peep.c
-+ $(STAMP) s-peep
-+
-+insn-attrtab.o : insn-attrtab.c $(CONFIG_H) $(RTL_H) $(REGS_H) real.h \
-+ output.h $(INSN_ATTR_H) insn-config.h $(SYSTEM_H) toplev.h $(RECOG_H) \
-+ $(TM_P_H) flags.h
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-attrtab.c \
-+ $(OUTPUT_OPTION)
-+
-+insn-attr.h: s-attr ; @true
-+s-attr : $(md_file) genattr$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genattr$(build_exeext) $(md_file) > tmp-attr.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-attr.h insn-attr.h
-+ $(STAMP) s-attr
-+
-+insn-attrtab.c: s-attrtab ; @true
-+s-attrtab : $(md_file) genattrtab$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genattrtab$(build_exeext) $(md_file) > tmp-attrtab.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-attrtab.c insn-attrtab.c
-+ $(STAMP) s-attrtab
-+
-+insn-output.o : insn-output.c $(CONFIG_H) $(RTL_H) $(GGC_H) $(REGS_H) real.h \
-+ conditions.h hard-reg-set.h insn-config.h $(INSN_ATTR_H) $(EXPR_H) \
-+ output.h $(RECOG_H) function.h $(SYSTEM_H) toplev.h flags.h \
-+ insn-codes.h $(TM_P_H)
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -c insn-output.c \
-+ $(OUTPUT_OPTION)
-+
-+insn-output.c: s-output ; @true
-+s-output : $(md_file) genoutput$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genoutput$(build_exeext) $(md_file) > tmp-output.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-output.c insn-output.c
-+ $(STAMP) s-output
-+
-+genrtl.o : genrtl.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) $(GGC_H)
-+genrtl.c genrtl.h : s-genrtl
-+ @true # force gnu make to recheck modification times.
-+
-+s-genrtl: gengenrtl$(build_exeext) $(srcdir)/move-if-change $(RTL_BASE_H)
-+ $(RUN_GEN) ./gengenrtl$(build_exeext) -h > tmp-genrtl.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-genrtl.h genrtl.h
-+ $(RUN_GEN) ./gengenrtl$(build_exeext) > tmp-genrtl.c
-+ $(SHELL) $(srcdir)/move-if-change tmp-genrtl.c genrtl.c
-+ $(STAMP) s-genrtl
-+
-+tm-preds.h: s-preds; @true
-+
-+s-preds: genpreds$(build_exeext) $(srcdir)/move-if-change
-+ $(RUN_GEN) ./genpreds$(build_exeext) > tmp-preds.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-preds.h tm-preds.h
-+ $(STAMP) s-preds
-+
-+GTFILES = $(GCONFIG_H) $(srcdir)/location.h \
-+ $(HASHTAB_H) \
-+ $(srcdir)/bitmap.h $(srcdir)/function.h $(srcdir)/rtl.h $(srcdir)/optabs.h \
-+ $(srcdir)/tree.h $(srcdir)/libfuncs.h $(srcdir)/hashtable.h $(srcdir)/real.h \
-+ $(srcdir)/varray.h $(srcdir)/ssa.h $(srcdir)/insn-addr.h $(srcdir)/cselib.h \
-+ $(srcdir)/c-common.h $(srcdir)/c-tree.h \
-+ $(srcdir)/basic-block.h \
-+ $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c \
-+ $(srcdir)/dwarf2out.c $(srcdir)/emit-rtl.c \
-+ $(srcdir)/except.c $(srcdir)/explow.c $(srcdir)/expr.c \
-+ $(srcdir)/fold-const.c $(srcdir)/function.c \
-+ $(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \
-+ $(srcdir)/profile.c $(srcdir)/ra-build.c $(srcdir)/regclass.c \
-+ $(srcdir)/reg-stack.c \
-+ $(srcdir)/sdbout.c $(srcdir)/stmt.c $(srcdir)/stor-layout.c \
-+ $(srcdir)/tree.c $(srcdir)/varasm.c \
-+ $(out_file) \
-+ @all_gtfiles@
-+
-+GTFILES_FILES_LANGS = @all_gtfiles_files_langs@
-+GTFILES_FILES_FILES = @all_gtfiles_files_files@
-+GTFILES_LANG_DIR_NAMES = @subdirs@
-+GTFILES_SRCDIR = @srcdir@
-+
-+gtype-desc.h gtype-desc.c gt-except.h gt-function.h : s-gtype; @true
-+gt-integrate.h gt-stmt.h gt-tree.h gt-varasm.h gt-emit-rtl.h : s-gtype; @true
-+gt-explow.h gt-stor-layout.h gt-regclass.h gt-lists.h : s-gtype; @true
-+gt-alias.h gt-cselib.h gt-fold-const.h gt-gcse.h gt-profile.h : s-gtype; @true
-+gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h gt-dwarf2out.h : s-gtype ; @true
-+gt-ra-build.h gt-reg-stack.h : s-gtype ; @true
-+gt-c-common.h gt-c-decl.h gt-c-parse.h gt-c-pragma.h : s-gtype; @true
-+gt-c-objc-common.h gtype-c.h gt-location.h : s-gtype ; @true
-+
-+gtyp-gen.h: Makefile
-+ echo "/* This file is machine generated. Do not edit. */" > tmp-gtyp.h
-+ echo "static const char *srcdir = " >> tmp-gtyp.h
-+ echo "\"$(GTFILES_SRCDIR)\"" >> tmp-gtyp.h
-+ echo ";" >> tmp-gtyp.h
-+ echo "static const char *lang_files[] = {" >> tmp-gtyp.h
-+ ll="$(GTFILES_FILES_FILES)"; \
-+ for f in $$ll; do \
-+ echo "\"$$f\", "; done >> tmp-gtyp.h
-+ echo "NULL};" >> tmp-gtyp.h
-+ echo "static const char *langs_for_lang_files[] = {" >> tmp-gtyp.h
-+ ff="$(GTFILES_FILES_LANGS)"; \
-+ for f in $$ff; do \
-+ echo "\"$$f\", " ; done >> tmp-gtyp.h
-+ echo "NULL};" >> tmp-gtyp.h
-+ echo "static const char *all_files[] = {" >> tmp-gtyp.h
-+ gf="$(GTFILES)"; \
-+ for f in $$gf; do \
-+ echo "\"$$f\", "; done >> tmp-gtyp.h
-+ echo " NULL};" >> tmp-gtyp.h
-+ echo "static const char *lang_dir_names[] = { \"c\", " >> tmp-gtyp.h
-+ gf="$(GTFILES_LANG_DIR_NAMES)"; \
-+ for l in $$gf; do \
-+ echo "\"$$l\", "; done >> tmp-gtyp.h
-+ echo "NULL};" >> tmp-gtyp.h
-+ $(SHELL) $(srcdir)/move-if-change tmp-gtyp.h gtyp-gen.h
-+
-+s-gtype: gengtype$(build_exeext) $(GTFILES)
-+ $(RUN_GEN) ./gengtype
-+ $(STAMP) s-gtype
-+
-+#\f
-+# Compile the programs that generate insn-* from the machine description.
-+# They are compiled with $(HOST_CC), and associated libraries,
-+# since they need to run on this machine
-+# even if GCC is being compiled to run on some other machine.
-+
-+# $(CONFIG_H) is omitted from the deps of the gen*.o
-+# because these programs don't really depend on anything
-+# about the target machine. They do depend on config.h itself,
-+# since that describes the host machine.
-+
-+read-rtl.o: read-rtl.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \
-+ $(OBSTACK_H) $(HASHTAB_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/read-rtl.c $(OUTPUT_OPTION)
-+
-+gensupport.o: gensupport.c $(RTL_H) $(OBSTACK_H) $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gensupport.c $(OUTPUT_OPTION)
-+
-+genconfig$(build_exeext) : genconfig.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genconfig.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genconfig.o : genconfig.c $(RTL_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconfig.c $(OUTPUT_OPTION)
-+
-+genflags$(build_exeext) : genflags.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genflags.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genflags.o : genflags.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genflags.c $(OUTPUT_OPTION)
-+
-+gencodes$(build_exeext) : gencodes.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ gencodes.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+gencodes.o : gencodes.c $(RTL_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gencodes.c $(OUTPUT_OPTION)
-+
-+genconstants$(build_exeext) : genconstants.o $(HOST_RTL) $(HOST_EARLY_SUPPORT) \
-+ $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genconstants.o $(HOST_EARLY_SUPPORT) $(HOST_RTL) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genconstants.o : genconstants.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genconstants.c $(OUTPUT_OPTION)
-+
-+genemit$(build_exeext) : genemit.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genemit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genemit.o : genemit.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genemit.c $(OUTPUT_OPTION)
-+
-+genopinit$(build_exeext) : genopinit.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genopinit.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genopinit.o : genopinit.c $(RTL_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genopinit.c $(OUTPUT_OPTION)
-+
-+genrecog$(build_exeext) : genrecog.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genrecog.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genrecog.o : genrecog.c $(RTL_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genrecog.c $(OUTPUT_OPTION)
-+
-+genextract$(build_exeext) : genextract.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genextract.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genextract.o : genextract.c $(RTL_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) insn-config.h errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genextract.c $(OUTPUT_OPTION)
-+
-+genpeep$(build_exeext) : genpeep.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genpeep.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genpeep.o : genpeep.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpeep.c $(OUTPUT_OPTION)
-+
-+genattr$(build_exeext) : genattr.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genattr.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genattr.o : genattr.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattr.c $(OUTPUT_OPTION)
-+
-+genattrtab$(build_exeext) : genattrtab.o genautomata.o \
-+ $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) $(HOST_VARRAY) \
-+ $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genattrtab.o genautomata.o \
-+ $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) $(HOST_ERRORS) \
-+ $(HOST_VARRAY) $(HOST_LIBS) -lm
-+
-+genattrtab.o : genattrtab.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) errors.h $(GGC_H) gensupport.h genattrtab.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genattrtab.c $(OUTPUT_OPTION)
-+
-+genautomata.o : genautomata.c $(RTL_H) $(OBSTACK_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) errors.h varray.h genattrtab.h $(HASHTAB_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genautomata.c $(OUTPUT_OPTION)
-+
-+genoutput$(build_exeext) : genoutput.o $(HOST_RTL) $(HOST_SUPPORT) \
-+ $(HOST_PRINT) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genoutput.o $(HOST_RTL) $(HOST_SUPPORT) $(HOST_PRINT) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genoutput.o : genoutput.c $(RTL_H) $(HCONFIG_H) \
-+ $(SYSTEM_H) errors.h gensupport.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genoutput.c $(OUTPUT_OPTION)
-+
-+gengenrtl$(build_exeext) : gengenrtl.o $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ gengenrtl.o $(HOST_LIBS)
-+
-+gengenrtl.o : gengenrtl.c $(RTL_BASE_H) $(HCONFIG_H) $(SYSTEM_H) real.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gengenrtl.c $(OUTPUT_OPTION)
-+
-+genpreds$(build_exeext) : genpreds.o $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genpreds.o $(HOST_LIBS)
-+
-+genpreds.o : genpreds.c $(RTL_BASE_H) $(HCONFIG_H) $(SYSTEM_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/genpreds.c $(OUTPUT_OPTION)
-+
-+gengtype$(build_exeext) : gengtype.o gengtype-lex.o gengtype-yacc.o \
-+ $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ gengtype.o gengtype-lex.o gengtype-yacc.o $(HOST_LIBS)
-+
-+gengtype.o : gengtype.c gengtype.h $(HCONFIG_H) $(SYSTEM_H) real.h rtl.def \
-+ gtyp-gen.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
-+ $(srcdir)/gengtype.c $(OUTPUT_OPTION)
-+
-+gengtype-lex.o : $(srcdir)/gengtype-lex.c gengtype.h $(srcdir)/gengtype-yacc.c \
-+ $(HCONFIG_H) $(SYSTEM_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
-+ $(srcdir)/gengtype-lex.c $(OUTPUT_OPTION)
-+
-+gengtype-yacc.o : $(srcdir)/gengtype-yacc.c gengtype.h $(HCONFIG_H) $(SYSTEM_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
-+ $(srcdir)/gengtype-yacc.c $(OUTPUT_OPTION)
-+
-+# The sed command works around a bug in flex-2.5.4.
-+$(srcdir)/gengtype-lex.c : $(srcdir)/gengtype-lex.l
-+ cd $(srcdir) && \
-+ $(FLEX) $(FLEXFLAGS) -t -o$@ gengtype-lex.l | \
-+ sed 's/^\(char msg\[\];\)/yyconst \1/' > g-$$$$ ; \
-+ if test $$? -eq 0 ; then \
-+ mv -f g-$$$$ gengtype-lex.c ; \
-+ else \
-+ rm -f g-$$$$.* ; \
-+ false ; \
-+ fi
-+
-+$(srcdir)/gengtype-yacc.c: $(srcdir)/gengtype-yacc.y
-+ (cd $(srcdir) && \
-+ $(BISON) $(BISONFLAGS) -d -o gengtype-yacc.c gengtype-yacc.y || \
-+ ( rm -f $@ && false ) )
-+
-+genconditions$(build_exeext) : genconditions.o $(HOST_EARLY_SUPPORT) \
-+ $(HOST_RTL) $(HOST_ERRORS) $(HOST_LIBDEPS)
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ genconditions.o $(HOST_EARLY_SUPPORT) $(HOST_RTL) \
-+ $(HOST_ERRORS) $(HOST_LIBS)
-+
-+genconditions.o : genconditions.c $(RTL_H) $(HCONFIG_H) $(SYSTEM_H) errors.h
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
-+ $(srcdir)/genconditions.c $(OUTPUT_OPTION)
-+
-+#\f
-+# Compile the libraries to be used by gen*.
-+# If we are not cross-building, gen* use the same .o's that cc1 will use,
-+# and BUILD_PREFIX_1 is `loser-', just to ensure these rules don't conflict
-+# with the rules for rtl.o, etc.
-+$(BUILD_PREFIX_1)rtl.o: $(srcdir)/rtl.c $(HCONFIG_H) $(SYSTEM_H) $(RTL_H) \
-+ real.h $(GGC_H) errors.h
-+ rm -f $(BUILD_PREFIX)rtl.c
-+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/rtl.c > $(BUILD_PREFIX)rtl.c
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)rtl.c $(OUTPUT_OPTION)
-+
-+print-rtl1.o: $(srcdir)/print-rtl.c $(HCONFIG_H) \
-+ $(RTL_H) $(TREE_H) hard-reg-set.h $(BASIC_BLOCK_H)
-+ rm -f print-rtl1.c
-+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/print-rtl.c > print-rtl1.c
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) print-rtl1.c $(OUTPUT_OPTION)
-+
-+$(BUILD_PREFIX_1)bitmap.o: $(srcdir)/bitmap.c $(HCONFIG_H) $(SYSTEM_H) \
-+ $(RTL_H) flags.h $(BASIC_BLOCK_H) $(REGS_H) $(GGC_H)
-+ rm -f $(BUILD_PREFIX)bitmap.c
-+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/bitmap.c > $(BUILD_PREFIX)bitmap.c
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)bitmap.c $(OUTPUT_OPTION)
-+
-+$(BUILD_PREFIX_1)errors.o: errors.c $(HCONFIG_H) $(SYSTEM_H) errors.h
-+ rm -f $(BUILD_PREFIX)errors.c
-+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/errors.c > $(BUILD_PREFIX)errors.c
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)errors.c $(OUTPUT_OPTION)
-+
-+$(BUILD_PREFIX_1)varray.o: varray.c $(HCONFIG_H) $(SYSTEM_H) varray.h \
-+ $(RTL_H) $(GGC_H) $(TREE_H) bitmap.h errors.h
-+ rm -f $(BUILD_PREFIX)varray.c
-+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/varray.c > \
-+ $(BUILD_PREFIX)varray.c
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) \
-+ $(BUILD_PREFIX)varray.c $(OUTPUT_OPTION)
-+
-+$(BUILD_PREFIX_1)ggc-none.o: ggc-none.c $(HCONFIG_H) $(SYSTEM_H) $(GGC_H)
-+ rm -f $(BUILD_PREFIX)ggc-none.c
-+ sed -e 's/config[.]h/hconfig.h/' $(srcdir)/ggc-none.c > $(BUILD_PREFIX)ggc-none.c
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(BUILD_PREFIX)ggc-none.c $(OUTPUT_OPTION)
-+
-+#\f
-+# Remake internationalization support.
-+intl.o: intl.c $(CONFIG_H) system.h intl.h Makefile
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ -DLOCALEDIR=\"$(localedir)\" \
-+ -c $(srcdir)/intl.c $(OUTPUT_OPTION)
-+
-+$(top_builddir)/intl/libintl.a: intl.all
-+
-+intl.all intl.install intl.uninstall \
-+ intl.mostlyclean intl.clean intl.distclean intl.maintainer-clean:
-+ @for d in $(INTL_SUBDIRS); do \
-+ target=`expr $@ : 'intl.\(.*\)'` && \
-+ echo "(cd $$d && $(MAKE) $$target)" && \
-+ (cd $$d && AWK='$(AWK)' $(MAKE) $(SUBDIR_FLAGS_TO_PASS) $$target); \
-+ if [ $$? -eq 0 ] ; then true ; else exit 1 ; fi ; \
-+ done
-+
-+# intl.all and intl.install need config.h to exist, and the files it includes.
-+# (FIXME: intl/*.c shouldn't need to see insn-foo.h!)
-+intl.all intl.install: config.h insn-flags.h insn-constants.h
-+
-+# Make-lang.in should add dependencies of po-generated on any generated
-+# files which need to be scanned by gettext (usually Yacc-generated parsers).
-+po-generated: c-parse.c
-+
-+#\f
-+# Remake cpp and protoize.
-+
-+PREPROCESSOR_DEFINES = \
-+ -DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
-+ -DGPLUSPLUS_INCLUDE_DIR=\"$(gcc_gxx_include_dir)\" \
-+ -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_alias)\" \
-+ -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \
-+ -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
-+ -DCROSS_INCLUDE_DIR=\"$(gcc_tooldir)/sys-include\" \
-+ -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\"
-+
-+LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o cpptrad.o \
-+ cpphash.o cpperror.o cppinit.o cppdefault.o cppmain.o \
-+ hashtable.o line-map.o mkdeps.o prefix.o mbchar.o
-+
-+LIBCPP_DEPS = $(CPPLIB_H) cpphash.h line-map.h hashtable.h intl.h \
-+ $(OBSTACK_H) $(SYSTEM_H)
-+
-+# Most of the other archives built/used by this makefile are for
-+# targets. This one is strictly for the host.
-+libcpp.a: $(LIBCPP_OBJS)
-+ -rm -rf libcpp.a
-+ $(AR) $(AR_FLAGS) libcpp.a $(LIBCPP_OBJS)
-+ -$(RANLIB) libcpp.a
-+
-+cppmain.o: cppmain.c $(CONFIG_H) $(LIBCPP_DEPS)
-+
-+cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
-+cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS)
-+cpplex.o: cpplex.c $(CONFIG_H) $(LIBCPP_DEPS) mbchar.h
-+cppmacro.o: cppmacro.c $(CONFIG_H) $(LIBCPP_DEPS)
-+cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS)
-+cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS)
-+cpptrad.o: cpptrad.c $(CONFIG_H) $(LIBCPP_DEPS)
-+cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h
-+cppinit.o: cppinit.c $(CONFIG_H) $(LIBCPP_DEPS) cppdefault.h \
-+ mkdeps.h prefix.h
-+
-+cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) cppdefault.h Makefile
-+ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ $(PREPROCESSOR_DEFINES) \
-+ -c $(srcdir)/cppdefault.c $(OUTPUT_OPTION)
-+
-+mkdeps.o: mkdeps.c $(CONFIG_H) $(SYSTEM_H) mkdeps.h
-+
-+# Note for the stamp targets, we run the program `true' instead of
-+# having an empty command (nothing following the semicolon).
-+
-+proto: config.status protoize$(exeext) unprotoize$(exeext) SYSCALLS.c.X
-+
-+PROTO_OBJS = intl.o version.o cppdefault.o
-+
-+protoize$(exeext): protoize.o $(PROTO_OBJS) $(LIBDEPS)
-+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ protoize.o $(PROTO_OBJS) $(LIBS)
-+
-+unprotoize$(exeext): unprotoize.o $(PROTO_OBJS) $(LIBDEPS)
-+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ unprotoize.o $(PROTO_OBJS) $(LIBS)
-+
-+protoize.o: protoize.c $(srcdir)/../include/getopt.h $(CONFIG_H) $(SYSTEM_H) \
-+ Makefile version.h
-+ (SHLIB_LINK='$(SHLIB_LINK)' \
-+ SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
-+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ $(DRIVER_DEFINES) \
-+ $(srcdir)/protoize.c $(OUTPUT_OPTION))
-+
-+unprotoize.o: protoize.c $(srcdir)/../include/getopt.h \
-+ $(CONFIG_H) $(SYSTEM_H) Makefile version.h
-+ (SHLIB_LINK='$(SHLIB_LINK)' \
-+ SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \
-+ $(CC) -c -DUNPROTOIZE $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ $(DRIVER_DEFINES) \
-+ $(srcdir)/protoize.c $(OUTPUT_OPTION))
-+
-+# This info describes the target machine, so compile with GCC just built.
-+SYSCALLS.c.X: $(srcdir)/sys-types.h $(srcdir)/sys-protos.h $(GCC_PASSES) \
-+ stmp-int-hdrs
-+ -rm -f SYSCALLS.c tmp-SYSCALLS.s
-+ sed -e s/TARGET_GETGROUPS_T/$(TARGET_GETGROUPS_T)/ \
-+ $(srcdir)/sys-types.h $(srcdir)/sys-protos.h > SYSCALLS.c
-+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-+ -aux-info $@ -S -o tmp-SYSCALLS.s SYSCALLS.c
-+ -rm -f SYSCALLS.c tmp-SYSCALLS.s
-+
-+
-+test-protoize-simple: ./protoize ./unprotoize $(GCC_PASSES)
-+ -rm -f tmp-proto.[cso]
-+ cp $(srcdir)/protoize.c tmp-proto.c
-+ chmod u+w tmp-proto.c
-+ ./protoize -N -B ./ -x getopt.h -c "-B./ -Wall -Wwrite-strings \
-+ $(GCC_CFLAGS) $(INCLUDES) \
-+ -DGCC_INCLUDE_DIR=0 \
-+ -DGPLUSPLUS_INCLUDE_DIR=0 \
-+ -DCROSS_INCLUDE_DIR=0 \
-+ -DTOOL_INCLUDE_DIR=0 \
-+ -DSTANDARD_EXEC_PREFIX=0 \
-+ -DDEFAULT_TARGET_MACHINE=0 \
-+ -DDEFAULT_TARGET_VERSION=0" tmp-proto.c
-+ @echo '**********' Expect 400 lines of differences.
-+ -diff $(srcdir)/protoize.c tmp-proto.c > tmp-proto.diff
-+ -wc -l tmp-proto.diff
-+ ./unprotoize -N -x getopt.h -c "-B./ -Wall -Wwrite-strings \
-+ $(GCC_CFLAGS) $(INCLUDES) \
-+ -DGCC_INCLUDE_DIR=0 \
-+ -DGPLUSPLUS_INCLUDE_DIR=0 \
-+ -DCROSS_INCLUDE_DIR=0 \
-+ -DTOOL_INCLUDE_DIR=0 \
-+ -DSTANDARD_EXEC_PREFIX=0 \
-+ -DDEFAULT_TARGET_MACHINE=0 \
-+ -DDEFAULT_TARGET_VERSION=0" tmp-proto.c
-+ @echo Expect zero differences.
-+ diff $(srcdir)/protoize.c tmp-proto.c | cat
-+ -rm -f tmp-proto.[cs] tmp-proto$(objext)
-+
-+gcov.o: gcov.c gcov-io.h intl.h $(SYSTEM_H) $(CONFIG_H)
-+
-+# Only one of 'gcov' or 'gcov.exe' is actually built, depending
-+# upon whether $(exeext) is empty or not.
-+GCOV_OBJS = gcov.o intl.o version.o
-+gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS)
-+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(GCOV_OBJS) $(LIBS) -o $@
-+#\f
-+# Build the include directory. The stamp files are stmp-* rather than
-+# s-* so that mostlyclean does not force the include directory to
-+# be rebuilt.
-+
-+# Build the include directory
-+stmp-int-hdrs: $(STMP_FIXINC) $(USER_H) xlimits.h
-+# Copy in the headers provided with gcc.
-+# The sed command gets just the last file name component;
-+# this is necessary because VPATH could add a dirname.
-+# Using basename would be simpler, but some systems don't have it.
-+# The touch command is here to workaround an AIX/Linux NFS bug.
-+ -if [ -d include ] ; then true; else mkdir include; chmod a+rx include; fi
-+ for file in .. $(USER_H); do \
-+ if [ X$$file != X.. ]; then \
-+ realfile=`echo $$file | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
-+ $(STAMP) include/$$realfile; \
-+ rm -f include/$$realfile; \
-+ cp $$file include; \
-+ chmod a+r include/$$realfile; \
-+ fi; \
-+ done
-+ rm -f include/limits.h
-+ cp xlimits.h include/limits.h
-+ chmod a+r include/limits.h
-+# Install the README
-+ rm -f include/README
-+ cp $(srcdir)/README-fixinc include/README
-+ chmod a+r include/README
-+ $(STAMP) $@
-+
-+# fixinc.sh depends on this, not on specs directly.
-+# The idea is to make sure specs gets built, but not rerun fixinc.sh
-+# after each stage just because specs' mtime has changed.
-+specs.ready: specs
-+ -if [ -f specs.ready ] ; then \
-+ true; \
-+ else \
-+ $(STAMP) specs.ready; \
-+ fi
-+
-+FIXINCSRCDIR=$(srcdir)/fixinc
-+fixinc.sh: $(FIXINCSRCDIR)/mkfixinc.sh $(FIXINCSRCDIR)/fixincl.c \
-+ $(FIXINCSRCDIR)/procopen.c $(FIXINCSRCDIR)/gnu-regex.c \
-+ $(FIXINCSRCDIR)/server.c $(FIXINCSRCDIR)/gnu-regex.h \
-+ $(FIXINCSRCDIR)/server.h $(FIXINCSRCDIR)/inclhack.def specs.ready
-+ (MAKE="$(MAKE)"; srcdir=`cd $(srcdir)/fixinc && ${PWD_COMMAND}` ; \
-+ CC="$(HOST_CC)"; CFLAGS="$(HOST_CFLAGS)"; LDFLAGS="$(HOST_LDFLAGS)"; \
-+ WARN_CFLAGS="$(WARN_CFLAGS)"; \
-+ export MAKE srcdir CC CFLAGS LDFLAGS WARN_CFLAGS; cd ./fixinc && \
-+ $(SHELL) $${srcdir}/mkfixinc.sh $(build_canonical) $(target))
-+
-+# Build fixed copies of system files.
-+stmp-fixinc: fixinc.sh gsyslimits.h
-+ rm -rf include; mkdir include
-+ -chmod a+rx include
-+ (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); ${PWD_COMMAND}`; \
-+ SHELL='$(SHELL)' ;\
-+ export TARGET_MACHINE srcdir SHELL ; \
-+ $(SHELL) ./fixinc.sh `${PWD_COMMAND}`/include $(SYSTEM_HEADER_DIR) $(OTHER_FIXINCLUDES_DIRS); \
-+ rm -f include/syslimits.h; \
-+ if [ -f include/limits.h ]; then \
-+ mv include/limits.h include/syslimits.h; \
-+ else \
-+ cp $(srcdir)/gsyslimits.h include/syslimits.h; \
-+ fi; \
-+ chmod a+r include/syslimits.h)
-+# If $(SYSTEM_HEADER_DIR) is $(build_tooldir)/sys-include, and
-+# that directory exists, then make sure that $(libsubdir) exists.
-+# This is because cpp is compiled to find $(gcc_tooldir)/include via
-+# $(libsubdir)/$(unlibsubdir), which will only work if $(libsubdir)
-+# exists.
-+# ??? Better would be to use -isystem $(build_tooldir)/sys-include,
-+# but fixincludes does not take such arguments.
-+ if [ "$(SYSTEM_HEADER_DIR)" = "$(build_tooldir)/sys-include" ] \
-+ && [ -d $(build_tooldir)/sys-include ]; then \
-+ if [ -d $(libdir) ] ; then true ; else mkdir $(libdir) ; fi; \
-+ if [ -d $(libdir)/gcc-lib ] ; then true ; else mkdir $(libdir)/gcc-lib; fi; \
-+ if [ -d $(libdir)/gcc-lib/$(target_alias) ] ; then true ; else mkdir $(libdir)/gcc-lib/$(target_alias) ; fi; \
-+ if [ -d $(libdir)/gcc-lib/$(target_alias)/$(version) ] ; then true ; else mkdir $(libdir)/gcc-lib/$(target_alias)/$(version) ; fi; \
-+ else true; fi
-+ $(STAMP) stmp-fixinc
-+
-+# Files related to the fixproto script.
-+# gen-protos and fix-header are compiled with HOST_CC, but they are only
-+# used in native and host-x-target builds, so it's safe to link them with
-+# libiberty.a.
-+
-+deduced.h: $(GCC_PASSES) $(srcdir)/scan-types.sh stmp-int-hdrs
-+ if [ -d $(SYSTEM_HEADER_DIR) ]; \
-+ then \
-+ CC="$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(ALL_CPPFLAGS) -I. -I$(srcdir) -isystem include -isystem ${SYSTEM_HEADER_DIR}"; \
-+ export CC; \
-+ $(SHELL) $(srcdir)/scan-types.sh "$(srcdir)" >tmp-deduced.h; \
-+ mv tmp-deduced.h deduced.h; \
-+ else \
-+ $(STAMP) deduced.h; \
-+ fi
-+
-+GEN_PROTOS_OBJS = gen-protos.o scan.o
-+gen-protos$(build_exeext): $(GEN_PROTOS_OBJS)
-+ ${HOST_CC} $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ \
-+ $(GEN_PROTOS_OBJS) $(HOST_LIBS)
-+
-+gen-protos.o: gen-protos.c scan.h $(HCONFIG_H) $(SYSTEM_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/gen-protos.c $(OUTPUT_OPTION)
-+
-+scan.o: scan.c scan.h $(HCONFIG_H) $(SYSTEM_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/scan.c $(OUTPUT_OPTION)
-+
-+xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h gen-protos$(build_exeext) Makefile
-+ sed -e s/TARGET_GETGROUPS_T/$(TARGET_GETGROUPS_T)/ \
-+ deduced.h $(srcdir)/sys-protos.h > tmp-fixtmp.c
-+ mv tmp-fixtmp.c fixtmp.c
-+ $(GCC_FOR_TARGET) fixtmp.c -w -U__SIZE_TYPE__ -U__PTRDIFF_TYPE__ -U__WCHAR_TYPE__ -E \
-+ | sed -e 's/ / /g' -e 's/ *(/ (/g' -e 's/ [ ]*/ /g' -e 's/( )/()/' \
-+ | $(RUN_GEN) ./gen-protos >xsys-protos.hT
-+ mv xsys-protos.hT xsys-protos.h
-+ rm -rf fixtmp.c
-+
-+# This is nominally a 'build' program, but it's run only when host==build,
-+# so we can (indeed, must) use $(LIBDEPS) and $(LIBS).
-+fix-header$(build_exeext): fix-header.o scan-decls.o scan.o xsys-protos.h \
-+ $(LIBDEPS) libcpp.a
-+ $(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -o $@ fix-header.o \
-+ scan-decls.o scan.o libcpp.a $(LIBS)
-+
-+fix-header.o: fix-header.c $(OBSTACK_H) scan.h \
-+ xsys-protos.h $(HCONFIG_H) $(SYSTEM_H) $(CPPLIB_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/fix-header.c $(OUTPUT_OPTION)
-+
-+scan-decls.o: scan-decls.c scan.h $(CPPLIB_H) $(HCONFIG_H) $(SYSTEM_H)
-+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(srcdir)/scan-decls.c $(OUTPUT_OPTION)
-+
-+# stmp-fixproto depends on this, not on fix-header directly.
-+# The idea is to make sure fix-header gets built,
-+# but not rerun fixproto after each stage
-+# just because fix-header's mtime has changed.
-+fixhdr.ready: fix-header$(build_exeext)
-+ -if [ -f fixhdr.ready ] ; then \
-+ true; \
-+ else \
-+ $(STAMP) fixhdr.ready; \
-+ fi
-+
-+# stmp-int-headers is to make sure fixincludes has already finished.
-+# The if statement is so that we don't run fixproto a second time
-+# if it has already been run on the files in `include'.
-+stmp-fixproto: fixhdr.ready fixproto stmp-int-hdrs
-+ if [ -f include/fixed ] ; then true; \
-+ else \
-+ : This line works around a 'make' bug in BSDI 1.1.; \
-+ FIXPROTO_DEFINES="$(FIXPROTO_DEFINES)"; export FIXPROTO_DEFINES; \
-+ mkinstalldirs="$(SHELL) $(srcdir)/mkinstalldirs"; \
-+ export mkinstalldirs; \
-+ if [ -d $(SYSTEM_HEADER_DIR) ] ; then \
-+ $(SHELL) ${srcdir}/fixproto include include $(SYSTEM_HEADER_DIR); \
-+ if [ $$? -eq 0 ] ; then true ; else exit 1 ; fi ; \
-+ else true; fi; \
-+ $(STAMP) include/fixed; \
-+ fi
-+ $(STAMP) stmp-fixproto
-+#\f
-+# Remake the info files.
-+
-+docdir = $(srcdir)/doc
-+
-+doc: $(BUILD_INFO) $(GENERATED_MANPAGES) gccbug
-+info: $(docdir)/cpp.info $(docdir)/gcc.info $(docdir)/gccint.info $(docdir)/gccinstall.info lang.info $(docdir)/cppinternals.info
-+
-+TEXI_CPP_FILES = $(docdir)/cpp.texi $(docdir)/include/fdl.texi \
-+ $(docdir)/cppenv.texi $(docdir)/cppopts.texi
-+
-+TEXI_GCC_FILES = $(docdir)/gcc.texi $(docdir)/include/gcc-common.texi \
-+ $(docdir)/frontends.texi $(docdir)/standards.texi \
-+ $(docdir)/invoke.texi $(docdir)/extend.texi $(docdir)/md.texi \
-+ $(docdir)/objc.texi $(docdir)/gcov.texi $(docdir)/trouble.texi \
-+ $(docdir)/bugreport.texi $(docdir)/service.texi \
-+ $(docdir)/contribute.texi $(docdir)/compat.texi \
-+ $(docdir)/include/funding.texi $(docdir)/gnu.texi \
-+ $(docdir)/include/gpl.texi $(docdir)/include/fdl.texi \
-+ $(docdir)/contrib.texi $(docdir)/cppenv.texi $(docdir)/cppopts.texi
-+
-+TEXI_GCCINT_FILES = $(docdir)/gccint.texi \
-+ $(docdir)/include/gcc-common.texi $(docdir)/contribute.texi \
-+ $(docdir)/makefile.texi $(docdir)/configterms.texi \
-+ $(docdir)/portability.texi $(docdir)/interface.texi \
-+ $(docdir)/passes.texi $(docdir)/c-tree.texi \
-+ $(docdir)/rtl.texi $(docdir)/md.texi $(docdir)/tm.texi \
-+ $(docdir)/hostconfig.texi $(docdir)/fragments.texi \
-+ $(docdir)/configfiles.texi $(docdir)/collect2.texi \
-+ $(docdir)/headerdirs.texi $(docdir)/include/funding.texi \
-+ $(docdir)/gnu.texi $(docdir)/include/gpl.texi \
-+ $(docdir)/include/fdl.texi $(docdir)/contrib.texi \
-+ $(docdir)/languages.texi $(docdir)/sourcebuild.texi \
-+ $(docdir)/gty.texi
-+
-+TEXI_GCCINSTALL_FILES = $(docdir)/install.texi $(docdir)/install-old.texi \
-+ $(docdir)/include/fdl.texi
-+
-+TEXI_CPPINT_FILES = $(docdir)/cppinternals.texi
-+
-+$(docdir)/cpp.info: $(TEXI_CPP_FILES)
-+ cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/cpp.info doc/cpp.texi
-+
-+$(docdir)/gcc.info: $(TEXI_GCC_FILES)
-+ cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gcc.info doc/gcc.texi
-+
-+$(docdir)/gccint.info: $(TEXI_GCCINT_FILES)
-+ cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gccint.info doc/gccint.texi
-+
-+$(docdir)/gccinstall.info: $(TEXI_GCCINSTALL_FILES)
-+ cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/gccinstall.info doc/install.texi
-+
-+$(docdir)/cppinternals.info: $(TEXI_CPPINT_FILES)
-+ cd $(srcdir) && $(MAKEINFO) $(MAKEINFOFLAGS) -I doc -I doc/include -o doc/cppinternals.info \
-+ doc/cppinternals.texi
-+
-+dvi: gcc.dvi gccint.dvi gccinstall.dvi cpp.dvi lang.dvi cppinternals.dvi
-+
-+# This works with GNU Make's default rule.
-+cpp.dvi: $(TEXI_CPP_FILES)
-+ $(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/cpp.texi
-+
-+gcc.dvi: $(TEXI_GCC_FILES)
-+ $(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/gcc.texi
-+
-+gccint.dvi: $(TEXI_GCCINT_FILES)
-+ $(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/gccint.texi
-+
-+gccinstall.dvi: $(TEXI_GCCINSTALL_FILES)
-+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
-+ $(TEXI2DVI) -I $$s/doc -I $$s/doc/include -o $@ $$s/doc/install.texi
-+
-+cppinternals.dvi: $(TEXI_CPPINT_FILES)
-+ $(TEXI2DVI) -I $(docdir) -I $(docdir)/include $(docdir)/cppinternals.texi
-+
-+generated-manpages: $(docdir)/gcov.1 $(docdir)/cpp.1 $(docdir)/gcc.1 \
-+ $(docdir)/gfdl.7 $(docdir)/gpl.7 $(docdir)/fsf-funding.7 \
-+ lang.generated-manpages
-+
-+$(docdir)/gcov.1: $(docdir)/gcov.texi
-+ $(STAMP) $(docdir)/gcov.1
-+ -$(TEXI2POD) $(docdir)/gcov.texi > gcov.pod
-+ -($(POD2MAN) --section=1 gcov.pod > $(docdir)/gcov.1.T$$$$ && \
-+ mv -f $(docdir)/gcov.1.T$$$$ $(docdir)/gcov.1) || \
-+ (rm -f $(docdir)/gcov.1.T$$$$ && exit 1)
-+ -rm -f gcov.pod
-+
-+$(docdir)/cpp.1: $(docdir)/cpp.texi $(docdir)/cppenv.texi \
-+ $(docdir)/cppopts.texi
-+ $(STAMP) $(docdir)/cpp.1
-+ -$(TEXI2POD) $(docdir)/cpp.texi > cpp.pod
-+ -($(POD2MAN) --section=1 cpp.pod > $(docdir)/cpp.1.T$$$$ && \
-+ mv -f $(docdir)/cpp.1.T$$$$ $(docdir)/cpp.1) || \
-+ (rm -f $(docdir)/cpp.1.T$$$$ && exit 1)
-+ -rm -f cpp.pod
-+
-+$(docdir)/gcc.1: $(docdir)/invoke.texi $(docdir)/cppenv.texi \
-+ $(docdir)/cppopts.texi
-+ $(STAMP) $(docdir)/gcc.1
-+ -$(TEXI2POD) $(docdir)/invoke.texi > gcc.pod
-+ -($(POD2MAN) --section=1 gcc.pod > $(docdir)/gcc.1.T$$$$ && \
-+ mv -f $(docdir)/gcc.1.T$$$$ $(docdir)/gcc.1) || \
-+ (rm -f $(docdir)/gcc.1.T$$$$ && exit 1)
-+ -rm -f gcc.pod
-+
-+$(docdir)/gfdl.7: $(docdir)/include/fdl.texi
-+ $(STAMP) $(docdir)/gfdl.7
-+ -$(TEXI2POD) $(docdir)/include/fdl.texi > gfdl.pod
-+ -($(POD2MAN) --section=7 gfdl.pod > $(docdir)/gfdl.7.T$$$$ && \
-+ mv -f $(docdir)/gfdl.7.T$$$$ $(docdir)/gfdl.7) || \
-+ (rm -f $(docdir)/gfdl.7.T$$$$ && exit 1)
-+ -rm -f gfdl.pod
-+
-+$(docdir)/gpl.7: $(docdir)/include/gpl.texi
-+ $(STAMP) $(docdir)/gpl.7
-+ -$(TEXI2POD) $(docdir)/include/gpl.texi > gpl.pod
-+ -($(POD2MAN) --section=7 gpl.pod > $(docdir)/gpl.7.T$$$$ && \
-+ mv -f $(docdir)/gpl.7.T$$$$ $(docdir)/gpl.7) || \
-+ (rm -f $(docdir)/gpl.7.T$$$$ && exit 1)
-+ -rm -f gpl.pod
-+
-+$(docdir)/fsf-funding.7: $(docdir)/include/funding.texi
-+ $(STAMP) $(docdir)/fsf-funding.7
-+ -$(TEXI2POD) $(docdir)/include/funding.texi > fsf-funding.pod
-+ -($(POD2MAN) --section=7 fsf-funding.pod \
-+ > $(docdir)/fsf-funding.7.T$$$$ && \
-+ mv -f $(docdir)/fsf-funding.7.T$$$$ $(docdir)/fsf-funding.7) || \
-+ (rm -f $(docdir)/fsf-funding.7.T$$$$ && exit 1)
-+ -rm -f fsf-funding.pod
-+
-+#\f
-+# Deletion of files made during compilation.
-+# There are four levels of this:
-+# `mostlyclean', `clean', `distclean' and `maintainer-clean'.
-+# `mostlyclean' is useful while working on a particular type of machine.
-+# It deletes most, but not all, of the files made by compilation.
-+# It does not delete libgcc.a or its parts, so it won't have to be recompiled.
-+# `clean' deletes everything made by running `make all'.
-+# `distclean' also deletes the files made by config.
-+# `maintainer-clean' also deletes everything that could be regenerated
-+# automatically, except for `configure'.
-+# We remove as much from the language subdirectories as we can
-+# (less duplicated code).
-+
-+INTL_MOSTLYCLEAN = intl.mostlyclean
-+mostlyclean: $(INTL_MOSTLYCLEAN) lang.mostlyclean
-+ -rm -f $(STAGESTUFF)
-+ -rm -f *$(coverageexts)
-+ -rm -rf libgcc
-+# Delete the temporary source copies for cross compilation.
-+ -rm -f $(BUILD_PREFIX_1)rtl.c $(BUILD_PREFIX_1)print-rtl.c
-+ -rm -f $(BUILD_PREFIX_1)bitmap.c $(BUILD_PREFIX_1)errors.c
-+ -rm -f $(BUILD_PREFIX_1)ggc-none.c
-+# Delete the temp files made in the course of building libgcc.a.
-+ -rm -f xlimits.h
-+# Delete other built files.
-+ -rm -f xsys-protos.hT
-+ -rm -f specs.h options.h gencheck.h
-+# Delete the stamp and temporary files.
-+ -rm -f s-* tmp-* stamp-* stmp-*
-+ -rm -f */stamp-* */tmp-*
-+# Delete debugging dump files.
-+ -rm -f *.[0-9][0-9].* */*.[0-9][0-9].*
-+# Delete some files made during installation.
-+ -rm -f specs SYSCALLS.c.X SYSCALLS.c
-+ -rm -f collect collect2 mips-tfile mips-tdump
-+# Delete files generated for fixproto
-+ -rm -rf fix-header$(build_exeext) xsys-protos.h deduced.h tmp-deduced.h \
-+ gen-protos$(build_exeext) fixproto.list fixtmp.* fixhdr.ready
-+# Delete files generated for fixincl
-+ -rm -rf fixincl fixinc.sh specs.ready
-+ (cd fixinc && $(MAKE) clean)
-+# Delete unwanted output files from TeX.
-+ -rm -f *.toc *.log *.vr *.fn *.cp *.tp *.ky *.pg
-+ -rm -f */*.toc */*.log */*.vr */*.fn */*.cp */*.tp */*.ky */*.pg
-+# Delete sorted indices we don't actually use.
-+ -rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns
-+# Delete core dumps.
-+ -rm -f core */core
-+# Delete file generated for gengtype.c
-+ -rm -f gtyp-gen.h
-+# Delete files generated by gengtype.c
-+ -rm -f gtype-*
-+ -rm -f gt-*
-+
-+# Delete all files made by compilation
-+# that don't exist in the distribution.
-+INTL_CLEAN = intl.clean
-+clean: mostlyclean $(INTL_CLEAN) lang.clean
-+ -rm -f libgcc.a libgcc_eh.a libgcc_s$(SHLIB_EXT) libgcc_s$(SHLIB_EXT).1
-+ -rm -f config.h tconfig.h hconfig.h tm_p.h
-+ -rm -f cs-*
-+ -rm -rf libgcc
-+ -rm -f *.dvi
-+ -rm -f */*.dvi
-+# Delete the include directory.
-+ -rm -rf include
-+# Delete files used by the "multilib" facility (including libgcc subdirs).
-+ -rm -f multilib.h tmpmultilib*
-+ -if [ "x$(MULTILIB_DIRNAMES)" != x ] ; then \
-+ rm -rf $(MULTILIB_DIRNAMES); \
-+ else if [ "x$(MULTILIB_OPTIONS)" != x ] ; then \
-+ rm -rf `echo $(MULTILIB_OPTIONS) | sed -e 's/\// /g'`; \
-+ fi ; fi
-+ -rm -fr stage1 stage2 stage3 stage4
-+# Delete stamps of bootstrap stages
-+ -rm -f stage?_*
-+ -rm -f clean?_*
-+ -rm -f stage_last
-+
-+# Delete all files that users would normally create
-+# while building and installing GCC.
-+INTL_DISTCLEAN = intl.distclean
-+distclean: clean $(INTL_DISTCLEAN) lang.distclean
-+ -rm -f auto-host.h auto-build.h
-+ -rm -f cstamp-h
-+ -rm -f config.status config.run config.cache config.bak
-+ -rm -f Make-lang Make-hooks Make-host Make-target
-+ -rm -f Makefile *.oaux
-+ -rm -f gthr-default.h
-+ -rm -f */stage1 */stage2 */stage3 */stage4 */include
-+ -rm -f c-parse.output
-+ -rm -f *.asm
-+ -rm -f site.exp site.bak testsuite/site.exp testsuite/site.bak
-+ -rm -f testsuite/*.log testsuite/*.sum
-+ -cd testsuite && rm -f x *.x *.x? *.exe *.rpo *.o *.s *.S *.c
-+ -cd testsuite && rm -f *.out *.gcov *.bb *.bbg
-+ -rm -rf ${QMTEST_DIR} stamp-qmtest
-+ -rm -f intl/libintl.h libintl.h
-+ -rm -f cxxmain.c
-+ -rm -f mklibgcc mkheaders gccbug .gdbinit configargs.h
-+ -rm -f gcov.pod
-+ -rm -f fixinc/Makefile
-+# Delete po/*.gmo only if we are not building in the source directory.
-+ -if [ ! -f po/exgettext ]; then rm -f po/*.gmo; fi
-+ -rmdir ada cp f java objc fixinc intl po testsuite 2>/dev/null
-+
-+# Delete anything likely to be found in the source directory
-+# that shouldn't be in the distribution.
-+extraclean: distclean lang.extraclean
-+ -rm -rf =* ./"#"* *~* config/=* config/"#"* config/*~*
-+ -rm -f patch* *.orig *.rej config/patch* config/*.orig config/*.rej
-+ -rm -f config/*/=* config/*/"#"* config/*/*~*
-+ -rm -f config/*/*.orig config/*/*.rej
-+ -rm -f *.dvi *.ps *.oaux *.d *.[zZ] *.gz
-+ -rm -f *.tar *.xtar *diff *.diff.* *.tar.* *.xtar.* *diffs
-+ -rm -f *lose config/*lose config/*/*lose
-+ -rm -f *.s *.s[0-9] *.i config/ChangeLog
-+ -rm -f y.tab.c yacc.*
-+ -rm -f */=* */"#"* */*~*
-+ -rm -f */patch* */*.orig */*.rej
-+ -rm -f */*.dvi */*.oaux */*.d */*.[zZ] */*.gz
-+ -rm -f */*.tar */*.xtar */*diff */*.diff.* */*.tar.* */*.xtar.* */*diffs
-+ -rm -f */*lose */*.s */*.s[0-9] */*.i
-+
-+# Get rid of every file that's generated from some other file, except for `configure'.
-+# Most of these files ARE PRESENT in the GCC distribution.
-+# We define INTL_DISTCLEAN, INTL_CLEAN & INTL_MOSTLYCLEAN to be empty in the
-+# submake, so that we don't descend into intl after its makefile has been
-+# removed.
-+maintainer-clean:
-+ @echo 'This command is intended for maintainers to use; it'
-+ @echo 'deletes files that may need special tools to rebuild.'
-+ $(MAKE) INTL_DISTCLEAN= INTL_CLEAN= INTL_MOSTLYCLEAN= \
-+ intl.maintainer-clean lang.maintainer-clean distclean
-+ -rm -f c-parse.y c-parse.c c-parse.output TAGS
-+ -rm -f cpp.??s cpp.*aux
-+ -rm -f gcc.??s gcc.*aux
-+ -rm -f $(docdir)/cpp.info* $(docdir)/gcc.info* $(docdir)/gccint.info*
-+ -rm -f $(docdir)/cppinternals.info*
-+ -rm -f $(docdir)/gcov.1 $(docdir)/cpp.1 $(docdir)/gcc.1
-+ -rm -f $(docdir)/fsf-funding.7 $(docdir)/gfdl.7 $(docdir)/gpl.7
-+#\f
-+# Entry points `install' and `uninstall'.
-+# Also use `install-collect2' to install collect2 when the config files don't.
-+
-+# Copy the compiler files into directories where they will be run.
-+# Install the driver last so that the window when things are
-+# broken is small.
-+install: install-common $(INSTALL_HEADERS) $(INSTALL_LIBGCC) \
-+ install-cpp install-man install-info intl.install install-@POSUB@ \
-+ lang.install-normal install-driver
-+
-+# Handle cpp installation.
-+install-cpp: cpp$(exeext)
-+ -if [ -f gcc-cross$(exeext) ] ; then \
-+ rm -f $(DESTDIR)$(bindir)/$(CPP_CROSS_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(bindir)/$(CPP_CROSS_NAME)$(exeext); \
-+ if [ x$(cpp_install_dir) != x ]; then \
-+ rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_CROSS_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_CROSS_NAME)$(exeext); \
-+ else true; fi; \
-+ else \
-+ rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext); \
-+ if [ x$(cpp_install_dir) != x ]; then \
-+ rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
-+ else true; fi; \
-+ fi
-+
-+# Create the installation directories.
-+# $(libdir)/gcc-lib/include isn't currently searched by cpp.
-+installdirs:
-+ $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(libsubdir)
-+ $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
-+ $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(includedir)
-+ $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(infodir)
-+ $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(slibdir)
-+ $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(man1dir)
-+ $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(man7dir)
-+
-+# Install the compiler executables built during cross compilation.
-+install-common: native $(EXTRA_PARTS) lang.install-common
-+ for file in $(COMPILERS); do \
-+ if [ -f $$file ] ; then \
-+ rm -f $(DESTDIR)$(libsubdir)/$$file; \
-+ $(INSTALL_PROGRAM) $$file $(DESTDIR)$(libsubdir)/$$file; \
-+ else true; \
-+ fi; \
-+ done
-+ for file in $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(USE_COLLECT2) ..; do \
-+ if [ x"$$file" != x.. ]; then \
-+ rm -f $(DESTDIR)$(libsubdir)/$$file; \
-+ $(INSTALL_PROGRAM) $$file $(DESTDIR)$(libsubdir)/$$file; \
-+ else true; fi; \
-+ done
-+ for file in $(EXTRA_PARTS) ..; do \
-+ if [ x"$$file" != x.. ]; then \
-+ rm -f $(DESTDIR)$(libsubdir)/$$file; \
-+ $(INSTALL_DATA) $$file $(DESTDIR)$(libsubdir)/$$file; \
-+ chmod a-x $(DESTDIR)$(libsubdir)/$$file; \
-+ else true; fi; \
-+ done
-+# Don't mess with specs if it doesn't exist yet.
-+ -if [ -f specs ] ; then \
-+ rm -f $(DESTDIR)$(libsubdir)/specs; \
-+ $(INSTALL_DATA) specs $(DESTDIR)$(libsubdir)/specs; \
-+ chmod a-x $(DESTDIR)$(libsubdir)/specs; \
-+ fi
-+# Install protoize if it was compiled.
-+ -if [ -f protoize$(exeext) ]; \
-+ then \
-+ if [ -f gcc-cross$(exeext) ] ; then \
-+ rm -f $(DESTDIR)$(bindir)/$(PROTOIZE_CROSS_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) protoize$(exeext) $(DESTDIR)$(bindir)/$(PROTOIZE_CROSS_NAME)$(exeext); \
-+ rm -f $(DESTDIR)$(bindir)/$(UNPROTOIZE_CROSS_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) unprotoize$(exeext) $(DESTDIR)$(bindir)/$(UNPROTOIZE_CROSS_NAME)$(exeext); \
-+ else \
-+ rm -f $(DESTDIR)$(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) protoize$(exeext) $(DESTDIR)$(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext); \
-+ rm -f $(DESTDIR)$(bindir)/$(UNPROTOIZE_INSTALL_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) unprotoize$(exeext) $(DESTDIR)$(bindir)/$(UNPROTOIZE_INSTALL_NAME)$(exeext); \
-+ fi ; \
-+ rm -f $(DESTDIR)$(libsubdir)/SYSCALLS.c.X; \
-+ $(INSTALL_DATA) SYSCALLS.c.X $(DESTDIR)$(libsubdir)/SYSCALLS.c.X; \
-+ chmod a-x $(DESTDIR)$(libsubdir)/SYSCALLS.c.X; \
-+ fi
-+# Install gcov if it was compiled.
-+ -if [ -f gcov$(exeext) ]; \
-+ then \
-+ rm -f $(DESTDIR)$(bindir)/gcov$(exeext); \
-+ $(INSTALL_PROGRAM) gcov$(exeext) $(DESTDIR)$(bindir)/$(GCOV_INSTALL_NAME)$(exeext); \
-+ fi
-+ $(INSTALL_SCRIPT) gccbug $(DESTDIR)$(bindir)/$(GCCBUG_INSTALL_NAME)
-+
-+# Install the driver program as $(target_alias)-gcc,
-+# $(target-alias)-gcc-$(version)
-+# and also as either gcc (if native) or $(gcc_tooldir)/bin/gcc.
-+install-driver: installdirs xgcc$(exeext)
-+ -if [ -f gcc-cross$(exeext) ] ; then \
-+ rm -f $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) gcc-cross$(exeext) $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext); \
-+ rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-$(version); \
-+ ( cd $(DESTDIR)$(bindir) && \
-+ $(LN) $(GCC_CROSS_NAME)$(exeext) $(target_alias)-gcc-$(version) ); \
-+ if [ -d $(DESTDIR)$(gcc_tooldir)/bin/. ] ; then \
-+ rm -f $(DESTDIR)$(gcc_tooldir)/bin/gcc$(exeext); \
-+ $(INSTALL_PROGRAM) gcc-cross$(exeext) $(DESTDIR)$(gcc_tooldir)/bin/gcc$(exeext); \
-+ else true; fi; \
-+ else \
-+ rm -f $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext); \
-+ $(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext); \
-+ rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-$(version); \
-+ ( cd $(DESTDIR)$(bindir) && \
-+ $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_alias)-gcc-$(version) ); \
-+ rm -f $(DESTDIR)$(bindir)/$(target_alias)-gcc-tmp$(exeext); \
-+ ( cd $(DESTDIR)$(bindir) && \
-+ $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_alias)-gcc-tmp$(exeext) && \
-+ mv -f $(target_alias)-gcc-tmp$(exeext) $(GCC_TARGET_INSTALL_NAME)$(exeext) ); \
-+ fi
-+
-+# Install the info files.
-+# $(INSTALL_DATA) might be a relative pathname, so we can't cd into srcdir
-+# to do the install.
-+install-info: doc installdirs lang.install-info
-+ -rm -f $(DESTDIR)$(infodir)/cpp.info* $(DESTDIR)$(infodir)/gcc.info*
-+ -rm -f $(DESTDIR)$(infodir)/cppinternals.info* $(DESTDIR)$(infodir)/gccint.info*
-+ if [ -f $(docdir)/gcc.info ]; then \
-+ for f in $(docdir)/cpp.info* $(docdir)/gcc.info* \
-+ $(docdir)/cppinternals.info* $(docdir)/gccint.info*; do \
-+ realfile=`echo $$f | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
-+ $(INSTALL_DATA) $$f $(DESTDIR)$(infodir)/$$realfile; \
-+ done; \
-+ else true; fi
-+ -if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
-+ if [ -f $(DESTDIR)$(infodir)/dir ] ; then \
-+ for f in cpp.info gcc.info gccint.info cppinternals.info; do \
-+ if [ -f $(DESTDIR)$(infodir)/$$f ]; then \
-+ install-info --dir-file=$(DESTDIR)$(infodir)/dir $(DESTDIR)$(infodir)/$$f; \
-+ else true; fi; \
-+ done; \
-+ else true; fi; \
-+ else true; fi;
-+ -chmod a-x $(DESTDIR)$(infodir)/cpp.info* $(DESTDIR)$(infodir)/gcc.info*
-+ -chmod a-x $(DESTDIR)$(infodir)/cppinternals.info* $(DESTDIR)$(infodir)/gccint.info*
-+
-+# Install the man pages.
-+install-man: installdirs $(GENERATED_MANPAGES) lang.install-man
-+ -if [ -f gcc-cross$(exeext) ] ; then \
-+ rm -f $(DESTDIR)$(man1dir)/$(GCC_CROSS_NAME)$(man1ext); \
-+ $(INSTALL_DATA) $(docdir)/gcc.1 $(DESTDIR)$(man1dir)/$(GCC_CROSS_NAME)$(man1ext); \
-+ chmod a-x $(DESTDIR)$(man1dir)/$(GCC_CROSS_NAME)$(man1ext); \
-+ else \
-+ rm -f $(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext); \
-+ $(INSTALL_DATA) $(docdir)/gcc.1 $(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext); \
-+ chmod a-x $(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext); \
-+ fi
-+ -rm -f $(DESTDIR)$(man1dir)/cpp$(man1ext)
-+ -$(INSTALL_DATA) $(docdir)/cpp.1 $(DESTDIR)$(man1dir)/cpp$(man1ext)
-+ -chmod a-x $(DESTDIR)$(man1dir)/cpp$(man1ext)
-+ -rm -f $(DESTDIR)$(man1dir)/gcov$(man1ext)
-+ -$(INSTALL_DATA) $(docdir)/gcov.1 $(DESTDIR)$(man1dir)/gcov$(man1ext)
-+ -chmod a-x $(DESTDIR)$(man1dir)/gcov$(man1ext)
-+ -rm -f $(DESTDIR)$(man7dir)/fsf-funding$(man7ext)
-+ -$(INSTALL_DATA) $(docdir)/fsf-funding.7 $(DESTDIR)$(man7dir)/fsf-funding$(man7ext)
-+ -chmod a-x $(DESTDIR)$(man7dir)/fsf-funding$(man7ext)
-+ -rm -f $(DESTDIR)$(man7dir)/gfdl$(man7ext)
-+ -$(INSTALL_DATA) $(docdir)/gfdl.7 $(DESTDIR)$(man7dir)/gfdl$(man7ext)
-+ -chmod a-x $(DESTDIR)$(man7dir)/gfdl$(man7ext)
-+ -rm -f $(DESTDIR)$(man7dir)/gpl$(man7ext)
-+ -$(INSTALL_DATA) $(docdir)/gpl.7 $(DESTDIR)$(man7dir)/gpl$(man7ext)
-+ -chmod a-x $(DESTDIR)$(man7dir)/gpl$(man7ext)
-+
-+# Install the library.
-+install-libgcc: libgcc.mk libgcc.a installdirs
-+ if $(RANLIB_TEST_FOR_TARGET); then \
-+ r_f_t=$(RANLIB_FOR_TARGET); \
-+ else \
-+ r_f_t=: ; \
-+ fi; \
-+ $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
-+ BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
-+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
-+ AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \
-+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
-+ CFLAGS="$(CFLAGS) $(WARN_CFLAGS)" \
-+ RANLIB_TEST_FOR_TARGET="$(RANLIB_TEST_FOR_TARGET)" \
-+ NM_FOR_TARGET="$(NM_FOR_TARGET)" AWK="$(AWK)" \
-+ LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" \
-+ INCLUDES="$(INCLUDES)" \
-+ CONFIG_H="$(TCONFIG_H)" MACHMODE_H="$(MACHMODE_H)" \
-+ LIB1ASMSRC='$(LIB1ASMSRC)' \
-+ MAKEOVERRIDES= \
-+ INSTALL_DATA="$(INSTALL_DATA)" \
-+ RANLIB_FOR_TARGET="$$r_f_t" \
-+ DESTDIR="$(DESTDIR)" \
-+ libsubdir="$(libsubdir)" \
-+ slibdir="$(slibdir)" \
-+ -f libgcc.mk install
-+
-+# Install multiple versions of libgcc.a.
-+install-multilib: stmp-multilib installdirs
-+ if $(RANLIB_TEST_FOR_TARGET); then \
-+ r_f_t=$(RANLIB_FOR_TARGET); \
-+ else \
-+ r_f_t=: ; \
-+ fi; \
-+ $(MAKE) GCC_FOR_TARGET="$(GCC_FOR_TARGET)" \
-+ BUILD_PREFIX="$(BUILD_PREFIX)" BUILD_PREFIX_1="$(BUILD_PREFIX_1)" \
-+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
-+ AR_CREATE_FOR_TARGET="$(AR_CREATE_FOR_TARGET)" \
-+ AR_FLAGS_FOR_TARGET="$(AR_FLAGS_FOR_TARGET)" \
-+ CFLAGS="$(CFLAGS) $(WARN_CFLAGS)" \
-+ RANLIB_TEST_FOR_TARGET="$(RANLIB_TEST_FOR_TARGET)" \
-+ NM_FOR_TARGET="$(NM_FOR_TARGET)" AWK="$(AWK)" \
-+ LIBGCC2_CFLAGS="$(LIBGCC2_CFLAGS)" \
-+ INCLUDES="$(INCLUDES)" \
-+ CONFIG_H="$(CONFIG_H)" MACHMODE_H="$(MACHMODE_H)" \
-+ LIB1ASMSRC='$(LIB1ASMSRC)' \
-+ MAKEOVERRIDES= \
-+ INSTALL_DATA="$(INSTALL_DATA)" \
-+ RANLIB_FOR_TARGET="$$r_f_t" \
-+ DESTDIR="$(DESTDIR)" \
-+ libsubdir="$(libsubdir)" \
-+ slibdir="$(slibdir)" \
-+ -f libgcc.mk install
-+
-+# Install all the header files built in the include subdirectory.
-+install-headers: $(INSTALL_HEADERS_DIR)
-+# Fix symlinks to absolute paths in the installed include directory to
-+# point to the installed directory, not the build directory.
-+# Don't need to use LN_S here since we really do need ln -s and no substitutes.
-+ -files=`cd $(DESTDIR)$(libsubdir)/include; find . -type l -print 2>/dev/null`; \
-+ if [ $$? -eq 0 ]; then \
-+ dir=`cd include; ${PWD_COMMAND}`; \
-+ for i in $$files; do \
-+ dest=`ls -ld $(DESTDIR)$(libsubdir)/include/$$i | sed -n 's/.*-> //p'`; \
-+ if expr "$$dest" : "$$dir.*" > /dev/null; then \
-+ rm -f $(DESTDIR)$(libsubdir)/include/$$i; \
-+ ln -s `echo $$i | sed "s|/[^/]*|/..|g" | sed 's|/..$$||'``echo "$$dest" | sed "s|$$dir||"` $(DESTDIR)$(libsubdir)/include/$$i; \
-+ fi; \
-+ done; \
-+ fi
-+
-+# Create or recreate the gcc private include file directory.
-+install-include-dir: installdirs
-+ -rm -rf $(DESTDIR)$(libsubdir)/include
-+ mkdir $(DESTDIR)$(libsubdir)/include
-+ -chmod a+rx $(DESTDIR)$(libsubdir)/include
-+
-+# Install the include directory using tar.
-+install-headers-tar: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
-+# We use `pwd`/include instead of just include to problems with CDPATH
-+# Unless a full pathname is provided, some shells would print the new CWD,
-+# found in CDPATH, corrupting the output. We could just redirect the
-+# output of `cd', but some shells lose on redirection within `()'s
-+ (cd `${PWD_COMMAND}`/include ; \
-+ tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include; tar xpf - )
-+# /bin/sh on some systems returns the status of the first tar,
-+# and that can lose with GNU tar which always writes a full block.
-+# So use `exit 0' to ignore its exit status.
-+
-+# Install the include directory using cpio.
-+install-headers-cpio: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
-+# See discussion about the use of `pwd` above
-+ cd `${PWD_COMMAND}`/include ; \
-+ find . -print | cpio -pdum $(DESTDIR)$(libsubdir)/include
-+
-+# Install the include directory using cp.
-+install-headers-cp: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir
-+ cp -p -r include $(DESTDIR)$(libsubdir)
-+
-+itoolsdir = $(libsubdir)/install-tools
-+# Don't install the headers. Instead, install appropriate scripts
-+# and supporting files for fixincludes to be run later.
-+install-mkheaders: stmp-int-hdrs $(STMP_FIXPROTO) install-include-dir \
-+ mkheaders xlimits.h
-+ -rm -rf $(DESTDIR)$(itoolsdir)
-+ $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(itoolsdir)/include
-+ for file in $(USER_H); do \
-+ realfile=`echo $$file | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
-+ $(INSTALL_DATA) $$file \
-+ $(DESTDIR)$(itoolsdir)/include/$$realfile ; \
-+ done
-+ $(INSTALL_DATA) xlimits.h $(DESTDIR)$(itoolsdir)/include/limits.h
-+ if [ x$(STMP_FIXINC) != x ] ; then \
-+ $(INSTALL_DATA) $(srcdir)/README-fixinc \
-+ $(DESTDIR)$(itoolsdir)/include/README ; \
-+ $(INSTALL_PROGRAM) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
-+ $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
-+ $(INSTALL_DATA) $(srcdir)/gsyslimits.h $(DESTDIR)$(itoolsdir)/gsyslimits.h ; \
-+ else :; fi
-+ if [ x$(STMP_FIXPROTO) != x ] ; then \
-+ $(INSTALL_PROGRAM) $(srcdir)/mkinstalldirs \
-+ $(DESTDIR)$(itoolsdir)/mkinstalldirs ; \
-+ $(INSTALL_PROGRAM) $(srcdir)/fixproto $(DESTDIR)$(itoolsdir)/fixproto ; \
-+ $(INSTALL_PROGRAM) fix-header$(build_exeext) \
-+ $(DESTDIR)$(itoolsdir)/fix-header$(build_exeext) ; \
-+ else :; fi
-+ $(INSTALL_PROGRAM) mkheaders $(DESTDIR)$(itoolsdir)/mkheaders
-+ echo 'SYSTEM_HEADER_DIR="$(SYSTEM_HEADER_DIR)"' \
-+ > $(DESTDIR)$(itoolsdir)/mkheaders.conf
-+ echo 'OTHER_FIXINCLUDES_DIRS="$(OTHER_FIXINCLUDES_DIRS)"' \
-+ >> $(DESTDIR)$(itoolsdir)/mkheaders.conf
-+ echo 'FIXPROTO_DEFINES="$(FIXPROTO_DEFINES)"' \
-+ >> $(DESTDIR)$(itoolsdir)/mkheaders.conf
-+ echo 'STMP_FIXPROTO="$(STMP_FIXPROTO)"' >> $(DESTDIR)$(itoolsdir)/mkheaders.conf
-+ echo 'STMP_FIXINC="$(STMP_FIXINC)"' >> $(DESTDIR)$(itoolsdir)/mkheaders.conf
-+
-+# Use this target to install the program `collect2' under the name `collect2'.
-+install-collect2: collect2 installdirs
-+ $(INSTALL_PROGRAM) collect2$(exeext) $(DESTDIR)$(libsubdir)/collect2$(exeext)
-+# Install the driver program as $(libsubdir)/gcc for collect2.
-+ $(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(libsubdir)/gcc$(exeext)
-+
-+# Cancel installation by deleting the installed files.
-+uninstall: intl.uninstall lang.uninstall
-+ -rm -rf $(DESTDIR)$(libsubdir)
-+ -rm -rf $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
-+ -rm -rf $(DESTDIR)$(bindir)/$(GCC_CROSS_NAME)$(exeext)
-+ -rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext)
-+ -rm -f $(DESTDIR)$(bindir)/$(CPP_CROSS_NAME)$(exeext)
-+ -if [ x$(cpp_install_dir) != x ]; then \
-+ rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
-+ rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_CROSS_NAME)$(exeext); \
-+ else true; fi
-+ -rm -rf $(DESTDIR)$(bindir)/$(PROTOIZE_INSTALL_NAME)$(exeext)
-+ -rm -rf $(DESTDIR)$(bindir)/$(PROTOIZE_CROSS_NAME)$(exeext)
-+ -rm -rf $(DESTDIR)$(bindir)/$(UNPROTOIZE_INSTALL_NAME)$(exeext)
-+ -rm -rf $(DESTDIR)$(bindir)/$(UNPROTOIZE_CROSS_NAME)$(exeext)
-+ -rm -rf $(DESTDIR)$(bindir)/$(GCOV_INSTALL_NAME)$(exeext)
-+ -rm -rf $(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext)
-+ -rm -rf $(DESTDIR)$(man1dir)/$(GCC_CROSS_NAME)$(man1ext)
-+ -rm -rf $(DESTDIR)$(man1dir)/cpp$(man1ext)
-+ -rm -rf $(DESTDIR)$(man1dir)/protoize$(man1ext)
-+ -rm -rf $(DESTDIR)$(man1dir)/unprotoize$(man1ext)
-+ -rm -f $(DESTDIR)$(infodir)/cpp.info* $(DESTDIR)$(infodir)/gcc.info*
-+ -rm -f $(DESTDIR)$(infodir)/cppinternals.info* $(DESTDIR)$(infodir)/gccint.info*
-+#\f
-+# These targets are for the dejagnu testsuites. The file site.exp
-+# contains global variables that all the testsuites will use.
-+
-+# Set to $(target_alias)/ for cross.
-+target_subdir = @target_subdir@
-+
-+site.exp: ./config.status Makefile
-+ @echo "Making a new config file..."
-+ -@rm -f ./tmp?
-+ @$(STAMP) site.exp
-+ -@mv site.exp site.bak
-+ @echo "## these variables are automatically generated by make ##" > ./tmp0
-+ @echo "# Do not edit here. If you wish to override these values" >> ./tmp0
-+ @echo "# add them to the last section" >> ./tmp0
-+ @echo "set rootme \"`${PWD_COMMAND}`\"" >> ./tmp0
-+ @echo "set srcdir \"`cd ${srcdir}; ${PWD_COMMAND}`\"" >> ./tmp0
-+ @echo "set host_triplet $(host_canonical)" >> ./tmp0
-+ @echo "set build_triplet $(build_canonical)" >> ./tmp0
-+ @echo "set target_triplet $(target)" >> ./tmp0
-+ @echo "set target_alias $(target_alias)" >> ./tmp0
-+# CFLAGS is set even though it's empty to show we reserve the right to set it.
-+ @echo "set CFLAGS \"\"" >> ./tmp0
-+ @echo "set CXXFLAGS \"-I$(objdir)/../$(target_subdir)libio -I\$$srcdir/../libg++/src -I\$$srcdir/../libio -I\$$srcdir/../libstdc++ -I\$$srcdir/../libstdc++/stl -L$(objdir)/../$(target_subdir)libg++ -L$(objdir)/../$(target_subdir)libstdc++\"" >> ./tmp0
-+ @echo "set TESTING_IN_BUILD_TREE 1" >> ./tmp0
-+ @echo "set HAVE_LIBSTDCXX_V3 1" >> ./tmp0
-+# If newlib has been configured, we need to pass -B to gcc so it can find
-+# newlib's crt0.o if it exists. This will cause a "path prefix not used"
-+# message if it doesn't, but the testsuite is supposed to ignore the message -
-+# it's too difficult to tell when to and when not to pass -B (not all targets
-+# have crt0's). We could only add the -B if ../newlib/crt0.o exists, but that
-+# seems like too selective a test.
-+# ??? Another way to solve this might be to rely on linker scripts. Then
-+# theoretically the -B won't be needed.
-+# We also need to pass -L ../ld so that the linker can find ldscripts.
-+ @if [ -d $(objdir)/../$(target_subdir)newlib ] ; then \
-+ echo "set newlib_cflags \"-I$(objdir)/../$(target_subdir)newlib/targ-include -I\$$srcdir/../newlib/libc/include\"" >> ./tmp0; \
-+ echo "set newlib_ldflags \"-B$(objdir)/../$(target_subdir)newlib/\"" >> ./tmp0; \
-+ echo "append CFLAGS \" \$$newlib_cflags\"" >> ./tmp0; \
-+ echo "append CXXFLAGS \" \$$newlib_cflags\"" >> ./tmp0; \
-+ echo "append LDFLAGS \" \$$newlib_ldflags\"" >> ./tmp0; \
-+ else true; \
-+ fi
-+ @if [ -d $(objdir)/../ld ] ; then \
-+ echo "append LDFLAGS \" -L$(objdir)/../ld\"" >> ./tmp0; \
-+ else true; \
-+ fi
-+ echo "set tmpdir $(objdir)/testsuite" >> ./tmp0
-+ @echo "set srcdir \"\$${srcdir}/testsuite\"" >> ./tmp0
-+ @if [ "X$(ALT_CXX_UNDER_TEST)" != "X" ] ; then \
-+ echo "set ALT_CXX_UNDER_TEST $(ALT_CXX_UNDER_TEST)" >> ./tmp0; \
-+ else true; \
-+ fi
-+ @if [ "X$(COMPAT_OPTIONS)" != "X" ] ; then \
-+ echo "set COMPAT_OPTIONS $(COMPAT_OPTIONS)" >> ./tmp0; \
-+ else true; \
-+ fi
-+ @echo "## All variables above are generated by configure. Do Not Edit ##" >> ./tmp0
-+ @cat ./tmp0 > site.exp
-+ @cat site.bak | sed \
-+ -e '1,/^## All variables above are.*##/ d' >> site.exp
-+ -@rm -f ./tmp?
-+
-+CHECK_TARGETS = check-gcc @check_languages@
-+
-+check-c++ : check-g++
-+check-f77 : check-g77
-+check-java :
-+
-+check: $(CHECK_TARGETS)
-+
-+# The idea is to parallelize testing of multilibs, for example:
-+# make -j3 check-gcc//sh-hms-sim/{-m1,-m2,-m3,-m3e,-m4}/{,-nofpu}
-+# will run 3 concurrent sessions of check-gcc, eventually testing
-+# all 10 combinations. GNU make is required, as is a shell that expands
-+# alternations within braces.
-+check-gcc//% check-g++//% check-g77//% check-objc//%: site.exp
-+ target=`echo "$@" | sed 's,//.*,,'`; \
-+ variant=`echo "$@" | sed 's,^[^/]*//,,'`; \
-+ vardots=`echo "$$variant" | sed 's,/,.,g'`; \
-+ $(MAKE) TESTSUITEDIR="testsuite.$$vardots" \
-+ RUNTESTFLAGS="--target_board=$$variant $(RUNTESTFLAGS)" \
-+ "$$target"
-+
-+TESTSUITEDIR = testsuite
-+
-+$(TESTSUITEDIR)/site.exp: site.exp
-+ test -d $(TESTSUITEDIR) || mkdir $(TESTSUITEDIR)
-+ -rm -f $@
-+ sed '/set tmpdir/ s|testsuite|$(TESTSUITEDIR)|' < site.exp > $@
-+
-+check-g++: $(TESTSUITEDIR)/site.exp
-+ -(rootme=`${PWD_COMMAND}`; export rootme; \
-+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
-+ cd $(TESTSUITEDIR); \
-+ EXPECT=${EXPECT} ; export EXPECT ; \
-+ if [ -f $${rootme}/../expect/expect ] ; then \
-+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
-+ export TCL_LIBRARY ; fi ; \
-+ $(RUNTEST) --tool g++ $(RUNTESTFLAGS))
-+
-+check-gcc: $(TESTSUITEDIR)/site.exp
-+ -(rootme=`${PWD_COMMAND}`; export rootme; \
-+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
-+ cd $(TESTSUITEDIR); \
-+ EXPECT=${EXPECT} ; export EXPECT ; \
-+ if [ -f $${rootme}/../expect/expect ] ; then \
-+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
-+ export TCL_LIBRARY ; fi ; \
-+ $(RUNTEST) --tool gcc $(RUNTESTFLAGS))
-+
-+check-g77: $(TESTSUITEDIR)/site.exp
-+ -(rootme=`${PWD_COMMAND}`; export rootme; \
-+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
-+ cd $(TESTSUITEDIR); \
-+ EXPECT=${EXPECT} ; export EXPECT ; \
-+ if [ -f $${rootme}/../expect/expect ] ; then \
-+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
-+ export TCL_LIBRARY ; fi ; \
-+ $(RUNTEST) --tool g77 $(RUNTESTFLAGS))
-+
-+check-objc: $(TESTSUITEDIR)/site.exp
-+ -(rootme=`${PWD_COMMAND}`; export rootme; \
-+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
-+ cd $(TESTSUITEDIR); \
-+ EXPECT=${EXPECT} ; export EXPECT ; \
-+ if [ -f $${rootme}/../expect/expect ] ; then \
-+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
-+ export TCL_LIBRARY ; fi ; \
-+ $(RUNTEST) --tool objc $(RUNTESTFLAGS))
-+
-+check-consistency: testsuite/site.exp
-+ -rootme=`${PWD_COMMAND}`; export rootme; \
-+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
-+ cd testsuite; \
-+ EXPECT=${EXPECT} ; export EXPECT ; \
-+ if [ -f $${rootme}/../expect/expect ] ; then \
-+ TCL_LIBRARY=`cd .. ; cd ${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
-+ export TCL_LIBRARY ; fi ; \
-+ $(RUNTEST) --tool consistency $(RUNTESTFLAGS)
-+
-+# QMTest targets
-+
-+# The path to qmtest.
-+QMTEST_PATH=qmtest
-+
-+# The flags to pass to qmtest.
-+QMTESTFLAGS=
-+
-+# The flags to pass to "qmtest run".
-+QMTESTRUNFLAGS=
-+
-+# The command to use to invoke qmtest.
-+QMTEST=${QMTEST_PATH} ${QMTESTFLAGS}
-+
-+# The tests (or suites) to run.
-+QMTEST_GPP_TESTS=gpp
-+
-+# The subdirectory of the OBJDIR that will be used to store the QMTest
-+# test database configuration and that will be used for temporary
-+# scratch space during QMTest's execution.
-+QMTEST_DIR=qmtestsuite
-+
-+# Create the QMTest database configuration.
-+${QMTEST_DIR} stamp-qmtest:
-+ debug_options=""; \
-+ ${STAMP} empty.C; \
-+ for option in \
-+ -gdwarf-2 -gstabs -gstabs+ -gxcoff -gxcoff+ -gcoff; do \
-+ (./cc1plus -q $${option} empty.C 2>&1 | \
-+ grep "unknown or unsupported -g option" > /dev/null) || \
-+ debug_options="$${debug_options}$${option} "; done; \
-+ ${QMTEST} -D ${QMTEST_DIR} create-tdb \
-+ -c gcc_database.GCCDatabase \
-+ -a GCCDatabase.testsuite_root=`cd ${srcdir}/testsuite && pwd` \
-+ -a GCCDatabase.debug_options="$${debug_options}"
-+ rm -f empty.C empty.s
-+ $(STAMP) stamp-qmtest
-+
-+# Create the QMTest context file.
-+${QMTEST_DIR}/context: stamp-qmtest
-+ echo "GCCTest.flags=-B${objdir}" >> $@
-+ echo "GCCTest.objdir=${objdir}/.." >> $@
-+ echo "GCCTest.host=${host_canonical}" >> $@
-+ echo "GCCTest.target=${target}" >> $@
-+ echo "GCCTest.gcov=${objdir}/gcov" >> $@
-+ echo "GPPTest.gpp=${objdir}/g++" >> $@
-+ echo "DGTest.demangler=${objdir}/c++filt" >> $@
-+
-+# Run the G++ testsuite using QMTest.
-+qmtest-g++: ${QMTEST_DIR}/context ${QMTEST_DIR}/gpp-expected.qmr
-+ cd ${QMTEST_DIR} && ${QMTEST} run ${QMTESTRUNFLAGS} -C context \
-+ -o gpp.qmr -O gpp-expected.qmr \
-+ ${QMTEST_GPP_TESTS}
-+
-+# Use the QMTest GUI.
-+qmtest-gui: ${QMTEST_DIR}/context
-+ cd ${QMTEST_DIR} && ${QMTEST} gui -C context
-+
-+# Build the set of expected G++ failures.
-+${QMTEST_DIR}/gpp-expected.qmr: ${QMTEST_DIR}/context
-+ echo "Determining expected results..."
-+ cd ${QMTEST_DIR} && ${QMTEST} run ${QMTESTRUNFLAGS} -C context \
-+ -c "GCCTest.generate_xfails=1" -o gpp-expected.qmr \
-+ ${QMTEST_GPP_TESTS} \
-+ > /dev/null
-+
-+.PHONY: qmtest-g++
-+
-+# Run Paranoia on real.c.
-+
-+paranoia.o: $(srcdir)/../contrib/paranoia.cc $(CONFIG_H) $(SYSTEM_H) \
-+ real.h $(TREE_H)
-+ g++ -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-+
-+paranoia: paranoia.o real.o $(LIBIBERTY)
-+ g++ -o $@ paranoia.o real.o $(LIBIBERTY)
-+
-+# These exist for maintenance purposes.
-+
-+# Update the tags table.
-+TAGS: force
-+ (cd $(srcdir); \
-+ mkdir tmp-tags; \
-+ mv -f c-parse.[ch] =*.[chy] tmp-tags; \
-+ etags *.y *.h *.c; \
-+ mv tmp-tags/* .; \
-+ rmdir tmp-tags)
-+
-+# A list of files to be destroyed during "lean" builds.
-+VOL_FILES=`echo $(BACKEND) $(OBJS) $(C_OBJS) $(LIBCPP_OBJS) *.c *.h gen*`
-+
-+# Flags to pass to stage2 and later recursive makes. Note that the
-+# WARN_CFLAGS setting can't be to the expansion of GCC_WARN_CFLAGS in
-+# the context of the stage_x rule.
-+STAGE2_FLAGS_TO_PASS = \
-+ ADAC="\$$(CC)" \
-+ AR_FOR_TARGET="$(AR_FOR_TARGET)" \
-+ RANLIB_FOR_TARGET="$(RANLIB_FOR_TARGET)" \
-+ CFLAGS="$(BOOT_CFLAGS)" \
-+ LDFLAGS="$(BOOT_LDFLAGS)" \
-+ WARN_CFLAGS="\$$(GCC_WARN_CFLAGS)" \
-+ STRICT_WARN="$(STRICT2_WARN)" \
-+ libdir=$(libdir) \
-+ LANGUAGES="$(LANGUAGES)" \
-+ MAKEOVERRIDES= \
-+ OUTPUT_OPTION="-o \$$@"
-+
-+# Only build the C compiler for stage1, because that is the only one that
-+# we can guarantee will build with the native compiler, and also it is the
-+# only thing useful for building stage2. STAGE1_CFLAGS (via CFLAGS),
-+# MAKEINFO and MAKEINFOFLAGS are explicitly passed here to make them
-+# overrideable (for a bootstrap build stage1 also builds gcc.info).
-+stage1_build:
-+ $(MAKE) AR_FOR_TARGET="$(AR_FOR_TARGET)" \
-+ RANLIB_FOR_TARGET="$(RANLIB_FOR_TARGET)" \
-+ CC="$(CC)" libdir=$(libdir) LANGUAGES="$(BOOT_LANGUAGES)" \
-+ CFLAGS="$(STAGE1_CFLAGS)" MAKEINFO="$(MAKEINFO)" \
-+ MAKEINFOFLAGS="$(MAKEINFOFLAGS)" COVERAGE_FLAGS=
-+ $(STAMP) stage1_build
-+ echo stage1_build > stage_last
-+
-+stage1_copy: stage1_build
-+ $(MAKE) stage1
-+ $(STAMP) stage1_copy
-+ echo stage2_build > stage_last
-+
-+stage2_build: stage1_copy
-+ $(MAKE) CC="$(STAGE_CC_WRAPPER) stage1/xgcc$(exeext) -Bstage1/ -B$(build_tooldir)/bin/" \
-+ STAGE_PREFIX=stage1/ \
-+ $(STAGE2_FLAGS_TO_PASS)
-+ $(STAMP) stage2_build
-+ echo stage2_build > stage_last
-+
-+stage2_copy: stage2_build
-+ $(MAKE) stage2
-+ $(STAMP) stage2_copy
-+ echo stage3_build > stage_last
-+
-+stage3_build: stage2_copy
-+ $(MAKE) CC="$(STAGE_CC_WRAPPER) stage2/xgcc$(exeext) -Bstage2/ -B$(build_tooldir)/bin/" \
-+ STAGE_PREFIX=stage2/ \
-+ $(STAGE2_FLAGS_TO_PASS)
-+ $(STAMP) stage3_build
-+ echo stage3_build > stage_last
-+
-+# For bootstrap4:
-+stage3_copy: stage3_build
-+ $(MAKE) stage3
-+ $(STAMP) stage3_copy
-+ echo stage4_build > stage_last
-+
-+stage4_build: stage3_copy
-+ $(MAKE) CC="$(STAGE_CC_WRAPPER) stage3/xgcc$(exeext) -Bstage3/ -B$(build_tooldir)/bin/" \
-+ STAGE_PREFIX=stage3/ \
-+ $(STAGE2_FLAGS_TO_PASS)
-+ $(STAMP) stage4_build
-+ echo stage4_build > stage_last
-+
-+# Additional steps for *-lean targets:
-+clean_s1: stage1_copy
-+ -(cd stage1 && rm -f $(VOL_FILES))
-+ $(STAMP) clean_s1
-+
-+clean_s2: stage2_copy
-+ -rm -rf stage1
-+ $(STAMP) clean_s2
-+
-+# The various entry points for bootstrapping.
-+
-+bootstrap: stage3_build
-+ @echo
-+ @echo Bootstrap complete - make \"quickstrap\" to redo last build,
-+ @echo \"restage1\" through \"restage3\" to rebuild specific stages,
-+ @echo \"restrap\" to redo the bootstrap from stage1, or
-+ @echo \"cleanstrap\" to redo the bootstrap from scratch.
-+
-+bootstrap-lean : clean_s1 clean_s2 stage3_build
-+ @echo
-+ @echo Bootstrap complete - make \"quickstrap\" to redo last build,
-+ @echo or \"cleanstrap\" to redo the bootstrap from scratch.
-+
-+bootstrap2: bootstrap
-+
-+bootstrap2-lean : bootstrap-lean
-+
-+bootstrap3 bootstrap3-lean: bootstrap
-+
-+bootstrap4 bootstrap4-lean: stage4_build
-+
-+unstage1 unstage2 unstage3 unstage4:
-+ -set -vx; stage=`echo $@ | sed -e 's/un//'`; \
-+ rm -f $$stage/as$(exeext); \
-+ rm -f $$stage/ld$(exeext); \
-+ rm -f $$stage/collect-ld$(exeext); \
-+ if test -d $$stage; then \
-+ mv $$stage/* . 2>/dev/null; \
-+ for i in `cd $$stage; echo *` ; do \
-+ if test -d $$stage/$$i; then \
-+ mv $$stage/$$i/* $$i/. 2>/dev/null; \
-+ else \
-+ mv $$stage/$$i .; \
-+ fi; \
-+ done \
-+ fi ; \
-+ rm -f $${stage}_build $${stage}_copy ;\
-+ echo $${stage}_build > stage_last
-+
-+restage1: unstage1
-+ $(MAKE) stage1_build
-+
-+restage2: unstage2
-+ $(MAKE) LANGUAGES="$(LANGUAGES)" stage2_build
-+
-+restage3: unstage3
-+ $(MAKE) LANGUAGES="$(LANGUAGES)" stage3_build
-+
-+restage4: unstage4
-+ $(MAKE) LANGUAGES="$(LANGUAGES)" stage4_build
-+
-+bubblestrap:
-+ if test -f stage3_build; then true; else \
-+ echo; echo You must \"make bootstrap\" first.; \
-+ exit 1; \
-+ fi
-+ for i in stage3 \
-+ unstage1 stage1_build stage1_copy \
-+ unstage2 stage2_build stage2_copy \
-+ unstage3 stage3_build ; \
-+ do \
-+ $(MAKE) LANGUAGES="$(LANGUAGES)" $$i || exit 1 ; \
-+ done
-+
-+quickstrap:
-+ if test -f stage_last ; then \
-+ LAST=`cat stage_last`; rm $$LAST; $(MAKE) LANGUAGES="$(LANGUAGES)" $$LAST; \
-+ else \
-+ $(MAKE) stage1_build; \
-+ fi
-+
-+cleanstrap:
-+ -$(MAKE) clean
-+ $(MAKE) LANGUAGES="$(LANGUAGES)" bootstrap
-+
-+unstrap:
-+ -rm -rf stage[234]*
-+ $(MAKE) unstage1
-+
-+# Differs from cleanstrap in that it starts from the earlier stage1 build,
-+# not from scratch.
-+restrap:
-+ $(MAKE) unstrap
-+ $(MAKE) LANGUAGES="$(LANGUAGES)" bootstrap
-+
-+# Compare the object files in the current directory with those in the
-+# stage2 directory.
-+
-+# ./ avoids bug in some versions of tail.
-+compare compare3 compare4 compare-lean compare3-lean compare4-lean: force
-+ -rm -f .bad_compare
-+ case "$@" in compare | compare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^compare\([0-9][0-9]*\).*,\1,'` ;; esac; \
-+ for file in *$(objext); do \
-+ tail +16c ./$$file > tmp-foo1; \
-+ tail +16c stage$$stage/$$file > tmp-foo2 \
-+ && (cmp tmp-foo1 tmp-foo2 > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
-+ done
-+ case "$@" in compare | compare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^compare\([0-9][0-9]*\).*,\1,'` ;; esac; \
-+ for dir in tmp-foo intl $(SUBDIRS); do \
-+ if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \
-+ for file in $$dir/*$(objext); do \
-+ tail +16c ./$$file > tmp-foo1; \
-+ tail +16c stage$$stage/$$file > tmp-foo2 \
-+ && (cmp tmp-foo1 tmp-foo2 > /dev/null 2>&1 || echo $$file differs >> .bad_compare) || true; \
-+ done; \
-+ else true; fi; \
-+ done
-+ -rm -f tmp-foo*
-+ case "$@" in compare | compare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^compare\([0-9][0-9]*\).*,\1,'` ;; esac; \
-+ if [ -f .bad_compare ]; then \
-+ echo "Bootstrap comparison failure!"; \
-+ cat .bad_compare; \
-+ exit 1; \
-+ else \
-+ case "$@" in \
-+ *-lean ) rm -rf stage$$stage ;; \
-+ *) ;; \
-+ esac; true; \
-+ fi
-+
-+# Compare the object files in the current directory with those in the
-+# stage2 directory. Use gnu cmp (diffutils v2.4 or later) to avoid
-+# running tail and the overhead of twice copying each object file.
-+# An exit status of 1 is precisely the result we're looking for (other
-+# values mean other problems).
-+gnucompare gnucompare3 gnucompare4 gnucompare-lean gnucompare3-lean gnucompare4-lean: force
-+ -rm -f .bad_compare
-+ case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \
-+ for file in *$(objext); do \
-+ cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1; \
-+ test $$? -eq 1 && echo $$file differs >> .bad_compare || true; \
-+ done
-+ case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \
-+ for dir in tmp-foo intl $(SUBDIRS); do \
-+ if [ "`echo $$dir/*$(objext)`" != "$$dir/*$(objext)" ] ; then \
-+ for file in $$dir/*$(objext); do \
-+ cmp --ignore-initial=16 $$file stage$$stage/$$file > /dev/null 2>&1; \
-+ test $$? -eq 1 && echo $$file differs >> .bad_compare || true; \
-+ done; \
-+ else true; fi; \
-+ done
-+ case "$@" in gnucompare | gnucompare-lean ) stage=2 ;; * ) stage=`echo $@ | sed -e 's,^gnucompare\([0-9][0-9]*\).*,\1,'` ;; esac; \
-+ if [ -f .bad_compare ]; then \
-+ echo "Bootstrap comparison failure!"; \
-+ cat .bad_compare; \
-+ exit 1; \
-+ else \
-+ case "$@" in \
-+ *-lean ) rm -rf stage$$stage ;; \
-+ esac; true; \
-+ fi
-+
-+# Copy the object files from a particular stage into a subdirectory.
-+stage1-start:
-+ -if [ -d stage1 ] ; then true ; else mkdir stage1 ; fi
-+ $(MAKE) -f libgcc.mk libgcc-stage-start stage=stage1
-+ -for dir in intl $(SUBDIRS) ; \
-+ do \
-+ if [ -d stage1/$$dir ] ; then true ; else mkdir stage1/$$dir ; fi ; \
-+ done
-+ -mv $(STAGESTUFF) stage1
-+ -mv intl/*$(objext) stage1/intl
-+# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
-+# dir will work properly.
-+ -if [ -f as$(exeext) ] ; then (cd stage1 && $(LN_S) ../as$(exeext) .) ; else true ; fi
-+ -if [ -f ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-+ -if [ -f collect-ld$(exeext) ] ; then (cd stage1 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
-+ -rm -f stage1/libgcc.a stage1/libgcc_eh.a
-+ -cp libgcc.a stage1
-+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
-+ $(RANLIB_FOR_TARGET) stage1/libgcc.a; \
-+ else true; fi
-+ -if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage1; \
-+ if $(RANLIB_TEST_FOR_TARGET) ; then \
-+ $(RANLIB_FOR_TARGET) stage1/libgcc_eh.a; \
-+ else true; fi; fi
-+ -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
-+ cp stage1/$${f} . ; \
-+ else true; \
-+ fi; done
-+stage1: force stage1-start lang.stage1
-+
-+stage2-start:
-+ -if [ -d stage2 ] ; then true ; else mkdir stage2 ; fi
-+ $(MAKE) -f libgcc.mk libgcc-stage-start stage=stage2
-+ -for dir in intl $(SUBDIRS) ; \
-+ do \
-+ if [ -d stage2/$$dir ] ; then true ; else mkdir stage2/$$dir ; fi ; \
-+ done
-+ -mv $(STAGESTUFF) stage2
-+ -mv intl/*$(objext) stage2/intl
-+# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
-+# dir will work properly.
-+ -if [ -f as$(exeext) ] ; then (cd stage2 && $(LN_S) ../as$(exeext) .) ; else true ; fi
-+ -if [ -f ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-+ -if [ -f collect-ld$(exeext) ] ; then (cd stage2 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
-+ -rm -f stage2/libgcc.a stage2/libgcc_eh.a
-+ -cp libgcc.a stage2
-+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
-+ $(RANLIB_FOR_TARGET) stage2/libgcc.a; \
-+ else true; fi
-+ -if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage2; \
-+ if $(RANLIB_TEST_FOR_TARGET) ; then \
-+ $(RANLIB_FOR_TARGET) stage2/libgcc_eh.a; \
-+ else true; fi; fi
-+ -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
-+ cp stage2/$${f} . ; \
-+ else true; \
-+ fi; done
-+stage2: force stage2-start lang.stage2
-+
-+stage3-start:
-+ -if [ -d stage3 ] ; then true ; else mkdir stage3 ; fi
-+ $(MAKE) -f libgcc.mk libgcc-stage-start stage=stage3
-+ -for dir in intl $(SUBDIRS) ; \
-+ do \
-+ if [ -d stage3/$$dir ] ; then true ; else mkdir stage3/$$dir ; fi ; \
-+ done
-+ -mv $(STAGESTUFF) stage3
-+ -mv intl/*$(objext) stage3/intl
-+# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
-+# dir will work properly.
-+ -if [ -f as$(exeext) ] ; then (cd stage3 && $(LN_S) ../as$(exeext) .) ; else true ; fi
-+ -if [ -f ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-+ -if [ -f collect-ld$(exeext) ] ; then (cd stage3 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
-+ -rm -f stage3/libgcc.a stage3/libgcc_eh.a
-+ -cp libgcc.a stage3
-+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
-+ $(RANLIB_FOR_TARGET) stage3/libgcc.a; \
-+ else true; fi
-+ -if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage3; \
-+ if $(RANLIB_TEST_FOR_TARGET) ; then \
-+ $(RANLIB_FOR_TARGET) stage3/libgcc_eh.a; \
-+ else true; fi; fi
-+ -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
-+ cp stage3/$${f} . ; \
-+ else true; \
-+ fi; done
-+stage3: force stage3-start lang.stage3
-+
-+stage4-start:
-+ -if [ -d stage4 ] ; then true ; else mkdir stage4 ; fi
-+ $(MAKE) -f libgcc.mk libgcc-stage-start stage=stage4
-+ -for dir in intl $(SUBDIRS) ; \
-+ do \
-+ if [ -d stage4/$$dir ] ; then true ; else mkdir stage4/$$dir ; fi ; \
-+ done
-+ -mv $(STAGESTUFF) stage4
-+ -mv intl/*$(objext) stage4/intl
-+# Copy as/ld if they exist to stage dir, so that running xgcc from the stage
-+# dir will work properly.
-+ -if [ -f as$(exeext) ] ; then (cd stage4 && $(LN_S) ../as$(exeext) .) ; else true ; fi
-+ -if [ -f ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../ld$(exeext) .) ; else true ; fi
-+ -if [ -f collect-ld$(exeext) ] ; then (cd stage4 && $(LN_S) ../collect-ld$(exeext) .) ; else true ; fi
-+ -rm -f stage4/libgcc.a stage4/libgcc_eh.a
-+ -cp libgcc.a stage4
-+ -if $(RANLIB_TEST_FOR_TARGET) ; then \
-+ $(RANLIB_FOR_TARGET) stage4/libgcc.a; \
-+ else true; fi
-+ -if [ -f libgcc_eh.a ] ; then cp libgcc_eh.a stage4; \
-+ if $(RANLIB_TEST_FOR_TARGET) ; then \
-+ $(RANLIB_FOR_TARGET) stage4/libgcc_eh.a; \
-+ else true; fi; fi
-+ -for f in .. $(EXTRA_MULTILIB_PARTS); do if [ x$${f} != x.. ]; then \
-+ cp stage4/$${f} . ; \
-+ else true; \
-+ fi; done
-+stage4: force stage4-start lang.stage4
-+
-+# Copy just the executable files from a particular stage into a subdirectory,
-+# and delete the object files. Use this if you're just verifying a version
-+# that is pretty sure to work, and you are short of disk space.
-+risky-stage1: stage1
-+ -$(MAKE) clean
-+
-+risky-stage2: stage2
-+ -$(MAKE) clean
-+
-+risky-stage3: stage3
-+ -$(MAKE) clean
-+
-+risky-stage4: stage4
-+ -$(MAKE) clean
-+
-+#In GNU Make, ignore whether `stage*' exists.
-+.PHONY: stage1 stage2 stage3 stage4 clean maintainer-clean TAGS bootstrap
-+.PHONY: risky-stage1 risky-stage2 risky-stage3 risky-stage4
-+
-+force:
-+
-+# Rules for generating translated message descriptions.
-+# Disabled by autoconf if the tools are not available.
-+
-+XGETTEXT = @XGETTEXT@
-+GMSGFMT = @GMSGFMT@
-+MSGMERGE = msgmerge
-+
-+PACKAGE = @PACKAGE@
-+CATALOGS = @CATALOGS@
-+
-+.PHONY: build- install- build-po install-po update-po
-+
-+# Dummy rules to deal with dependencies produced by use of
-+# "build-@POSUB@" and "install-@POSUB@" above, when NLS is disabled.
-+build-: ; @true
-+install-: ; @true
-+
-+build-po: $(CATALOGS)
-+
-+# This notation should be acceptable to all Make implementations used
-+# by people who are interested in updating .po files.
-+update-po: $(CATALOGS:.gmo=.pox)
-+
-+# N.B. We do not attempt to copy these into $(srcdir). The snapshot
-+# script does that.
-+.po.gmo:
-+ -test -d po || mkdir po
-+ $(GMSGFMT) --statistics -o $@ $<
-+
-+# The new .po has to be gone over by hand, so we deposit it into
-+# build/po with a different extension.
-+# If build/po/$(PACKAGE).pot exists, use it (it was just created),
-+# else use the one in srcdir.
-+.po.pox:
-+ -test -d po || mkdir po
-+ $(MSGMERGE) $< `if test -f po/$(PACKAGE).pot; \
-+ then echo po/$(PACKAGE).pot; \
-+ else echo $(srcdir)/po/$(PACKAGE).pot; fi` -o $@
-+
-+# This rule has to look for .gmo modules in both srcdir and
-+# the cwd, and has to check that we actually have a catalog
-+# for each language, in case they weren't built or included
-+# with the distribution.
-+install-po:
-+ $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(datadir)
-+ for cat in $(CATALOGS); do \
-+ lang=`basename $$cat | sed 's/\.gmo$$//'`; \
-+ if [ -f $$cat ]; then :; \
-+ elif [ -f $(srcdir)/$$cat ]; then cat=$(srcdir)/$$cat; \
-+ else continue; \
-+ fi; \
-+ dir=$(localedir)/$$lang/LC_MESSAGES; \
-+ echo $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$$dir; \
-+ $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$$dir || exit 1; \
-+ echo $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \
-+ $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/$(PACKAGE).mo; \
-+ done
-+
-+# Rule for regenerating the message template (gcc.pot).
-+# Instead of forcing everyone to edit POTFILES.in, which proved impractical,
-+# this rule has no dependencies and always regenerates gcc.pot. This is
-+# relatively harmless since the .po files do not directly depend on it.
-+# Note that exgettext has an awk script embedded in it which requires a
-+# fairly modern (POSIX-compliant) awk.
-+# The .pot file is left in the build directory.
-+$(PACKAGE).pot: po/$(PACKAGE).pot
-+po/$(PACKAGE).pot: force
-+ -test -d po || mkdir po
-+ $(MAKE) po-generated
-+ AWK=$(AWK) $(SHELL) $(srcdir)/po/exgettext \
-+ $(XGETTEXT) $(PACKAGE) $(srcdir)
-diff -ruN gcc-3.3.1/gcc/calls.c gcc-3.3.1.pp/gcc/calls.c
+diff -urN gcc-3.3.1/gcc/calls.c gcc-3.3.1-pp/gcc/calls.c
--- gcc-3.3.1/gcc/calls.c 2003-07-18 02:58:25.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/calls.c 2003-09-05 11:58:58.000000000 +0000
++++ gcc-3.3.1-pp/gcc/calls.c 2003-09-12 13:40:28.000000000 +0000
@@ -2327,7 +2327,7 @@
/* For variable-sized objects, we must be called with a target
specified. If we were to allocate space on the stack here,
mark_temp_addr_taken (d);
structure_value_addr = XEXP (d, 0);
-diff -ruN gcc-3.3.1/gcc/calls.c.orig gcc-3.3.1.pp/gcc/calls.c.orig
---- gcc-3.3.1/gcc/calls.c.orig 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/calls.c.orig 2003-07-18 02:58:25.000000000 +0000
-@@ -0,0 +1,4667 @@
-+/* Convert function calls to rtl insns, for GNU C compiler.
-+ Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-+
-+This file is part of GCC.
-+
-+GCC is free software; you can redistribute it and/or modify it under
-+the terms of the GNU General Public License as published by the Free
-+Software Foundation; either version 2, or (at your option) any later
-+version.
-+
-+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-+WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GCC; see the file COPYING. If not, write to the Free
-+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-+02111-1307, USA. */
-+
-+#include "config.h"
-+#include "system.h"
-+#include "rtl.h"
-+#include "tree.h"
-+#include "flags.h"
-+#include "expr.h"
-+#include "libfuncs.h"
-+#include "function.h"
-+#include "regs.h"
-+#include "toplev.h"
-+#include "output.h"
-+#include "tm_p.h"
-+#include "timevar.h"
-+#include "sbitmap.h"
-+#include "langhooks.h"
-+#include "target.h"
-+#include "except.h"
-+
-+#if !defined FUNCTION_OK_FOR_SIBCALL
-+#define FUNCTION_OK_FOR_SIBCALL(DECL) 1
-+#endif
-+
-+/* Decide whether a function's arguments should be processed
-+ from first to last or from last to first.
-+
-+ They should if the stack and args grow in opposite directions, but
-+ only if we have push insns. */
-+
-+#ifdef PUSH_ROUNDING
-+
-+#ifndef PUSH_ARGS_REVERSED
-+#if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
-+#define PUSH_ARGS_REVERSED PUSH_ARGS
-+#endif
-+#endif
-+
-+#endif
-+
-+#ifndef PUSH_ARGS_REVERSED
-+#define PUSH_ARGS_REVERSED 0
+diff -urN gcc-3.3.1/gcc/combine.c gcc-3.3.1-pp/gcc/combine.c
+--- gcc-3.3.1/gcc/combine.c 2003-03-24 11:37:32.000000000 +0000
++++ gcc-3.3.1-pp/gcc/combine.c 2003-09-12 13:40:28.000000000 +0000
+@@ -3859,7 +3859,17 @@
+ rtx inner_op0 = XEXP (XEXP (x, 0), 1);
+ rtx inner_op1 = XEXP (x, 1);
+ rtx inner;
+-
++
++#ifndef FRAME_GROWS_DOWNWARD
++ if (flag_propolice_protection
++ && code == PLUS
++ && other == frame_pointer_rtx
++ && GET_CODE (inner_op0) == CONST_INT
++ && GET_CODE (inner_op1) == CONST_INT
++ && INTVAL (inner_op0) > 0
++ && INTVAL (inner_op0) + INTVAL (inner_op1) <= 0)
++ return x;
+#endif
-+
-+#ifndef STACK_POINTER_OFFSET
-+#define STACK_POINTER_OFFSET 0
+ /* Make sure we pass the constant operand if any as the second
+ one if this is a commutative operation. */
+ if (CONSTANT_P (inner_op0) && GET_RTX_CLASS (code) == 'c')
+@@ -4272,6 +4282,11 @@
+ they are now checked elsewhere. */
+ if (GET_CODE (XEXP (x, 0)) == PLUS
+ && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
++#ifndef FRAME_GROWS_DOWNWARD
++ if (! (flag_propolice_protection
++ && XEXP (XEXP (x, 0), 0) == frame_pointer_rtx
++ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+#endif
-+
-+/* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */
-+#define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
-+
-+/* Data structure and subroutines used within expand_call. */
-+
-+struct arg_data
-+{
-+ /* Tree node for this argument. */
-+ tree tree_value;
-+ /* Mode for value; TYPE_MODE unless promoted. */
-+ enum machine_mode mode;
-+ /* Current RTL value for argument, or 0 if it isn't precomputed. */
-+ rtx value;
-+ /* Initially-compute RTL value for argument; only for const functions. */
-+ rtx initial_value;
-+ /* Register to pass this argument in, 0 if passed on stack, or an
-+ PARALLEL if the arg is to be copied into multiple non-contiguous
-+ registers. */
-+ rtx reg;
-+ /* Register to pass this argument in when generating tail call sequence.
-+ This is not the same register as for normal calls on machines with
-+ register windows. */
-+ rtx tail_call_reg;
-+ /* If REG was promoted from the actual mode of the argument expression,
-+ indicates whether the promotion is sign- or zero-extended. */
-+ int unsignedp;
-+ /* Number of registers to use. 0 means put the whole arg in registers.
-+ Also 0 if not passed in registers. */
-+ int partial;
-+ /* Nonzero if argument must be passed on stack.
-+ Note that some arguments may be passed on the stack
-+ even though pass_on_stack is zero, just because FUNCTION_ARG says so.
-+ pass_on_stack identifies arguments that *cannot* go in registers. */
-+ int pass_on_stack;
-+ /* Offset of this argument from beginning of stack-args. */
-+ struct args_size offset;
-+ /* Similar, but offset to the start of the stack slot. Different from
-+ OFFSET if this arg pads downward. */
-+ struct args_size slot_offset;
-+ /* Size of this argument on the stack, rounded up for any padding it gets,
-+ parts of the argument passed in registers do not count.
-+ If REG_PARM_STACK_SPACE is defined, then register parms
-+ are counted here as well. */
-+ struct args_size size;
-+ /* Location on the stack at which parameter should be stored. The store
-+ has already been done if STACK == VALUE. */
-+ rtx stack;
-+ /* Location on the stack of the start of this argument slot. This can
-+ differ from STACK if this arg pads downward. This location is known
-+ to be aligned to FUNCTION_ARG_BOUNDARY. */
-+ rtx stack_slot;
-+ /* Place that this stack area has been saved, if needed. */
-+ rtx save_area;
-+ /* If an argument's alignment does not permit direct copying into registers,
-+ copy in smaller-sized pieces into pseudos. These are stored in a
-+ block pointed to by this field. The next field says how many
-+ word-sized pseudos we made. */
-+ rtx *aligned_regs;
-+ int n_aligned_regs;
-+ /* The amount that the stack pointer needs to be adjusted to
-+ force alignment for the next argument. */
-+ struct args_size alignment_pad;
-+};
-+
-+/* A vector of one char per byte of stack space. A byte if nonzero if
-+ the corresponding stack location has been used.
-+ This vector is used to prevent a function call within an argument from
-+ clobbering any stack already set up. */
-+static char *stack_usage_map;
-+
-+/* Size of STACK_USAGE_MAP. */
-+static int highest_outgoing_arg_in_use;
-+
-+/* A bitmap of virtual-incoming stack space. Bit is set if the corresponding
-+ stack location's tail call argument has been already stored into the stack.
-+ This bitmap is used to prevent sibling call optimization if function tries
-+ to use parent's incoming argument slots when they have been already
-+ overwritten with tail call arguments. */
-+static sbitmap stored_args_map;
-+
-+/* stack_arg_under_construction is nonzero when an argument may be
-+ initialized with a constructor call (including a C function that
-+ returns a BLKmode struct) and expand_call must take special action
-+ to make sure the object being constructed does not overlap the
-+ argument list for the constructor call. */
-+int stack_arg_under_construction;
-+
-+static int calls_function PARAMS ((tree, int));
-+static int calls_function_1 PARAMS ((tree, int));
-+
-+/* Nonzero if this is a call to a `const' function. */
-+#define ECF_CONST 1
-+/* Nonzero if this is a call to a `volatile' function. */
-+#define ECF_NORETURN 2
-+/* Nonzero if this is a call to malloc or a related function. */
-+#define ECF_MALLOC 4
-+/* Nonzero if it is plausible that this is a call to alloca. */
-+#define ECF_MAY_BE_ALLOCA 8
-+/* Nonzero if this is a call to a function that won't throw an exception. */
-+#define ECF_NOTHROW 16
-+/* Nonzero if this is a call to setjmp or a related function. */
-+#define ECF_RETURNS_TWICE 32
-+/* Nonzero if this is a call to `longjmp'. */
-+#define ECF_LONGJMP 64
-+/* Nonzero if this is a syscall that makes a new process in the image of
-+ the current one. */
-+#define ECF_FORK_OR_EXEC 128
-+#define ECF_SIBCALL 256
-+/* Nonzero if this is a call to "pure" function (like const function,
-+ but may read memory. */
-+#define ECF_PURE 512
-+/* Nonzero if this is a call to a function that returns with the stack
-+ pointer depressed. */
-+#define ECF_SP_DEPRESSED 1024
-+/* Nonzero if this call is known to always return. */
-+#define ECF_ALWAYS_RETURN 2048
-+/* Create libcall block around the call. */
-+#define ECF_LIBCALL_BLOCK 4096
-+
-+static void emit_call_1 PARAMS ((rtx, tree, tree, HOST_WIDE_INT,
-+ HOST_WIDE_INT, HOST_WIDE_INT, rtx,
-+ rtx, int, rtx, int,
-+ CUMULATIVE_ARGS *));
-+static void precompute_register_parameters PARAMS ((int,
-+ struct arg_data *,
-+ int *));
-+static int store_one_arg PARAMS ((struct arg_data *, rtx, int, int,
-+ int));
-+static void store_unaligned_arguments_into_pseudos PARAMS ((struct arg_data *,
-+ int));
-+static int finalize_must_preallocate PARAMS ((int, int,
-+ struct arg_data *,
-+ struct args_size *));
-+static void precompute_arguments PARAMS ((int, int,
-+ struct arg_data *));
-+static int compute_argument_block_size PARAMS ((int,
-+ struct args_size *,
-+ int));
-+static void initialize_argument_information PARAMS ((int,
-+ struct arg_data *,
-+ struct args_size *,
-+ int, tree, tree,
-+ CUMULATIVE_ARGS *,
-+ int, rtx *, int *,
-+ int *, int *));
-+static void compute_argument_addresses PARAMS ((struct arg_data *,
-+ rtx, int));
-+static rtx rtx_for_function_call PARAMS ((tree, tree));
-+static void load_register_parameters PARAMS ((struct arg_data *,
-+ int, rtx *, int));
-+static rtx emit_library_call_value_1 PARAMS ((int, rtx, rtx,
-+ enum libcall_type,
-+ enum machine_mode,
-+ int, va_list));
-+static int special_function_p PARAMS ((tree, int));
-+static int flags_from_decl_or_type PARAMS ((tree));
-+static rtx try_to_integrate PARAMS ((tree, tree, rtx,
-+ int, tree, rtx));
-+static int check_sibcall_argument_overlap_1 PARAMS ((rtx));
-+static int check_sibcall_argument_overlap PARAMS ((rtx, struct arg_data *));
-+
-+static int combine_pending_stack_adjustment_and_call
-+ PARAMS ((int, struct args_size *, int));
-+static tree fix_unsafe_tree PARAMS ((tree));
-+
-+#ifdef REG_PARM_STACK_SPACE
-+static rtx save_fixed_argument_area PARAMS ((int, rtx, int *, int *));
-+static void restore_fixed_argument_area PARAMS ((rtx, rtx, int, int));
+ return gen_binary (PLUS, mode,
+ gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0),
+ XEXP (x, 1)),
+@@ -4400,7 +4415,10 @@
+
+ /* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for
+ integers. */
+- if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode))
++ if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode)
++ && (! (flag_propolice_protection
++ && XEXP (XEXP (x, 1), 0) == frame_pointer_rtx
++ && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)))
+ return gen_binary (MINUS, mode,
+ gen_binary (MINUS, mode, XEXP (x, 0),
+ XEXP (XEXP (x, 1), 0)),
+diff -urN gcc-3.3.1/gcc/config/t-linux gcc-3.3.1-pp/gcc/config/t-linux
+--- gcc-3.3.1/gcc/config/t-linux 2003-06-04 16:56:11.000000000 +0000
++++ gcc-3.3.1-pp/gcc/config/t-linux 2003-09-12 13:40:28.000000000 +0000
+@@ -4,7 +4,7 @@
+ # Compile crtbeginS.o and crtendS.o with pic.
+ CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
+ # Compile libgcc2.a with pic.
+-TARGET_LIBGCC2_CFLAGS = -fPIC
++TARGET_LIBGCC2_CFLAGS = -fPIC -DHAVE_SYSLOG
+
+ # Override t-slibgcc-elf-ver to export some libgcc symbols with
+ # the symbol versions that glibc used.
+diff -urN gcc-3.3.1/gcc/cse.c gcc-3.3.1-pp/gcc/cse.c
+--- gcc-3.3.1/gcc/cse.c 2003-04-29 19:16:40.000000000 +0000
++++ gcc-3.3.1-pp/gcc/cse.c 2003-09-12 13:40:28.000000000 +0000
+@@ -4288,7 +4288,14 @@
+
+ if (new_const == 0)
+ break;
+-
++#ifndef FRAME_GROWS_DOWNWARD
++ if (flag_propolice_protection
++ && GET_CODE (y) == PLUS
++ && XEXP (y, 0) == frame_pointer_rtx
++ && INTVAL (inner_const) > 0
++ && INTVAL (new_const) <= 0)
++ break;
+#endif
-+\f
-+/* If WHICH is 1, return 1 if EXP contains a call to the built-in function
-+ `alloca'.
-+
-+ If WHICH is 0, return 1 if EXP contains a call to any function.
-+ Actually, we only need return 1 if evaluating EXP would require pushing
-+ arguments on the stack, but that is too difficult to compute, so we just
-+ assume any function call might require the stack. */
-+
-+static tree calls_function_save_exprs;
-+
-+static int
-+calls_function (exp, which)
-+ tree exp;
-+ int which;
-+{
-+ int val;
-+
-+ calls_function_save_exprs = 0;
-+ val = calls_function_1 (exp, which);
-+ calls_function_save_exprs = 0;
-+ return val;
-+}
-+
-+/* Recursive function to do the work of above function. */
-+
-+static int
-+calls_function_1 (exp, which)
-+ tree exp;
-+ int which;
-+{
-+ int i;
-+ enum tree_code code = TREE_CODE (exp);
-+ int class = TREE_CODE_CLASS (code);
-+ int length = first_rtl_op (code);
-+
-+ /* If this code is language-specific, we don't know what it will do. */
-+ if ((int) code >= NUM_TREE_CODES)
-+ return 1;
-+
-+ switch (code)
-+ {
-+ case CALL_EXPR:
-+ if (which == 0)
-+ return 1;
-+ else if ((TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
-+ == FUNCTION_TYPE)
-+ && (TYPE_RETURNS_STACK_DEPRESSED
-+ (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))))
-+ return 1;
-+ else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
-+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
-+ == FUNCTION_DECL)
-+ && (special_function_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-+ 0)
-+ & ECF_MAY_BE_ALLOCA))
-+ return 1;
-+
-+ break;
-+
-+ case CONSTRUCTOR:
-+ {
-+ tree tem;
-+
-+ for (tem = CONSTRUCTOR_ELTS (exp); tem != 0; tem = TREE_CHAIN (tem))
-+ if (calls_function_1 (TREE_VALUE (tem), which))
-+ return 1;
-+ }
-+
-+ return 0;
-+
-+ case SAVE_EXPR:
-+ if (SAVE_EXPR_RTL (exp) != 0)
-+ return 0;
-+ if (value_member (exp, calls_function_save_exprs))
-+ return 0;
-+ calls_function_save_exprs = tree_cons (NULL_TREE, exp,
-+ calls_function_save_exprs);
-+ return (TREE_OPERAND (exp, 0) != 0
-+ && calls_function_1 (TREE_OPERAND (exp, 0), which));
-+
-+ case BLOCK:
-+ {
-+ tree local;
-+ tree subblock;
-+
-+ for (local = BLOCK_VARS (exp); local; local = TREE_CHAIN (local))
-+ if (DECL_INITIAL (local) != 0
-+ && calls_function_1 (DECL_INITIAL (local), which))
-+ return 1;
-+
-+ for (subblock = BLOCK_SUBBLOCKS (exp);
-+ subblock;
-+ subblock = TREE_CHAIN (subblock))
-+ if (calls_function_1 (subblock, which))
-+ return 1;
+ /* If we are associating shift operations, don't let this
+ produce a shift of the size of the object or larger.
+ This could occur when we follow a sign-extend by a right
+@@ -4823,6 +4830,13 @@
+ if (SET_DEST (x) == pc_rtx
+ && GET_CODE (SET_SRC (x)) == LABEL_REF)
+ ;
++ /* cut the reg propagation of stack-protected argument */
++ else if (x->volatil) {
++ rtx x1 = SET_DEST (x);
++ if (GET_CODE (x1) == SUBREG && GET_CODE (SUBREG_REG (x1)) == REG)
++ x1 = SUBREG_REG (x1);
++ make_new_qty (REGNO (x1), GET_MODE (x1));
+ }
-+ return 0;
-+
-+ case TREE_LIST:
-+ for (; exp != 0; exp = TREE_CHAIN (exp))
-+ if (calls_function_1 (TREE_VALUE (exp), which))
-+ return 1;
-+ return 0;
-+
-+ default:
-+ break;
-+ }
-+
-+ /* Only expressions, references, and blocks can contain calls. */
-+ if (! IS_EXPR_CODE_CLASS (class) && class != 'r' && class != 'b')
-+ return 0;
-+
-+ for (i = 0; i < length; i++)
-+ if (TREE_OPERAND (exp, i) != 0
-+ && calls_function_1 (TREE_OPERAND (exp, i), which))
-+ return 1;
-+
-+ return 0;
-+}
-+\f
-+/* Force FUNEXP into a form suitable for the address of a CALL,
-+ and return that as an rtx. Also load the static chain register
-+ if FNDECL is a nested function.
-+
-+ CALL_FUSAGE points to a variable holding the prospective
-+ CALL_INSN_FUNCTION_USAGE information. */
-+
-+rtx
-+prepare_call_address (funexp, fndecl, call_fusage, reg_parm_seen, sibcallp)
-+ rtx funexp;
-+ tree fndecl;
-+ rtx *call_fusage;
-+ int reg_parm_seen;
-+ int sibcallp;
-+{
-+ rtx static_chain_value = 0;
-+
-+ funexp = protect_from_queue (funexp, 0);
-+
-+ if (fndecl != 0)
-+ /* Get possible static chain value for nested function in C. */
-+ static_chain_value = lookup_static_chain (fndecl);
-+
-+ /* Make a valid memory address and copy constants thru pseudo-regs,
-+ but not for a constant address if -fno-function-cse. */
-+ if (GET_CODE (funexp) != SYMBOL_REF)
-+ /* If we are using registers for parameters, force the
-+ function address into a register now. */
-+ funexp = ((SMALL_REGISTER_CLASSES && reg_parm_seen)
-+ ? force_not_mem (memory_address (FUNCTION_MODE, funexp))
-+ : memory_address (FUNCTION_MODE, funexp));
-+ else if (! sibcallp)
-+ {
-+#ifndef NO_FUNCTION_CSE
-+ if (optimize && ! flag_no_function_cse)
-+#ifdef NO_RECURSIVE_FUNCTION_CSE
-+ if (fndecl != current_function_decl)
-+#endif
-+ funexp = force_reg (Pmode, funexp);
-+#endif
-+ }
-+
-+ if (static_chain_value != 0)
-+ {
-+ emit_move_insn (static_chain_rtx, static_chain_value);
-+
-+ if (GET_CODE (static_chain_rtx) == REG)
-+ use_reg (call_fusage, static_chain_rtx);
-+ }
-+
-+ return funexp;
-+}
-+
-+/* Generate instructions to call function FUNEXP,
-+ and optionally pop the results.
-+ The CALL_INSN is the first insn generated.
-+
-+ FNDECL is the declaration node of the function. This is given to the
-+ macro RETURN_POPS_ARGS to determine whether this function pops its own args.
-+
-+ FUNTYPE is the data type of the function. This is given to the macro
-+ RETURN_POPS_ARGS to determine whether this function pops its own args.
-+ We used to allow an identifier for library functions, but that doesn't
-+ work when the return type is an aggregate type and the calling convention
-+ says that the pointer to this aggregate is to be popped by the callee.
-+
-+ STACK_SIZE is the number of bytes of arguments on the stack,
-+ ROUNDED_STACK_SIZE is that number rounded up to
-+ PREFERRED_STACK_BOUNDARY; zero if the size is variable. This is
-+ both to put into the call insn and to generate explicit popping
-+ code if necessary.
-+
-+ STRUCT_VALUE_SIZE is the number of bytes wanted in a structure value.
-+ It is zero if this call doesn't want a structure value.
-+
-+ NEXT_ARG_REG is the rtx that results from executing
-+ FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1)
-+ just after all the args have had their registers assigned.
-+ This could be whatever you like, but normally it is the first
-+ arg-register beyond those used for args in this call,
-+ or 0 if all the arg-registers are used in this call.
-+ It is passed on to `gen_call' so you can put this info in the call insn.
-+
-+ VALREG is a hard register in which a value is returned,
-+ or 0 if the call does not return a value.
-+
-+ OLD_INHIBIT_DEFER_POP is the value that `inhibit_defer_pop' had before
-+ the args to this call were processed.
-+ We restore `inhibit_defer_pop' to that value.
-+
-+ CALL_FUSAGE is either empty or an EXPR_LIST of USE expressions that
-+ denote registers used by the called function. */
-+
-+static void
-+emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
-+ struct_value_size, next_arg_reg, valreg, old_inhibit_defer_pop,
-+ call_fusage, ecf_flags, args_so_far)
-+ rtx funexp;
-+ tree fndecl ATTRIBUTE_UNUSED;
-+ tree funtype ATTRIBUTE_UNUSED;
-+ HOST_WIDE_INT stack_size ATTRIBUTE_UNUSED;
-+ HOST_WIDE_INT rounded_stack_size;
-+ HOST_WIDE_INT struct_value_size ATTRIBUTE_UNUSED;
-+ rtx next_arg_reg ATTRIBUTE_UNUSED;
-+ rtx valreg;
-+ int old_inhibit_defer_pop;
-+ rtx call_fusage;
-+ int ecf_flags;
-+ CUMULATIVE_ARGS *args_so_far ATTRIBUTE_UNUSED;
-+{
-+ rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
-+ rtx call_insn;
-+ int already_popped = 0;
-+ HOST_WIDE_INT n_popped = RETURN_POPS_ARGS (fndecl, funtype, stack_size);
-+#if defined (HAVE_call) && defined (HAVE_call_value)
-+ rtx struct_value_size_rtx;
-+ struct_value_size_rtx = GEN_INT (struct_value_size);
-+#endif
-+
-+#ifdef CALL_POPS_ARGS
-+ n_popped += CALL_POPS_ARGS (* args_so_far);
-+#endif
-+
-+ /* Ensure address is valid. SYMBOL_REF is already valid, so no need,
-+ and we don't want to load it into a register as an optimization,
-+ because prepare_call_address already did it if it should be done. */
-+ if (GET_CODE (funexp) != SYMBOL_REF)
-+ funexp = memory_address (FUNCTION_MODE, funexp);
-+
-+#if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop)
-+ if ((ecf_flags & ECF_SIBCALL)
-+ && HAVE_sibcall_pop && HAVE_sibcall_value_pop
-+ && (n_popped > 0 || stack_size == 0))
-+ {
-+ rtx n_pop = GEN_INT (n_popped);
-+ rtx pat;
-+
-+ /* If this subroutine pops its own args, record that in the call insn
-+ if possible, for the sake of frame pointer elimination. */
-+
-+ if (valreg)
-+ pat = GEN_SIBCALL_VALUE_POP (valreg,
-+ gen_rtx_MEM (FUNCTION_MODE, funexp),
-+ rounded_stack_size_rtx, next_arg_reg,
-+ n_pop);
-+ else
-+ pat = GEN_SIBCALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp),
-+ rounded_stack_size_rtx, next_arg_reg, n_pop);
-+
-+ emit_call_insn (pat);
-+ already_popped = 1;
-+ }
-+ else
-+#endif
-+
-+#if defined (HAVE_call_pop) && defined (HAVE_call_value_pop)
-+ /* If the target has "call" or "call_value" insns, then prefer them
-+ if no arguments are actually popped. If the target does not have
-+ "call" or "call_value" insns, then we must use the popping versions
-+ even if the call has no arguments to pop. */
-+#if defined (HAVE_call) && defined (HAVE_call_value)
-+ if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop
-+ && n_popped > 0 && ! (ecf_flags & ECF_SP_DEPRESSED))
-+#else
-+ if (HAVE_call_pop && HAVE_call_value_pop)
-+#endif
-+ {
-+ rtx n_pop = GEN_INT (n_popped);
-+ rtx pat;
-+
-+ /* If this subroutine pops its own args, record that in the call insn
-+ if possible, for the sake of frame pointer elimination. */
-+
-+ if (valreg)
-+ pat = GEN_CALL_VALUE_POP (valreg,
-+ gen_rtx_MEM (FUNCTION_MODE, funexp),
-+ rounded_stack_size_rtx, next_arg_reg, n_pop);
-+ else
-+ pat = GEN_CALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp),
-+ rounded_stack_size_rtx, next_arg_reg, n_pop);
-+
-+ emit_call_insn (pat);
-+ already_popped = 1;
-+ }
-+ else
-+#endif
-+
-+#if defined (HAVE_sibcall) && defined (HAVE_sibcall_value)
-+ if ((ecf_flags & ECF_SIBCALL)
-+ && HAVE_sibcall && HAVE_sibcall_value)
-+ {
-+ if (valreg)
-+ emit_call_insn (GEN_SIBCALL_VALUE (valreg,
-+ gen_rtx_MEM (FUNCTION_MODE, funexp),
-+ rounded_stack_size_rtx,
-+ next_arg_reg, NULL_RTX));
-+ else
-+ emit_call_insn (GEN_SIBCALL (gen_rtx_MEM (FUNCTION_MODE, funexp),
-+ rounded_stack_size_rtx, next_arg_reg,
-+ struct_value_size_rtx));
-+ }
-+ else
-+#endif
-+
-+#if defined (HAVE_call) && defined (HAVE_call_value)
-+ if (HAVE_call && HAVE_call_value)
-+ {
-+ if (valreg)
-+ emit_call_insn (GEN_CALL_VALUE (valreg,
-+ gen_rtx_MEM (FUNCTION_MODE, funexp),
-+ rounded_stack_size_rtx, next_arg_reg,
-+ NULL_RTX));
-+ else
-+ emit_call_insn (GEN_CALL (gen_rtx_MEM (FUNCTION_MODE, funexp),
-+ rounded_stack_size_rtx, next_arg_reg,
-+ struct_value_size_rtx));
-+ }
-+ else
-+#endif
-+ abort ();
-+
-+ /* Find the CALL insn we just emitted. */
-+ for (call_insn = get_last_insn ();
-+ call_insn && GET_CODE (call_insn) != CALL_INSN;
-+ call_insn = PREV_INSN (call_insn))
-+ ;
-+
-+ if (! call_insn)
-+ abort ();
-+
-+ /* Mark memory as used for "pure" function call. */
-+ if (ecf_flags & ECF_PURE)
-+ call_fusage
-+ = gen_rtx_EXPR_LIST
-+ (VOIDmode,
-+ gen_rtx_USE (VOIDmode,
-+ gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))),
-+ call_fusage);
-+
-+ /* Put the register usage information on the CALL. If there is already
-+ some usage information, put ours at the end. */
-+ if (CALL_INSN_FUNCTION_USAGE (call_insn))
-+ {
-+ rtx link;
-+
-+ for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
-+ link = XEXP (link, 1))
-+ ;
-+
-+ XEXP (link, 1) = call_fusage;
-+ }
-+ else
-+ CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
-+
-+ /* If this is a const call, then set the insn's unchanging bit. */
-+ if (ecf_flags & (ECF_CONST | ECF_PURE))
-+ CONST_OR_PURE_CALL_P (call_insn) = 1;
-+
-+ /* If this call can't throw, attach a REG_EH_REGION reg note to that
-+ effect. */
-+ if (ecf_flags & ECF_NOTHROW)
-+ REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, const0_rtx,
-+ REG_NOTES (call_insn));
-+ else
-+ note_eh_region_may_contain_throw ();
-+
-+ if (ecf_flags & ECF_NORETURN)
-+ REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_NORETURN, const0_rtx,
-+ REG_NOTES (call_insn));
-+ if (ecf_flags & ECF_ALWAYS_RETURN)
-+ REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_ALWAYS_RETURN, const0_rtx,
-+ REG_NOTES (call_insn));
-+
-+ if (ecf_flags & ECF_RETURNS_TWICE)
-+ {
-+ REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_SETJMP, const0_rtx,
-+ REG_NOTES (call_insn));
-+ current_function_calls_setjmp = 1;
-+ }
-+
-+ SIBLING_CALL_P (call_insn) = ((ecf_flags & ECF_SIBCALL) != 0);
-+
-+ /* Restore this now, so that we do defer pops for this call's args
-+ if the context of the call as a whole permits. */
-+ inhibit_defer_pop = old_inhibit_defer_pop;
-+
-+ if (n_popped > 0)
-+ {
-+ if (!already_popped)
-+ CALL_INSN_FUNCTION_USAGE (call_insn)
-+ = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_CLOBBER (VOIDmode, stack_pointer_rtx),
-+ CALL_INSN_FUNCTION_USAGE (call_insn));
-+ rounded_stack_size -= n_popped;
-+ rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
-+ stack_pointer_delta -= n_popped;
-+ }
-+
-+ if (!ACCUMULATE_OUTGOING_ARGS)
-+ {
-+ /* If returning from the subroutine does not automatically pop the args,
-+ we need an instruction to pop them sooner or later.
-+ Perhaps do it now; perhaps just record how much space to pop later.
-+
-+ If returning from the subroutine does pop the args, indicate that the
-+ stack pointer will be changed. */
-+
-+ if (rounded_stack_size != 0)
-+ {
-+ if (ecf_flags & ECF_SP_DEPRESSED)
-+ /* Just pretend we did the pop. */
-+ stack_pointer_delta -= rounded_stack_size;
-+ else if (flag_defer_pop && inhibit_defer_pop == 0
-+ && ! (ecf_flags & (ECF_CONST | ECF_PURE)))
-+ pending_stack_adjust += rounded_stack_size;
-+ else
-+ adjust_stack (rounded_stack_size_rtx);
-+ }
-+ }
-+ /* When we accumulate outgoing args, we must avoid any stack manipulations.
-+ Restore the stack pointer to its original value now. Usually
-+ ACCUMULATE_OUTGOING_ARGS targets don't get here, but there are exceptions.
-+ On i386 ACCUMULATE_OUTGOING_ARGS can be enabled on demand, and
-+ popping variants of functions exist as well.
-+
-+ ??? We may optimize similar to defer_pop above, but it is
-+ probably not worthwhile.
-+
-+ ??? It will be worthwhile to enable combine_stack_adjustments even for
-+ such machines. */
-+ else if (n_popped)
-+ anti_adjust_stack (GEN_INT (n_popped));
-+}
-+
-+/* Determine if the function identified by NAME and FNDECL is one with
-+ special properties we wish to know about.
-+
-+ For example, if the function might return more than one time (setjmp), then
-+ set RETURNS_TWICE to a nonzero value.
-+
-+ Similarly set LONGJMP for if the function is in the longjmp family.
-+
-+ Set MALLOC for any of the standard memory allocation functions which
-+ allocate from the heap.
-+
-+ Set MAY_BE_ALLOCA for any memory allocation function that might allocate
-+ space from the stack such as alloca. */
-+
-+static int
-+special_function_p (fndecl, flags)
-+ tree fndecl;
-+ int flags;
-+{
-+ if (! (flags & ECF_MALLOC)
-+ && fndecl && DECL_NAME (fndecl)
-+ && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
-+ /* Exclude functions not at the file scope, or not `extern',
-+ since they are not the magic functions we would otherwise
-+ think they are. */
-+ && DECL_CONTEXT (fndecl) == NULL_TREE && TREE_PUBLIC (fndecl))
-+ {
-+ const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
-+ const char *tname = name;
-+
-+ /* We assume that alloca will always be called by name. It
-+ makes no sense to pass it as a pointer-to-function to
-+ anything that does not understand its behavior. */
-+ if (((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
-+ && name[0] == 'a'
-+ && ! strcmp (name, "alloca"))
-+ || (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
-+ && name[0] == '_'
-+ && ! strcmp (name, "__builtin_alloca"))))
-+ flags |= ECF_MAY_BE_ALLOCA;
-+
-+ /* Disregard prefix _, __ or __x. */
-+ if (name[0] == '_')
-+ {
-+ if (name[1] == '_' && name[2] == 'x')
-+ tname += 3;
-+ else if (name[1] == '_')
-+ tname += 2;
-+ else
-+ tname += 1;
-+ }
-+
-+ if (tname[0] == 's')
-+ {
-+ if ((tname[1] == 'e'
-+ && (! strcmp (tname, "setjmp")
-+ || ! strcmp (tname, "setjmp_syscall")))
-+ || (tname[1] == 'i'
-+ && ! strcmp (tname, "sigsetjmp"))
-+ || (tname[1] == 'a'
-+ && ! strcmp (tname, "savectx")))
-+ flags |= ECF_RETURNS_TWICE;
-+
-+ if (tname[1] == 'i'
-+ && ! strcmp (tname, "siglongjmp"))
-+ flags |= ECF_LONGJMP;
-+ }
-+ else if ((tname[0] == 'q' && tname[1] == 's'
-+ && ! strcmp (tname, "qsetjmp"))
-+ || (tname[0] == 'v' && tname[1] == 'f'
-+ && ! strcmp (tname, "vfork")))
-+ flags |= ECF_RETURNS_TWICE;
-+
-+ else if (tname[0] == 'l' && tname[1] == 'o'
-+ && ! strcmp (tname, "longjmp"))
-+ flags |= ECF_LONGJMP;
-+
-+ else if ((tname[0] == 'f' && tname[1] == 'o'
-+ && ! strcmp (tname, "fork"))
-+ /* Linux specific: __clone. check NAME to insist on the
-+ leading underscores, to avoid polluting the ISO / POSIX
-+ namespace. */
-+ || (name[0] == '_' && name[1] == '_'
-+ && ! strcmp (tname, "clone"))
-+ || (tname[0] == 'e' && tname[1] == 'x' && tname[2] == 'e'
-+ && tname[3] == 'c' && (tname[4] == 'l' || tname[4] == 'v')
-+ && (tname[5] == '\0'
-+ || ((tname[5] == 'p' || tname[5] == 'e')
-+ && tname[6] == '\0'))))
-+ flags |= ECF_FORK_OR_EXEC;
-+
-+ /* Do not add any more malloc-like functions to this list,
-+ instead mark them as malloc functions using the malloc attribute.
-+ Note, realloc is not suitable for attribute malloc since
-+ it may return the same address across multiple calls.
-+ C++ operator new is not suitable because it is not required
-+ to return a unique pointer; indeed, the standard placement new
-+ just returns its argument. */
-+ else if (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == Pmode
-+ && (! strcmp (tname, "malloc")
-+ || ! strcmp (tname, "calloc")
-+ || ! strcmp (tname, "strdup")))
-+ flags |= ECF_MALLOC;
-+ }
-+ return flags;
-+}
-+
-+/* Return nonzero when tree represent call to longjmp. */
-+
-+int
-+setjmp_call_p (fndecl)
-+ tree fndecl;
-+{
-+ return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE;
-+}
-+
-+/* Return true when exp contains alloca call. */
-+bool
-+alloca_call_p (exp)
-+ tree exp;
-+{
-+ if (TREE_CODE (exp) == CALL_EXPR
-+ && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
-+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
-+ == FUNCTION_DECL)
-+ && (special_function_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-+ 0) & ECF_MAY_BE_ALLOCA))
-+ return true;
-+ return false;
-+}
-+
-+/* Detect flags (function attributes) from the function decl or type node. */
-+
-+static int
-+flags_from_decl_or_type (exp)
-+ tree exp;
-+{
-+ int flags = 0;
-+ tree type = exp;
-+ /* ??? We can't set IS_MALLOC for function types? */
-+ if (DECL_P (exp))
-+ {
-+ type = TREE_TYPE (exp);
-+
-+ /* The function exp may have the `malloc' attribute. */
-+ if (DECL_P (exp) && DECL_IS_MALLOC (exp))
-+ flags |= ECF_MALLOC;
-+
-+ /* The function exp may have the `pure' attribute. */
-+ if (DECL_P (exp) && DECL_IS_PURE (exp))
-+ flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
-+
-+ if (TREE_NOTHROW (exp))
-+ flags |= ECF_NOTHROW;
-+
-+ if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
-+ flags |= ECF_LIBCALL_BLOCK;
-+ }
-+
-+ if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
-+ flags |= ECF_CONST;
-+
-+ if (TREE_THIS_VOLATILE (exp))
-+ flags |= ECF_NORETURN;
-+
-+ /* Mark if the function returns with the stack pointer depressed. We
-+ cannot consider it pure or constant in that case. */
-+ if (TREE_CODE (type) == FUNCTION_TYPE && TYPE_RETURNS_STACK_DEPRESSED (type))
-+ {
-+ flags |= ECF_SP_DEPRESSED;
-+ flags &= ~(ECF_PURE | ECF_CONST | ECF_LIBCALL_BLOCK);
-+ }
-+
-+ return flags;
-+}
-+
-+/* Precompute all register parameters as described by ARGS, storing values
-+ into fields within the ARGS array.
-+
-+ NUM_ACTUALS indicates the total number elements in the ARGS array.
-+
-+ Set REG_PARM_SEEN if we encounter a register parameter. */
-+
-+static void
-+precompute_register_parameters (num_actuals, args, reg_parm_seen)
-+ int num_actuals;
-+ struct arg_data *args;
-+ int *reg_parm_seen;
-+{
-+ int i;
-+
-+ *reg_parm_seen = 0;
-+
-+ for (i = 0; i < num_actuals; i++)
-+ if (args[i].reg != 0 && ! args[i].pass_on_stack)
-+ {
-+ *reg_parm_seen = 1;
-+
-+ if (args[i].value == 0)
-+ {
-+ push_temp_slots ();
-+ args[i].value = expand_expr (args[i].tree_value, NULL_RTX,
-+ VOIDmode, 0);
-+ preserve_temp_slots (args[i].value);
-+ pop_temp_slots ();
-+
-+ /* ANSI doesn't require a sequence point here,
-+ but PCC has one, so this will avoid some problems. */
-+ emit_queue ();
-+ }
-+
-+ /* If the value is a non-legitimate constant, force it into a
-+ pseudo now. TLS symbols sometimes need a call to resolve. */
-+ if (CONSTANT_P (args[i].value)
-+ && !LEGITIMATE_CONSTANT_P (args[i].value))
-+ args[i].value = force_reg (args[i].mode, args[i].value);
-+
-+ /* If we are to promote the function arg to a wider mode,
-+ do it now. */
-+
-+ if (args[i].mode != TYPE_MODE (TREE_TYPE (args[i].tree_value)))
-+ args[i].value
-+ = convert_modes (args[i].mode,
-+ TYPE_MODE (TREE_TYPE (args[i].tree_value)),
-+ args[i].value, args[i].unsignedp);
-+
-+ /* If the value is expensive, and we are inside an appropriately
-+ short loop, put the value into a pseudo and then put the pseudo
-+ into the hard reg.
-+
-+ For small register classes, also do this if this call uses
-+ register parameters. This is to avoid reload conflicts while
-+ loading the parameters registers. */
-+
-+ if ((! (GET_CODE (args[i].value) == REG
-+ || (GET_CODE (args[i].value) == SUBREG
-+ && GET_CODE (SUBREG_REG (args[i].value)) == REG)))
-+ && args[i].mode != BLKmode
-+ && rtx_cost (args[i].value, SET) > COSTS_N_INSNS (1)
-+ && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
-+ || preserve_subexpressions_p ()))
-+ args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
-+ }
-+}
-+
-+#ifdef REG_PARM_STACK_SPACE
-+
-+ /* The argument list is the property of the called routine and it
-+ may clobber it. If the fixed area has been used for previous
-+ parameters, we must save and restore it. */
-+
-+static rtx
-+save_fixed_argument_area (reg_parm_stack_space, argblock,
-+ low_to_save, high_to_save)
-+ int reg_parm_stack_space;
-+ rtx argblock;
-+ int *low_to_save;
-+ int *high_to_save;
-+{
-+ int i;
-+ rtx save_area = NULL_RTX;
-+
-+ /* Compute the boundary of the that needs to be saved, if any. */
-+#ifdef ARGS_GROW_DOWNWARD
-+ for (i = 0; i < reg_parm_stack_space + 1; i++)
-+#else
-+ for (i = 0; i < reg_parm_stack_space; i++)
-+#endif
-+ {
-+ if (i >= highest_outgoing_arg_in_use
-+ || stack_usage_map[i] == 0)
-+ continue;
-+
-+ if (*low_to_save == -1)
-+ *low_to_save = i;
-+
-+ *high_to_save = i;
-+ }
-+
-+ if (*low_to_save >= 0)
-+ {
-+ int num_to_save = *high_to_save - *low_to_save + 1;
-+ enum machine_mode save_mode
-+ = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
-+ rtx stack_area;
-+
-+ /* If we don't have the required alignment, must do this in BLKmode. */
-+ if ((*low_to_save & (MIN (GET_MODE_SIZE (save_mode),
-+ BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
-+ save_mode = BLKmode;
-+
-+#ifdef ARGS_GROW_DOWNWARD
-+ stack_area
-+ = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ plus_constant (argblock,
-+ - *high_to_save)));
-+#else
-+ stack_area = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ plus_constant (argblock,
-+ *low_to_save)));
-+#endif
-+
-+ set_mem_align (stack_area, PARM_BOUNDARY);
-+ if (save_mode == BLKmode)
-+ {
-+ save_area = assign_stack_temp (BLKmode, num_to_save, 0);
-+ emit_block_move (validize_mem (save_area), stack_area,
-+ GEN_INT (num_to_save), BLOCK_OP_CALL_PARM);
-+ }
-+ else
-+ {
-+ save_area = gen_reg_rtx (save_mode);
-+ emit_move_insn (save_area, stack_area);
-+ }
-+ }
-+
-+ return save_area;
-+}
-+
-+static void
-+restore_fixed_argument_area (save_area, argblock, high_to_save, low_to_save)
-+ rtx save_area;
-+ rtx argblock;
-+ int high_to_save;
-+ int low_to_save;
-+{
-+ enum machine_mode save_mode = GET_MODE (save_area);
-+#ifdef ARGS_GROW_DOWNWARD
-+ rtx stack_area
-+ = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ plus_constant (argblock,
-+ - high_to_save)));
-+#else
-+ rtx stack_area
-+ = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ plus_constant (argblock,
-+ low_to_save)));
-+#endif
-+
-+ if (save_mode != BLKmode)
-+ emit_move_insn (stack_area, save_area);
-+ else
-+ emit_block_move (stack_area, validize_mem (save_area),
-+ GEN_INT (high_to_save - low_to_save + 1),
-+ BLOCK_OP_CALL_PARM);
-+}
-+#endif /* REG_PARM_STACK_SPACE */
-+
-+/* If any elements in ARGS refer to parameters that are to be passed in
-+ registers, but not in memory, and whose alignment does not permit a
-+ direct copy into registers. Copy the values into a group of pseudos
-+ which we will later copy into the appropriate hard registers.
-+
-+ Pseudos for each unaligned argument will be stored into the array
-+ args[argnum].aligned_regs. The caller is responsible for deallocating
-+ the aligned_regs array if it is nonzero. */
-+
-+static void
-+store_unaligned_arguments_into_pseudos (args, num_actuals)
-+ struct arg_data *args;
-+ int num_actuals;
-+{
-+ int i, j;
-+
-+ for (i = 0; i < num_actuals; i++)
-+ if (args[i].reg != 0 && ! args[i].pass_on_stack
-+ && args[i].mode == BLKmode
-+ && (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
-+ < (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
-+ {
-+ int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
-+ int big_endian_correction = 0;
-+
-+ args[i].n_aligned_regs
-+ = args[i].partial ? args[i].partial
-+ : (bytes + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
-+
-+ args[i].aligned_regs = (rtx *) xmalloc (sizeof (rtx)
-+ * args[i].n_aligned_regs);
-+
-+ /* Structures smaller than a word are aligned to the least
-+ significant byte (to the right). On a BYTES_BIG_ENDIAN machine,
-+ this means we must skip the empty high order bytes when
-+ calculating the bit offset. */
-+ if (BYTES_BIG_ENDIAN
-+ && bytes < UNITS_PER_WORD)
-+ big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT));
-+
-+ for (j = 0; j < args[i].n_aligned_regs; j++)
-+ {
-+ rtx reg = gen_reg_rtx (word_mode);
-+ rtx word = operand_subword_force (args[i].value, j, BLKmode);
-+ int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD);
-+
-+ args[i].aligned_regs[j] = reg;
-+
-+ /* There is no need to restrict this code to loading items
-+ in TYPE_ALIGN sized hunks. The bitfield instructions can
-+ load up entire word sized registers efficiently.
-+
-+ ??? This may not be needed anymore.
-+ We use to emit a clobber here but that doesn't let later
-+ passes optimize the instructions we emit. By storing 0 into
-+ the register later passes know the first AND to zero out the
-+ bitfield being set in the register is unnecessary. The store
-+ of 0 will be deleted as will at least the first AND. */
-+
-+ emit_move_insn (reg, const0_rtx);
-+
-+ bytes -= bitsize / BITS_PER_UNIT;
-+ store_bit_field (reg, bitsize, big_endian_correction, word_mode,
-+ extract_bit_field (word, bitsize, 0, 1, NULL_RTX,
-+ word_mode, word_mode,
-+ BITS_PER_WORD),
-+ BITS_PER_WORD);
-+ }
-+ }
-+}
-+
-+/* Fill in ARGS_SIZE and ARGS array based on the parameters found in
-+ ACTPARMS.
-+
-+ NUM_ACTUALS is the total number of parameters.
-+
-+ N_NAMED_ARGS is the total number of named arguments.
-+
-+ FNDECL is the tree code for the target of this call (if known)
-+
-+ ARGS_SO_FAR holds state needed by the target to know where to place
-+ the next argument.
-+
-+ REG_PARM_STACK_SPACE is the number of bytes of stack space reserved
-+ for arguments which are passed in registers.
-+
-+ OLD_STACK_LEVEL is a pointer to an rtx which olds the old stack level
-+ and may be modified by this routine.
-+
-+ OLD_PENDING_ADJ, MUST_PREALLOCATE and FLAGS are pointers to integer
-+ flags which may may be modified by this routine. */
-+
-+static void
-+initialize_argument_information (num_actuals, args, args_size, n_named_args,
-+ actparms, fndecl, args_so_far,
-+ reg_parm_stack_space, old_stack_level,
-+ old_pending_adj, must_preallocate,
-+ ecf_flags)
-+ int num_actuals ATTRIBUTE_UNUSED;
-+ struct arg_data *args;
-+ struct args_size *args_size;
-+ int n_named_args ATTRIBUTE_UNUSED;
-+ tree actparms;
-+ tree fndecl;
-+ CUMULATIVE_ARGS *args_so_far;
-+ int reg_parm_stack_space;
-+ rtx *old_stack_level;
-+ int *old_pending_adj;
-+ int *must_preallocate;
-+ int *ecf_flags;
-+{
-+ /* 1 if scanning parms front to back, -1 if scanning back to front. */
-+ int inc;
-+
-+ /* Count arg position in order args appear. */
-+ int argpos;
-+
-+ struct args_size alignment_pad;
-+ int i;
-+ tree p;
-+
-+ args_size->constant = 0;
-+ args_size->var = 0;
-+
-+ /* In this loop, we consider args in the order they are written.
-+ We fill up ARGS from the front or from the back if necessary
-+ so that in any case the first arg to be pushed ends up at the front. */
-+
-+ if (PUSH_ARGS_REVERSED)
-+ {
-+ i = num_actuals - 1, inc = -1;
-+ /* In this case, must reverse order of args
-+ so that we compute and push the last arg first. */
-+ }
-+ else
-+ {
-+ i = 0, inc = 1;
-+ }
-+
-+ /* I counts args in order (to be) pushed; ARGPOS counts in order written. */
-+ for (p = actparms, argpos = 0; p; p = TREE_CHAIN (p), i += inc, argpos++)
-+ {
-+ tree type = TREE_TYPE (TREE_VALUE (p));
-+ int unsignedp;
-+ enum machine_mode mode;
-+
-+ args[i].tree_value = TREE_VALUE (p);
-+
-+ /* Replace erroneous argument with constant zero. */
-+ if (type == error_mark_node || !COMPLETE_TYPE_P (type))
-+ args[i].tree_value = integer_zero_node, type = integer_type_node;
-+
-+ /* If TYPE is a transparent union, pass things the way we would
-+ pass the first field of the union. We have already verified that
-+ the modes are the same. */
-+ if (TREE_CODE (type) == UNION_TYPE && TYPE_TRANSPARENT_UNION (type))
-+ type = TREE_TYPE (TYPE_FIELDS (type));
-+
-+ /* Decide where to pass this arg.
-+
-+ args[i].reg is nonzero if all or part is passed in registers.
-+
-+ args[i].partial is nonzero if part but not all is passed in registers,
-+ and the exact value says how many words are passed in registers.
-+
-+ args[i].pass_on_stack is nonzero if the argument must at least be
-+ computed on the stack. It may then be loaded back into registers
-+ if args[i].reg is nonzero.
-+
-+ These decisions are driven by the FUNCTION_... macros and must agree
-+ with those made by function.c. */
-+
-+ /* See if this argument should be passed by invisible reference. */
-+ if ((TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
-+ && contains_placeholder_p (TYPE_SIZE (type)))
-+ || TREE_ADDRESSABLE (type)
-+#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
-+ || FUNCTION_ARG_PASS_BY_REFERENCE (*args_so_far, TYPE_MODE (type),
-+ type, argpos < n_named_args)
-+#endif
-+ )
-+ {
-+ /* If we're compiling a thunk, pass through invisible
-+ references instead of making a copy. */
-+ if (current_function_is_thunk
-+#ifdef FUNCTION_ARG_CALLEE_COPIES
-+ || (FUNCTION_ARG_CALLEE_COPIES (*args_so_far, TYPE_MODE (type),
-+ type, argpos < n_named_args)
-+ /* If it's in a register, we must make a copy of it too. */
-+ /* ??? Is this a sufficient test? Is there a better one? */
-+ && !(TREE_CODE (args[i].tree_value) == VAR_DECL
-+ && REG_P (DECL_RTL (args[i].tree_value)))
-+ && ! TREE_ADDRESSABLE (type))
-+#endif
-+ )
-+ {
-+ /* C++ uses a TARGET_EXPR to indicate that we want to make a
-+ new object from the argument. If we are passing by
-+ invisible reference, the callee will do that for us, so we
-+ can strip off the TARGET_EXPR. This is not always safe,
-+ but it is safe in the only case where this is a useful
-+ optimization; namely, when the argument is a plain object.
-+ In that case, the frontend is just asking the backend to
-+ make a bitwise copy of the argument. */
-+
-+ if (TREE_CODE (args[i].tree_value) == TARGET_EXPR
-+ && (DECL_P (TREE_OPERAND (args[i].tree_value, 1)))
-+ && ! REG_P (DECL_RTL (TREE_OPERAND (args[i].tree_value, 1))))
-+ args[i].tree_value = TREE_OPERAND (args[i].tree_value, 1);
-+
-+ args[i].tree_value = build1 (ADDR_EXPR,
-+ build_pointer_type (type),
-+ args[i].tree_value);
-+ type = build_pointer_type (type);
-+ }
-+ else if (TREE_CODE (args[i].tree_value) == TARGET_EXPR)
-+ {
-+ /* In the V3 C++ ABI, parameters are destroyed in the caller.
-+ We implement this by passing the address of the temporary
-+ rather than expanding it into another allocated slot. */
-+ args[i].tree_value = build1 (ADDR_EXPR,
-+ build_pointer_type (type),
-+ args[i].tree_value);
-+ type = build_pointer_type (type);
-+ }
-+ else
-+ {
-+ /* We make a copy of the object and pass the address to the
-+ function being called. */
-+ rtx copy;
-+
-+ if (!COMPLETE_TYPE_P (type)
-+ || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
-+ || (flag_stack_check && ! STACK_CHECK_BUILTIN
-+ && (0 < compare_tree_int (TYPE_SIZE_UNIT (type),
-+ STACK_CHECK_MAX_VAR_SIZE))))
-+ {
-+ /* This is a variable-sized object. Make space on the stack
-+ for it. */
-+ rtx size_rtx = expr_size (TREE_VALUE (p));
-+
-+ if (*old_stack_level == 0)
-+ {
-+ emit_stack_save (SAVE_BLOCK, old_stack_level, NULL_RTX);
-+ *old_pending_adj = pending_stack_adjust;
-+ pending_stack_adjust = 0;
-+ }
-+
-+ copy = gen_rtx_MEM (BLKmode,
-+ allocate_dynamic_stack_space
-+ (size_rtx, NULL_RTX, TYPE_ALIGN (type)));
-+ set_mem_attributes (copy, type, 1);
-+ }
-+ else
-+ copy = assign_temp (type, 0, 1, 0);
-+
-+ store_expr (args[i].tree_value, copy, 0);
-+ *ecf_flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
-+
-+ args[i].tree_value = build1 (ADDR_EXPR,
-+ build_pointer_type (type),
-+ make_tree (type, copy));
-+ type = build_pointer_type (type);
-+ }
-+ }
-+
-+ mode = TYPE_MODE (type);
-+ unsignedp = TREE_UNSIGNED (type);
-+
-+#ifdef PROMOTE_FUNCTION_ARGS
-+ mode = promote_mode (type, mode, &unsignedp, 1);
-+#endif
-+
-+ args[i].unsignedp = unsignedp;
-+ args[i].mode = mode;
-+
-+ args[i].reg = FUNCTION_ARG (*args_so_far, mode, type,
-+ argpos < n_named_args);
-+#ifdef FUNCTION_INCOMING_ARG
-+ /* If this is a sibling call and the machine has register windows, the
-+ register window has to be unwinded before calling the routine, so
-+ arguments have to go into the incoming registers. */
-+ args[i].tail_call_reg = FUNCTION_INCOMING_ARG (*args_so_far, mode, type,
-+ argpos < n_named_args);
-+#else
-+ args[i].tail_call_reg = args[i].reg;
-+#endif
-+
-+#ifdef FUNCTION_ARG_PARTIAL_NREGS
-+ if (args[i].reg)
-+ args[i].partial
-+ = FUNCTION_ARG_PARTIAL_NREGS (*args_so_far, mode, type,
-+ argpos < n_named_args);
-+#endif
-+
-+ args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type);
-+
-+ /* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]),
-+ it means that we are to pass this arg in the register(s) designated
-+ by the PARALLEL, but also to pass it in the stack. */
-+ if (args[i].reg && GET_CODE (args[i].reg) == PARALLEL
-+ && XEXP (XVECEXP (args[i].reg, 0, 0), 0) == 0)
-+ args[i].pass_on_stack = 1;
-+
-+ /* If this is an addressable type, we must preallocate the stack
-+ since we must evaluate the object into its final location.
-+
-+ If this is to be passed in both registers and the stack, it is simpler
-+ to preallocate. */
-+ if (TREE_ADDRESSABLE (type)
-+ || (args[i].pass_on_stack && args[i].reg != 0))
-+ *must_preallocate = 1;
-+
-+ /* If this is an addressable type, we cannot pre-evaluate it. Thus,
-+ we cannot consider this function call constant. */
-+ if (TREE_ADDRESSABLE (type))
-+ *ecf_flags &= ~ECF_LIBCALL_BLOCK;
-+
-+ /* Compute the stack-size of this argument. */
-+ if (args[i].reg == 0 || args[i].partial != 0
-+ || reg_parm_stack_space > 0
-+ || args[i].pass_on_stack)
-+ locate_and_pad_parm (mode, type,
-+#ifdef STACK_PARMS_IN_REG_PARM_AREA
-+ 1,
-+#else
-+ args[i].reg != 0,
-+#endif
-+ fndecl, args_size, &args[i].offset,
-+ &args[i].size, &alignment_pad);
-+
-+#ifndef ARGS_GROW_DOWNWARD
-+ args[i].slot_offset = *args_size;
-+#endif
-+
-+ args[i].alignment_pad = alignment_pad;
-+
-+ /* If a part of the arg was put into registers,
-+ don't include that part in the amount pushed. */
-+ if (reg_parm_stack_space == 0 && ! args[i].pass_on_stack)
-+ args[i].size.constant -= ((args[i].partial * UNITS_PER_WORD)
-+ / (PARM_BOUNDARY / BITS_PER_UNIT)
-+ * (PARM_BOUNDARY / BITS_PER_UNIT));
-+
-+ /* Update ARGS_SIZE, the total stack space for args so far. */
-+
-+ args_size->constant += args[i].size.constant;
-+ if (args[i].size.var)
-+ {
-+ ADD_PARM_SIZE (*args_size, args[i].size.var);
-+ }
-+
-+ /* Since the slot offset points to the bottom of the slot,
-+ we must record it after incrementing if the args grow down. */
-+#ifdef ARGS_GROW_DOWNWARD
-+ args[i].slot_offset = *args_size;
-+
-+ args[i].slot_offset.constant = -args_size->constant;
-+ if (args_size->var)
-+ SUB_PARM_SIZE (args[i].slot_offset, args_size->var);
-+#endif
-+
-+ /* Increment ARGS_SO_FAR, which has info about which arg-registers
-+ have been used, etc. */
-+
-+ FUNCTION_ARG_ADVANCE (*args_so_far, TYPE_MODE (type), type,
-+ argpos < n_named_args);
-+ }
-+}
-+
-+/* Update ARGS_SIZE to contain the total size for the argument block.
-+ Return the original constant component of the argument block's size.
-+
-+ REG_PARM_STACK_SPACE holds the number of bytes of stack space reserved
-+ for arguments passed in registers. */
-+
-+static int
-+compute_argument_block_size (reg_parm_stack_space, args_size,
-+ preferred_stack_boundary)
-+ int reg_parm_stack_space;
-+ struct args_size *args_size;
-+ int preferred_stack_boundary ATTRIBUTE_UNUSED;
-+{
-+ int unadjusted_args_size = args_size->constant;
-+
-+ /* For accumulate outgoing args mode we don't need to align, since the frame
-+ will be already aligned. Align to STACK_BOUNDARY in order to prevent
-+ backends from generating misaligned frame sizes. */
-+ if (ACCUMULATE_OUTGOING_ARGS && preferred_stack_boundary > STACK_BOUNDARY)
-+ preferred_stack_boundary = STACK_BOUNDARY;
-+
-+ /* Compute the actual size of the argument block required. The variable
-+ and constant sizes must be combined, the size may have to be rounded,
-+ and there may be a minimum required size. */
-+
-+ if (args_size->var)
-+ {
-+ args_size->var = ARGS_SIZE_TREE (*args_size);
-+ args_size->constant = 0;
-+
-+ preferred_stack_boundary /= BITS_PER_UNIT;
-+ if (preferred_stack_boundary > 1)
-+ {
-+ /* We don't handle this case yet. To handle it correctly we have
-+ to add the delta, round and subtract the delta.
-+ Currently no machine description requires this support. */
-+ if (stack_pointer_delta & (preferred_stack_boundary - 1))
-+ abort ();
-+ args_size->var = round_up (args_size->var, preferred_stack_boundary);
-+ }
-+
-+ if (reg_parm_stack_space > 0)
-+ {
-+ args_size->var
-+ = size_binop (MAX_EXPR, args_size->var,
-+ ssize_int (reg_parm_stack_space));
-+
-+#ifndef OUTGOING_REG_PARM_STACK_SPACE
-+ /* The area corresponding to register parameters is not to count in
-+ the size of the block we need. So make the adjustment. */
-+ args_size->var
-+ = size_binop (MINUS_EXPR, args_size->var,
-+ ssize_int (reg_parm_stack_space));
-+#endif
-+ }
-+ }
-+ else
-+ {
-+ preferred_stack_boundary /= BITS_PER_UNIT;
-+ if (preferred_stack_boundary < 1)
-+ preferred_stack_boundary = 1;
-+ args_size->constant = (((args_size->constant
-+ + stack_pointer_delta
-+ + preferred_stack_boundary - 1)
-+ / preferred_stack_boundary
-+ * preferred_stack_boundary)
-+ - stack_pointer_delta);
-+
-+ args_size->constant = MAX (args_size->constant,
-+ reg_parm_stack_space);
-+
-+#ifdef MAYBE_REG_PARM_STACK_SPACE
-+ if (reg_parm_stack_space == 0)
-+ args_size->constant = 0;
-+#endif
-+
-+#ifndef OUTGOING_REG_PARM_STACK_SPACE
-+ args_size->constant -= reg_parm_stack_space;
-+#endif
-+ }
-+ return unadjusted_args_size;
-+}
-+
-+/* Precompute parameters as needed for a function call.
-+
-+ FLAGS is mask of ECF_* constants.
-+
-+ NUM_ACTUALS is the number of arguments.
-+
-+ ARGS is an array containing information for each argument; this
-+ routine fills in the INITIAL_VALUE and VALUE fields for each
-+ precomputed argument. */
-+
-+static void
-+precompute_arguments (flags, num_actuals, args)
-+ int flags;
-+ int num_actuals;
-+ struct arg_data *args;
-+{
-+ int i;
-+
-+ /* If this function call is cse'able, precompute all the parameters.
-+ Note that if the parameter is constructed into a temporary, this will
-+ cause an additional copy because the parameter will be constructed
-+ into a temporary location and then copied into the outgoing arguments.
-+ If a parameter contains a call to alloca and this function uses the
-+ stack, precompute the parameter. */
-+
-+ /* If we preallocated the stack space, and some arguments must be passed
-+ on the stack, then we must precompute any parameter which contains a
-+ function call which will store arguments on the stack.
-+ Otherwise, evaluating the parameter may clobber previous parameters
-+ which have already been stored into the stack. (we have code to avoid
-+ such case by saving the outgoing stack arguments, but it results in
-+ worse code) */
-+
-+ for (i = 0; i < num_actuals; i++)
-+ if ((flags & ECF_LIBCALL_BLOCK)
-+ || calls_function (args[i].tree_value, !ACCUMULATE_OUTGOING_ARGS))
-+ {
-+ enum machine_mode mode;
-+
-+ /* If this is an addressable type, we cannot pre-evaluate it. */
-+ if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
-+ abort ();
-+
-+ args[i].value
-+ = expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0);
-+
-+ /* ANSI doesn't require a sequence point here,
-+ but PCC has one, so this will avoid some problems. */
-+ emit_queue ();
-+
-+ args[i].initial_value = args[i].value
-+ = protect_from_queue (args[i].value, 0);
-+
-+ mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
-+ if (mode != args[i].mode)
-+ {
-+ args[i].value
-+ = convert_modes (args[i].mode, mode,
-+ args[i].value, args[i].unsignedp);
-+#ifdef PROMOTE_FOR_CALL_ONLY
-+ /* CSE will replace this only if it contains args[i].value
-+ pseudo, so convert it down to the declared mode using
-+ a SUBREG. */
-+ if (GET_CODE (args[i].value) == REG
-+ && GET_MODE_CLASS (args[i].mode) == MODE_INT)
-+ {
-+ args[i].initial_value
-+ = gen_lowpart_SUBREG (mode, args[i].value);
-+ SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
-+ SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value,
-+ args[i].unsignedp);
-+ }
-+#endif
-+ }
-+ }
-+}
-+
-+/* Given the current state of MUST_PREALLOCATE and information about
-+ arguments to a function call in NUM_ACTUALS, ARGS and ARGS_SIZE,
-+ compute and return the final value for MUST_PREALLOCATE. */
-+
-+static int
-+finalize_must_preallocate (must_preallocate, num_actuals, args, args_size)
-+ int must_preallocate;
-+ int num_actuals;
-+ struct arg_data *args;
-+ struct args_size *args_size;
-+{
-+ /* See if we have or want to preallocate stack space.
-+
-+ If we would have to push a partially-in-regs parm
-+ before other stack parms, preallocate stack space instead.
-+
-+ If the size of some parm is not a multiple of the required stack
-+ alignment, we must preallocate.
-+
-+ If the total size of arguments that would otherwise create a copy in
-+ a temporary (such as a CALL) is more than half the total argument list
-+ size, preallocation is faster.
-+
-+ Another reason to preallocate is if we have a machine (like the m88k)
-+ where stack alignment is required to be maintained between every
-+ pair of insns, not just when the call is made. However, we assume here
-+ that such machines either do not have push insns (and hence preallocation
-+ would occur anyway) or the problem is taken care of with
-+ PUSH_ROUNDING. */
-+
-+ if (! must_preallocate)
-+ {
-+ int partial_seen = 0;
-+ int copy_to_evaluate_size = 0;
-+ int i;
-+
-+ for (i = 0; i < num_actuals && ! must_preallocate; i++)
-+ {
-+ if (args[i].partial > 0 && ! args[i].pass_on_stack)
-+ partial_seen = 1;
-+ else if (partial_seen && args[i].reg == 0)
-+ must_preallocate = 1;
-+
-+ if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
-+ && (TREE_CODE (args[i].tree_value) == CALL_EXPR
-+ || TREE_CODE (args[i].tree_value) == TARGET_EXPR
-+ || TREE_CODE (args[i].tree_value) == COND_EXPR
-+ || TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value))))
-+ copy_to_evaluate_size
-+ += int_size_in_bytes (TREE_TYPE (args[i].tree_value));
-+ }
-+
-+ if (copy_to_evaluate_size * 2 >= args_size->constant
-+ && args_size->constant > 0)
-+ must_preallocate = 1;
-+ }
-+ return must_preallocate;
-+}
-+
-+/* If we preallocated stack space, compute the address of each argument
-+ and store it into the ARGS array.
-+
-+ We need not ensure it is a valid memory address here; it will be
-+ validized when it is used.
-+
-+ ARGBLOCK is an rtx for the address of the outgoing arguments. */
-+
-+static void
-+compute_argument_addresses (args, argblock, num_actuals)
-+ struct arg_data *args;
-+ rtx argblock;
-+ int num_actuals;
-+{
-+ if (argblock)
-+ {
-+ rtx arg_reg = argblock;
-+ int i, arg_offset = 0;
-+
-+ if (GET_CODE (argblock) == PLUS)
-+ arg_reg = XEXP (argblock, 0), arg_offset = INTVAL (XEXP (argblock, 1));
-+
-+ for (i = 0; i < num_actuals; i++)
-+ {
-+ rtx offset = ARGS_SIZE_RTX (args[i].offset);
-+ rtx slot_offset = ARGS_SIZE_RTX (args[i].slot_offset);
-+ rtx addr;
-+
-+ /* Skip this parm if it will not be passed on the stack. */
-+ if (! args[i].pass_on_stack && args[i].reg != 0)
-+ continue;
-+
-+ if (GET_CODE (offset) == CONST_INT)
-+ addr = plus_constant (arg_reg, INTVAL (offset));
-+ else
-+ addr = gen_rtx_PLUS (Pmode, arg_reg, offset);
-+
-+ addr = plus_constant (addr, arg_offset);
-+ args[i].stack = gen_rtx_MEM (args[i].mode, addr);
-+ set_mem_align (args[i].stack, PARM_BOUNDARY);
-+ set_mem_attributes (args[i].stack,
-+ TREE_TYPE (args[i].tree_value), 1);
-+
-+ if (GET_CODE (slot_offset) == CONST_INT)
-+ addr = plus_constant (arg_reg, INTVAL (slot_offset));
-+ else
-+ addr = gen_rtx_PLUS (Pmode, arg_reg, slot_offset);
-+
-+ addr = plus_constant (addr, arg_offset);
-+ args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
-+ set_mem_align (args[i].stack_slot, PARM_BOUNDARY);
-+ set_mem_attributes (args[i].stack_slot,
-+ TREE_TYPE (args[i].tree_value), 1);
-+
-+ /* Function incoming arguments may overlap with sibling call
-+ outgoing arguments and we cannot allow reordering of reads
-+ from function arguments with stores to outgoing arguments
-+ of sibling calls. */
-+ set_mem_alias_set (args[i].stack, 0);
-+ set_mem_alias_set (args[i].stack_slot, 0);
-+ }
-+ }
-+}
-+
-+/* Given a FNDECL and EXP, return an rtx suitable for use as a target address
-+ in a call instruction.
-+
-+ FNDECL is the tree node for the target function. For an indirect call
-+ FNDECL will be NULL_TREE.
-+
-+ ADDR is the operand 0 of CALL_EXPR for this call. */
-+
-+static rtx
-+rtx_for_function_call (fndecl, addr)
-+ tree fndecl;
-+ tree addr;
-+{
-+ rtx funexp;
-+
-+ /* Get the function to call, in the form of RTL. */
-+ if (fndecl)
-+ {
-+ /* If this is the first use of the function, see if we need to
-+ make an external definition for it. */
-+ if (! TREE_USED (fndecl))
-+ {
-+ assemble_external (fndecl);
-+ TREE_USED (fndecl) = 1;
-+ }
-+
-+ /* Get a SYMBOL_REF rtx for the function address. */
-+ funexp = XEXP (DECL_RTL (fndecl), 0);
-+ }
-+ else
-+ /* Generate an rtx (probably a pseudo-register) for the address. */
-+ {
-+ rtx funaddr;
-+ push_temp_slots ();
-+ funaddr = funexp
-+ = expand_expr (addr, NULL_RTX, VOIDmode, 0);
-+ pop_temp_slots (); /* FUNEXP can't be BLKmode. */
-+ emit_queue ();
-+ }
-+ return funexp;
-+}
-+
-+/* Do the register loads required for any wholly-register parms or any
-+ parms which are passed both on the stack and in a register. Their
-+ expressions were already evaluated.
-+
-+ Mark all register-parms as living through the call, putting these USE
-+ insns in the CALL_INSN_FUNCTION_USAGE field. */
-+
-+static void
-+load_register_parameters (args, num_actuals, call_fusage, flags)
-+ struct arg_data *args;
-+ int num_actuals;
-+ rtx *call_fusage;
-+ int flags;
-+{
-+ int i, j;
-+
-+#ifdef LOAD_ARGS_REVERSED
-+ for (i = num_actuals - 1; i >= 0; i--)
-+#else
-+ for (i = 0; i < num_actuals; i++)
-+#endif
-+ {
-+ rtx reg = ((flags & ECF_SIBCALL)
-+ ? args[i].tail_call_reg : args[i].reg);
-+ int partial = args[i].partial;
-+ int nregs;
-+
-+ if (reg)
-+ {
-+ /* Set to non-negative if must move a word at a time, even if just
-+ one word (e.g, partial == 1 && mode == DFmode). Set to -1 if
-+ we just use a normal move insn. This value can be zero if the
-+ argument is a zero size structure with no fields. */
-+ nregs = (partial ? partial
-+ : (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
-+ ? ((int_size_in_bytes (TREE_TYPE (args[i].tree_value))
-+ + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
-+ : -1));
-+
-+ /* Handle calls that pass values in multiple non-contiguous
-+ locations. The Irix 6 ABI has examples of this. */
-+
-+ if (GET_CODE (reg) == PARALLEL)
-+ emit_group_load (reg, args[i].value,
-+ int_size_in_bytes (TREE_TYPE (args[i].tree_value)));
-+
-+ /* If simple case, just do move. If normal partial, store_one_arg
-+ has already loaded the register for us. In all other cases,
-+ load the register(s) from memory. */
-+
-+ else if (nregs == -1)
-+ emit_move_insn (reg, args[i].value);
-+
-+ /* If we have pre-computed the values to put in the registers in
-+ the case of non-aligned structures, copy them in now. */
-+
-+ else if (args[i].n_aligned_regs != 0)
-+ for (j = 0; j < args[i].n_aligned_regs; j++)
-+ emit_move_insn (gen_rtx_REG (word_mode, REGNO (reg) + j),
-+ args[i].aligned_regs[j]);
-+
-+ else if (partial == 0 || args[i].pass_on_stack)
-+ move_block_to_reg (REGNO (reg),
-+ validize_mem (args[i].value), nregs,
-+ args[i].mode);
-+
-+ /* Handle calls that pass values in multiple non-contiguous
-+ locations. The Irix 6 ABI has examples of this. */
-+ if (GET_CODE (reg) == PARALLEL)
-+ use_group_regs (call_fusage, reg);
-+ else if (nregs == -1)
-+ use_reg (call_fusage, reg);
-+ else
-+ use_regs (call_fusage, REGNO (reg), nregs == 0 ? 1 : nregs);
-+ }
-+ }
-+}
-+
-+/* Try to integrate function. See expand_inline_function for documentation
-+ about the parameters. */
-+
-+static rtx
-+try_to_integrate (fndecl, actparms, target, ignore, type, structure_value_addr)
-+ tree fndecl;
-+ tree actparms;
-+ rtx target;
-+ int ignore;
-+ tree type;
-+ rtx structure_value_addr;
-+{
-+ rtx temp;
-+ rtx before_call;
-+ int i;
-+ rtx old_stack_level = 0;
-+ int reg_parm_stack_space = 0;
-+
-+#ifdef REG_PARM_STACK_SPACE
-+#ifdef MAYBE_REG_PARM_STACK_SPACE
-+ reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
-+#else
-+ reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
-+#endif
-+#endif
-+
-+ before_call = get_last_insn ();
-+
-+ timevar_push (TV_INTEGRATION);
-+
-+ temp = expand_inline_function (fndecl, actparms, target,
-+ ignore, type,
-+ structure_value_addr);
-+
-+ timevar_pop (TV_INTEGRATION);
-+
-+ /* If inlining succeeded, return. */
-+ if (temp != (rtx) (size_t) - 1)
-+ {
-+ if (ACCUMULATE_OUTGOING_ARGS)
-+ {
-+ /* If the outgoing argument list must be preserved, push
-+ the stack before executing the inlined function if it
-+ makes any calls. */
-+
-+ for (i = reg_parm_stack_space - 1; i >= 0; i--)
-+ if (i < highest_outgoing_arg_in_use && stack_usage_map[i] != 0)
-+ break;
-+
-+ if (stack_arg_under_construction || i >= 0)
-+ {
-+ rtx first_insn
-+ = before_call ? NEXT_INSN (before_call) : get_insns ();
-+ rtx insn = NULL_RTX, seq;
-+
-+ /* Look for a call in the inline function code.
-+ If DECL_SAVED_INSNS (fndecl)->outgoing_args_size is
-+ nonzero then there is a call and it is not necessary
-+ to scan the insns. */
-+
-+ if (DECL_SAVED_INSNS (fndecl)->outgoing_args_size == 0)
-+ for (insn = first_insn; insn; insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) == CALL_INSN)
-+ break;
-+
-+ if (insn)
-+ {
-+ /* Reserve enough stack space so that the largest
-+ argument list of any function call in the inline
-+ function does not overlap the argument list being
-+ evaluated. This is usually an overestimate because
-+ allocate_dynamic_stack_space reserves space for an
-+ outgoing argument list in addition to the requested
-+ space, but there is no way to ask for stack space such
-+ that an argument list of a certain length can be
-+ safely constructed.
-+
-+ Add the stack space reserved for register arguments, if
-+ any, in the inline function. What is really needed is the
-+ largest value of reg_parm_stack_space in the inline
-+ function, but that is not available. Using the current
-+ value of reg_parm_stack_space is wrong, but gives
-+ correct results on all supported machines. */
-+
-+ int adjust = (DECL_SAVED_INSNS (fndecl)->outgoing_args_size
-+ + reg_parm_stack_space);
-+
-+ start_sequence ();
-+ emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
-+ allocate_dynamic_stack_space (GEN_INT (adjust),
-+ NULL_RTX, BITS_PER_UNIT);
-+ seq = get_insns ();
-+ end_sequence ();
-+ emit_insn_before (seq, first_insn);
-+ emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
-+ }
-+ }
-+ }
-+
-+ /* If the result is equivalent to TARGET, return TARGET to simplify
-+ checks in store_expr. They can be equivalent but not equal in the
-+ case of a function that returns BLKmode. */
-+ if (temp != target && rtx_equal_p (temp, target))
-+ return target;
-+ return temp;
-+ }
-+
-+ /* If inlining failed, mark FNDECL as needing to be compiled
-+ separately after all. If function was declared inline,
-+ give a warning. */
-+ if (DECL_INLINE (fndecl) && warn_inline && !flag_no_inline
-+ && optimize > 0 && !TREE_ADDRESSABLE (fndecl))
-+ {
-+ warning_with_decl (fndecl, "inlining failed in call to `%s'");
-+ warning ("called from here");
-+ }
-+ (*lang_hooks.mark_addressable) (fndecl);
-+ return (rtx) (size_t) - 1;
-+}
-+
-+/* We need to pop PENDING_STACK_ADJUST bytes. But, if the arguments
-+ wouldn't fill up an even multiple of PREFERRED_UNIT_STACK_BOUNDARY
-+ bytes, then we would need to push some additional bytes to pad the
-+ arguments. So, we compute an adjust to the stack pointer for an
-+ amount that will leave the stack under-aligned by UNADJUSTED_ARGS_SIZE
-+ bytes. Then, when the arguments are pushed the stack will be perfectly
-+ aligned. ARGS_SIZE->CONSTANT is set to the number of bytes that should
-+ be popped after the call. Returns the adjustment. */
-+
-+static int
-+combine_pending_stack_adjustment_and_call (unadjusted_args_size,
-+ args_size,
-+ preferred_unit_stack_boundary)
-+ int unadjusted_args_size;
-+ struct args_size *args_size;
-+ int preferred_unit_stack_boundary;
-+{
-+ /* The number of bytes to pop so that the stack will be
-+ under-aligned by UNADJUSTED_ARGS_SIZE bytes. */
-+ HOST_WIDE_INT adjustment;
-+ /* The alignment of the stack after the arguments are pushed, if we
-+ just pushed the arguments without adjust the stack here. */
-+ HOST_WIDE_INT unadjusted_alignment;
-+
-+ unadjusted_alignment
-+ = ((stack_pointer_delta + unadjusted_args_size)
-+ % preferred_unit_stack_boundary);
-+
-+ /* We want to get rid of as many of the PENDING_STACK_ADJUST bytes
-+ as possible -- leaving just enough left to cancel out the
-+ UNADJUSTED_ALIGNMENT. In other words, we want to ensure that the
-+ PENDING_STACK_ADJUST is non-negative, and congruent to
-+ -UNADJUSTED_ALIGNMENT modulo the PREFERRED_UNIT_STACK_BOUNDARY. */
-+
-+ /* Begin by trying to pop all the bytes. */
-+ unadjusted_alignment
-+ = (unadjusted_alignment
-+ - (pending_stack_adjust % preferred_unit_stack_boundary));
-+ adjustment = pending_stack_adjust;
-+ /* Push enough additional bytes that the stack will be aligned
-+ after the arguments are pushed. */
-+ if (preferred_unit_stack_boundary > 1)
-+ {
-+ if (unadjusted_alignment > 0)
-+ adjustment -= preferred_unit_stack_boundary - unadjusted_alignment;
-+ else
-+ adjustment += unadjusted_alignment;
-+ }
-+
-+ /* Now, sets ARGS_SIZE->CONSTANT so that we pop the right number of
-+ bytes after the call. The right number is the entire
-+ PENDING_STACK_ADJUST less our ADJUSTMENT plus the amount required
-+ by the arguments in the first place. */
-+ args_size->constant
-+ = pending_stack_adjust - adjustment + unadjusted_args_size;
-+
-+ return adjustment;
-+}
-+
-+/* Scan X expression if it does not dereference any argument slots
-+ we already clobbered by tail call arguments (as noted in stored_args_map
-+ bitmap).
-+ Return nonzero if X expression dereferences such argument slots,
-+ zero otherwise. */
-+
-+static int
-+check_sibcall_argument_overlap_1 (x)
-+ rtx x;
-+{
-+ RTX_CODE code;
-+ int i, j;
-+ unsigned int k;
-+ const char *fmt;
-+
-+ if (x == NULL_RTX)
-+ return 0;
-+
-+ code = GET_CODE (x);
-+
-+ if (code == MEM)
-+ {
-+ if (XEXP (x, 0) == current_function_internal_arg_pointer)
-+ i = 0;
-+ else if (GET_CODE (XEXP (x, 0)) == PLUS
-+ && XEXP (XEXP (x, 0), 0) ==
-+ current_function_internal_arg_pointer
-+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
-+ i = INTVAL (XEXP (XEXP (x, 0), 1));
-+ else
-+ return 0;
-+
-+#ifdef ARGS_GROW_DOWNWARD
-+ i = -i - GET_MODE_SIZE (GET_MODE (x));
-+#endif
-+
-+ for (k = 0; k < GET_MODE_SIZE (GET_MODE (x)); k++)
-+ if (i + k < stored_args_map->n_bits
-+ && TEST_BIT (stored_args_map, i + k))
-+ return 1;
-+
-+ return 0;
-+ }
-+
-+ /* Scan all subexpressions. */
-+ fmt = GET_RTX_FORMAT (code);
-+ for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
-+ {
-+ if (*fmt == 'e')
-+ {
-+ if (check_sibcall_argument_overlap_1 (XEXP (x, i)))
-+ return 1;
-+ }
-+ else if (*fmt == 'E')
-+ {
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ if (check_sibcall_argument_overlap_1 (XVECEXP (x, i, j)))
-+ return 1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/* Scan sequence after INSN if it does not dereference any argument slots
-+ we already clobbered by tail call arguments (as noted in stored_args_map
-+ bitmap). Add stack slots for ARG to stored_args_map bitmap afterwards.
-+ Return nonzero if sequence after INSN dereferences such argument slots,
-+ zero otherwise. */
-+
-+static int
-+check_sibcall_argument_overlap (insn, arg)
-+ rtx insn;
-+ struct arg_data *arg;
-+{
-+ int low, high;
-+
-+ if (insn == NULL_RTX)
-+ insn = get_insns ();
-+ else
-+ insn = NEXT_INSN (insn);
-+
-+ for (; insn; insn = NEXT_INSN (insn))
-+ if (INSN_P (insn)
-+ && check_sibcall_argument_overlap_1 (PATTERN (insn)))
-+ break;
-+
-+#ifdef ARGS_GROW_DOWNWARD
-+ low = -arg->slot_offset.constant - arg->size.constant;
-+#else
-+ low = arg->slot_offset.constant;
-+#endif
-+
-+ for (high = low + arg->size.constant; low < high; low++)
-+ SET_BIT (stored_args_map, low);
-+ return insn != NULL_RTX;
-+}
-+
-+static tree
-+fix_unsafe_tree (t)
-+ tree t;
-+{
-+ switch (unsafe_for_reeval (t))
-+ {
-+ case 0: /* Safe. */
-+ break;
-+
-+ case 1: /* Mildly unsafe. */
-+ t = unsave_expr (t);
-+ break;
-+
-+ case 2: /* Wildly unsafe. */
-+ {
-+ tree var = build_decl (VAR_DECL, NULL_TREE,
-+ TREE_TYPE (t));
-+ SET_DECL_RTL (var,
-+ expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL));
-+ t = var;
-+ }
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+ return t;
-+}
-+
-+/* Generate all the code for a function call
-+ and return an rtx for its value.
-+ Store the value in TARGET (specified as an rtx) if convenient.
-+ If the value is stored in TARGET then TARGET is returned.
-+ If IGNORE is nonzero, then we ignore the value of the function call. */
-+
-+rtx
-+expand_call (exp, target, ignore)
-+ tree exp;
-+ rtx target;
-+ int ignore;
-+{
-+ /* Nonzero if we are currently expanding a call. */
-+ static int currently_expanding_call = 0;
-+
-+ /* List of actual parameters. */
-+ tree actparms = TREE_OPERAND (exp, 1);
-+ /* RTX for the function to be called. */
-+ rtx funexp;
-+ /* Sequence of insns to perform a tail recursive "call". */
-+ rtx tail_recursion_insns = NULL_RTX;
-+ /* Sequence of insns to perform a normal "call". */
-+ rtx normal_call_insns = NULL_RTX;
-+ /* Sequence of insns to perform a tail recursive "call". */
-+ rtx tail_call_insns = NULL_RTX;
-+ /* Data type of the function. */
-+ tree funtype;
-+ /* Declaration of the function being called,
-+ or 0 if the function is computed (not known by name). */
-+ tree fndecl = 0;
-+ rtx insn;
-+ int try_tail_call = 1;
-+ int try_tail_recursion = 1;
-+ int pass;
-+
-+ /* Register in which non-BLKmode value will be returned,
-+ or 0 if no value or if value is BLKmode. */
-+ rtx valreg;
-+ /* Address where we should return a BLKmode value;
-+ 0 if value not BLKmode. */
-+ rtx structure_value_addr = 0;
-+ /* Nonzero if that address is being passed by treating it as
-+ an extra, implicit first parameter. Otherwise,
-+ it is passed by being copied directly into struct_value_rtx. */
-+ int structure_value_addr_parm = 0;
-+ /* Size of aggregate value wanted, or zero if none wanted
-+ or if we are using the non-reentrant PCC calling convention
-+ or expecting the value in registers. */
-+ HOST_WIDE_INT struct_value_size = 0;
-+ /* Nonzero if called function returns an aggregate in memory PCC style,
-+ by returning the address of where to find it. */
-+ int pcc_struct_value = 0;
-+
-+ /* Number of actual parameters in this call, including struct value addr. */
-+ int num_actuals;
-+ /* Number of named args. Args after this are anonymous ones
-+ and they must all go on the stack. */
-+ int n_named_args;
-+
-+ /* Vector of information about each argument.
-+ Arguments are numbered in the order they will be pushed,
-+ not the order they are written. */
-+ struct arg_data *args;
-+
-+ /* Total size in bytes of all the stack-parms scanned so far. */
-+ struct args_size args_size;
-+ struct args_size adjusted_args_size;
-+ /* Size of arguments before any adjustments (such as rounding). */
-+ int unadjusted_args_size;
-+ /* Data on reg parms scanned so far. */
-+ CUMULATIVE_ARGS args_so_far;
-+ /* Nonzero if a reg parm has been scanned. */
-+ int reg_parm_seen;
-+ /* Nonzero if this is an indirect function call. */
-+
-+ /* Nonzero if we must avoid push-insns in the args for this call.
-+ If stack space is allocated for register parameters, but not by the
-+ caller, then it is preallocated in the fixed part of the stack frame.
-+ So the entire argument block must then be preallocated (i.e., we
-+ ignore PUSH_ROUNDING in that case). */
-+
-+ int must_preallocate = !PUSH_ARGS;
-+
-+ /* Size of the stack reserved for parameter registers. */
-+ int reg_parm_stack_space = 0;
-+
-+ /* Address of space preallocated for stack parms
-+ (on machines that lack push insns), or 0 if space not preallocated. */
-+ rtx argblock = 0;
-+
-+ /* Mask of ECF_ flags. */
-+ int flags = 0;
-+ /* Nonzero if this is a call to an inline function. */
-+ int is_integrable = 0;
-+#ifdef REG_PARM_STACK_SPACE
-+ /* Define the boundary of the register parm stack space that needs to be
-+ save, if any. */
-+ int low_to_save = -1, high_to_save;
-+ rtx save_area = 0; /* Place that it is saved */
-+#endif
-+
-+ int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
-+ char *initial_stack_usage_map = stack_usage_map;
-+ int old_stack_arg_under_construction = 0;
-+
-+ rtx old_stack_level = 0;
-+ int old_pending_adj = 0;
-+ int old_inhibit_defer_pop = inhibit_defer_pop;
-+ int old_stack_allocated;
-+ rtx call_fusage;
-+ tree p = TREE_OPERAND (exp, 0);
-+ tree addr = TREE_OPERAND (exp, 0);
-+ int i;
-+ /* The alignment of the stack, in bits. */
-+ HOST_WIDE_INT preferred_stack_boundary;
-+ /* The alignment of the stack, in bytes. */
-+ HOST_WIDE_INT preferred_unit_stack_boundary;
-+
-+ /* See if this is "nothrow" function call. */
-+ if (TREE_NOTHROW (exp))
-+ flags |= ECF_NOTHROW;
-+
-+ /* See if we can find a DECL-node for the actual function.
-+ As a result, decide whether this is a call to an integrable function. */
-+
-+ fndecl = get_callee_fndecl (exp);
-+ if (fndecl)
-+ {
-+ if (!flag_no_inline
-+ && fndecl != current_function_decl
-+ && DECL_INLINE (fndecl)
-+ && DECL_SAVED_INSNS (fndecl)
-+ && DECL_SAVED_INSNS (fndecl)->inlinable)
-+ is_integrable = 1;
-+ else if (! TREE_ADDRESSABLE (fndecl))
-+ {
-+ /* In case this function later becomes inlinable,
-+ record that there was already a non-inline call to it.
-+
-+ Use abstraction instead of setting TREE_ADDRESSABLE
-+ directly. */
-+ if (DECL_INLINE (fndecl) && warn_inline && !flag_no_inline
-+ && optimize > 0)
-+ {
-+ warning_with_decl (fndecl, "can't inline call to `%s'");
-+ warning ("called from here");
-+ }
-+ (*lang_hooks.mark_addressable) (fndecl);
-+ }
-+
-+ flags |= flags_from_decl_or_type (fndecl);
-+ }
-+
-+ /* If we don't have specific function to call, see if we have a
-+ attributes set in the type. */
-+ else
-+ flags |= flags_from_decl_or_type (TREE_TYPE (TREE_TYPE (p)));
-+
-+#ifdef REG_PARM_STACK_SPACE
-+#ifdef MAYBE_REG_PARM_STACK_SPACE
-+ reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
-+#else
-+ reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
-+#endif
-+#endif
-+
-+#ifndef OUTGOING_REG_PARM_STACK_SPACE
-+ if (reg_parm_stack_space > 0 && PUSH_ARGS)
-+ must_preallocate = 1;
-+#endif
-+
-+ /* Warn if this value is an aggregate type,
-+ regardless of which calling convention we are using for it. */
-+ if (warn_aggregate_return && AGGREGATE_TYPE_P (TREE_TYPE (exp)))
-+ warning ("function call has aggregate value");
-+
-+ /* Set up a place to return a structure. */
-+
-+ /* Cater to broken compilers. */
-+ if (aggregate_value_p (exp))
-+ {
-+ /* This call returns a big structure. */
-+ flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
-+
-+#ifdef PCC_STATIC_STRUCT_RETURN
-+ {
-+ pcc_struct_value = 1;
-+ /* Easier than making that case work right. */
-+ if (is_integrable)
-+ {
-+ /* In case this is a static function, note that it has been
-+ used. */
-+ if (! TREE_ADDRESSABLE (fndecl))
-+ (*lang_hooks.mark_addressable) (fndecl);
-+ is_integrable = 0;
-+ }
-+ }
-+#else /* not PCC_STATIC_STRUCT_RETURN */
-+ {
-+ struct_value_size = int_size_in_bytes (TREE_TYPE (exp));
-+
-+ if (target && GET_CODE (target) == MEM)
-+ structure_value_addr = XEXP (target, 0);
-+ else
-+ {
-+ /* For variable-sized objects, we must be called with a target
-+ specified. If we were to allocate space on the stack here,
-+ we would have no way of knowing when to free it. */
-+ rtx d = assign_temp (TREE_TYPE (exp), 1, 1, 1);
-+
-+ mark_temp_addr_taken (d);
-+ structure_value_addr = XEXP (d, 0);
-+ target = 0;
-+ }
-+ }
-+#endif /* not PCC_STATIC_STRUCT_RETURN */
-+ }
-+
-+ /* If called function is inline, try to integrate it. */
-+
-+ if (is_integrable)
-+ {
-+ rtx temp = try_to_integrate (fndecl, actparms, target,
-+ ignore, TREE_TYPE (exp),
-+ structure_value_addr);
-+ if (temp != (rtx) (size_t) - 1)
-+ return temp;
-+ }
-+
-+ /* Figure out the amount to which the stack should be aligned. */
-+ preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
-+
-+ /* Operand 0 is a pointer-to-function; get the type of the function. */
-+ funtype = TREE_TYPE (addr);
-+ if (! POINTER_TYPE_P (funtype))
-+ abort ();
-+ funtype = TREE_TYPE (funtype);
-+
-+ /* See if this is a call to a function that can return more than once
-+ or a call to longjmp or malloc. */
-+ flags |= special_function_p (fndecl, flags);
-+
-+ if (flags & ECF_MAY_BE_ALLOCA)
-+ current_function_calls_alloca = 1;
-+
-+ /* If struct_value_rtx is 0, it means pass the address
-+ as if it were an extra parameter. */
-+ if (structure_value_addr && struct_value_rtx == 0)
-+ {
-+ /* If structure_value_addr is a REG other than
-+ virtual_outgoing_args_rtx, we can use always use it. If it
-+ is not a REG, we must always copy it into a register.
-+ If it is virtual_outgoing_args_rtx, we must copy it to another
-+ register in some cases. */
-+ rtx temp = (GET_CODE (structure_value_addr) != REG
-+ || (ACCUMULATE_OUTGOING_ARGS
-+ && stack_arg_under_construction
-+ && structure_value_addr == virtual_outgoing_args_rtx)
-+ ? copy_addr_to_reg (structure_value_addr)
-+ : structure_value_addr);
-+
-+ actparms
-+ = tree_cons (error_mark_node,
-+ make_tree (build_pointer_type (TREE_TYPE (funtype)),
-+ temp),
-+ actparms);
-+ structure_value_addr_parm = 1;
-+ }
-+
-+ /* Count the arguments and set NUM_ACTUALS. */
-+ for (p = actparms, num_actuals = 0; p; p = TREE_CHAIN (p))
-+ num_actuals++;
-+
-+ /* Compute number of named args.
-+ Normally, don't include the last named arg if anonymous args follow.
-+ We do include the last named arg if STRICT_ARGUMENT_NAMING is nonzero.
-+ (If no anonymous args follow, the result of list_length is actually
-+ one too large. This is harmless.)
-+
-+ If PRETEND_OUTGOING_VARARGS_NAMED is set and STRICT_ARGUMENT_NAMING is
-+ zero, this machine will be able to place unnamed args that were
-+ passed in registers into the stack. So treat all args as named.
-+ This allows the insns emitting for a specific argument list to be
-+ independent of the function declaration.
-+
-+ If PRETEND_OUTGOING_VARARGS_NAMED is not set, we do not have any
-+ reliable way to pass unnamed args in registers, so we must force
-+ them into memory. */
-+
-+ if ((STRICT_ARGUMENT_NAMING
-+ || ! PRETEND_OUTGOING_VARARGS_NAMED)
-+ && TYPE_ARG_TYPES (funtype) != 0)
-+ n_named_args
-+ = (list_length (TYPE_ARG_TYPES (funtype))
-+ /* Don't include the last named arg. */
-+ - (STRICT_ARGUMENT_NAMING ? 0 : 1)
-+ /* Count the struct value address, if it is passed as a parm. */
-+ + structure_value_addr_parm);
-+ else
-+ /* If we know nothing, treat all args as named. */
-+ n_named_args = num_actuals;
-+
-+ /* Start updating where the next arg would go.
-+
-+ On some machines (such as the PA) indirect calls have a different
-+ calling convention than normal calls. The last argument in
-+ INIT_CUMULATIVE_ARGS tells the backend if this is an indirect call
-+ or not. */
-+ INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, (fndecl == 0));
-+
-+ /* Make a vector to hold all the information about each arg. */
-+ args = (struct arg_data *) alloca (num_actuals * sizeof (struct arg_data));
-+ memset ((char *) args, 0, num_actuals * sizeof (struct arg_data));
-+
-+ /* Build up entries in the ARGS array, compute the size of the
-+ arguments into ARGS_SIZE, etc. */
-+ initialize_argument_information (num_actuals, args, &args_size,
-+ n_named_args, actparms, fndecl,
-+ &args_so_far, reg_parm_stack_space,
-+ &old_stack_level, &old_pending_adj,
-+ &must_preallocate, &flags);
-+
-+ if (args_size.var)
-+ {
-+ /* If this function requires a variable-sized argument list, don't
-+ try to make a cse'able block for this call. We may be able to
-+ do this eventually, but it is too complicated to keep track of
-+ what insns go in the cse'able block and which don't. */
-+
-+ flags &= ~ECF_LIBCALL_BLOCK;
-+ must_preallocate = 1;
-+ }
-+
-+ /* Now make final decision about preallocating stack space. */
-+ must_preallocate = finalize_must_preallocate (must_preallocate,
-+ num_actuals, args,
-+ &args_size);
-+
-+ /* If the structure value address will reference the stack pointer, we
-+ must stabilize it. We don't need to do this if we know that we are
-+ not going to adjust the stack pointer in processing this call. */
-+
-+ if (structure_value_addr
-+ && (reg_mentioned_p (virtual_stack_dynamic_rtx, structure_value_addr)
-+ || reg_mentioned_p (virtual_outgoing_args_rtx,
-+ structure_value_addr))
-+ && (args_size.var
-+ || (!ACCUMULATE_OUTGOING_ARGS && args_size.constant)))
-+ structure_value_addr = copy_to_reg (structure_value_addr);
-+
-+ /* Tail calls can make things harder to debug, and we're traditionally
-+ pushed these optimizations into -O2. Don't try if we're already
-+ expanding a call, as that means we're an argument. Don't try if
-+ there's cleanups, as we know there's code to follow the call.
-+
-+ If rtx_equal_function_value_matters is false, that means we've
-+ finished with regular parsing. Which means that some of the
-+ machinery we use to generate tail-calls is no longer in place.
-+ This is most often true of sjlj-exceptions, which we couldn't
-+ tail-call to anyway. */
-+
-+ if (currently_expanding_call++ != 0
-+ || !flag_optimize_sibling_calls
-+ || !rtx_equal_function_value_matters
-+ || any_pending_cleanups (1)
-+ || args_size.var)
-+ try_tail_call = try_tail_recursion = 0;
-+
-+ /* Tail recursion fails, when we are not dealing with recursive calls. */
-+ if (!try_tail_recursion
-+ || TREE_CODE (addr) != ADDR_EXPR
-+ || TREE_OPERAND (addr, 0) != current_function_decl)
-+ try_tail_recursion = 0;
-+
-+ /* Rest of purposes for tail call optimizations to fail. */
-+ if (
-+#ifdef HAVE_sibcall_epilogue
-+ !HAVE_sibcall_epilogue
-+#else
-+ 1
-+#endif
-+ || !try_tail_call
-+ /* Doing sibling call optimization needs some work, since
-+ structure_value_addr can be allocated on the stack.
-+ It does not seem worth the effort since few optimizable
-+ sibling calls will return a structure. */
-+ || structure_value_addr != NULL_RTX
-+ /* If the register holding the address is a callee saved
-+ register, then we lose. We have no way to prevent that,
-+ so we only allow calls to named functions. */
-+ /* ??? This could be done by having the insn constraints
-+ use a register class that is all call-clobbered. Any
-+ reload insns generated to fix things up would appear
-+ before the sibcall_epilogue. */
-+ || fndecl == NULL_TREE
-+ || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP | ECF_NORETURN))
-+ || !FUNCTION_OK_FOR_SIBCALL (fndecl)
-+ /* If this function requires more stack slots than the current
-+ function, we cannot change it into a sibling call. */
-+ || args_size.constant > current_function_args_size
-+ /* If the callee pops its own arguments, then it must pop exactly
-+ the same number of arguments as the current function. */
-+ || (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant)
-+ != RETURN_POPS_ARGS (current_function_decl,
-+ TREE_TYPE (current_function_decl),
-+ current_function_args_size))
-+ || !(*lang_hooks.decls.ok_for_sibcall) (fndecl))
-+ try_tail_call = 0;
-+
-+ if (try_tail_call || try_tail_recursion)
-+ {
-+ int end, inc;
-+ actparms = NULL_TREE;
-+ /* Ok, we're going to give the tail call the old college try.
-+ This means we're going to evaluate the function arguments
-+ up to three times. There are two degrees of badness we can
-+ encounter, those that can be unsaved and those that can't.
-+ (See unsafe_for_reeval commentary for details.)
-+
-+ Generate a new argument list. Pass safe arguments through
-+ unchanged. For the easy badness wrap them in UNSAVE_EXPRs.
-+ For hard badness, evaluate them now and put their resulting
-+ rtx in a temporary VAR_DECL.
-+
-+ initialize_argument_information has ordered the array for the
-+ order to be pushed, and we must remember this when reconstructing
-+ the original argument order. */
-+
-+ if (PUSH_ARGS_REVERSED)
-+ {
-+ inc = 1;
-+ i = 0;
-+ end = num_actuals;
-+ }
-+ else
-+ {
-+ inc = -1;
-+ i = num_actuals - 1;
-+ end = -1;
-+ }
-+
-+ for (; i != end; i += inc)
-+ {
-+ args[i].tree_value = fix_unsafe_tree (args[i].tree_value);
-+ /* We need to build actparms for optimize_tail_recursion. We can
-+ safely trash away TREE_PURPOSE, since it is unused by this
-+ function. */
-+ if (try_tail_recursion)
-+ actparms = tree_cons (NULL_TREE, args[i].tree_value, actparms);
-+ }
-+ /* Do the same for the function address if it is an expression. */
-+ if (!fndecl)
-+ addr = fix_unsafe_tree (addr);
-+ /* Expanding one of those dangerous arguments could have added
-+ cleanups, but otherwise give it a whirl. */
-+ if (any_pending_cleanups (1))
-+ try_tail_call = try_tail_recursion = 0;
-+ }
-+
-+ /* Generate a tail recursion sequence when calling ourselves. */
-+
-+ if (try_tail_recursion)
-+ {
-+ /* We want to emit any pending stack adjustments before the tail
-+ recursion "call". That way we know any adjustment after the tail
-+ recursion call can be ignored if we indeed use the tail recursion
-+ call expansion. */
-+ int save_pending_stack_adjust = pending_stack_adjust;
-+ int save_stack_pointer_delta = stack_pointer_delta;
-+
-+ /* Emit any queued insns now; otherwise they would end up in
-+ only one of the alternates. */
-+ emit_queue ();
-+
-+ /* Use a new sequence to hold any RTL we generate. We do not even
-+ know if we will use this RTL yet. The final decision can not be
-+ made until after RTL generation for the entire function is
-+ complete. */
-+ start_sequence ();
-+ /* If expanding any of the arguments creates cleanups, we can't
-+ do a tailcall. So, we'll need to pop the pending cleanups
-+ list. If, however, all goes well, and there are no cleanups
-+ then the call to expand_start_target_temps will have no
-+ effect. */
-+ expand_start_target_temps ();
-+ if (optimize_tail_recursion (actparms, get_last_insn ()))
-+ {
-+ if (any_pending_cleanups (1))
-+ try_tail_call = try_tail_recursion = 0;
-+ else
-+ tail_recursion_insns = get_insns ();
-+ }
-+ expand_end_target_temps ();
-+ end_sequence ();
-+
-+ /* Restore the original pending stack adjustment for the sibling and
-+ normal call cases below. */
-+ pending_stack_adjust = save_pending_stack_adjust;
-+ stack_pointer_delta = save_stack_pointer_delta;
-+ }
-+
-+ if (profile_arc_flag && (flags & ECF_FORK_OR_EXEC))
-+ {
-+ /* A fork duplicates the profile information, and an exec discards
-+ it. We can't rely on fork/exec to be paired. So write out the
-+ profile information we have gathered so far, and clear it. */
-+ /* ??? When Linux's __clone is called with CLONE_VM set, profiling
-+ is subject to race conditions, just as with multithreaded
-+ programs. */
-+
-+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__bb_fork_func"),
-+ LCT_ALWAYS_RETURN,
-+ VOIDmode, 0);
-+ }
-+
-+ /* Ensure current function's preferred stack boundary is at least
-+ what we need. We don't have to increase alignment for recursive
-+ functions. */
-+ if (cfun->preferred_stack_boundary < preferred_stack_boundary
-+ && fndecl != current_function_decl)
-+ cfun->preferred_stack_boundary = preferred_stack_boundary;
-+
-+ preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
-+
-+ function_call_count++;
-+
-+ /* We want to make two insn chains; one for a sibling call, the other
-+ for a normal call. We will select one of the two chains after
-+ initial RTL generation is complete. */
-+ for (pass = 0; pass < 2; pass++)
-+ {
-+ int sibcall_failure = 0;
-+ /* We want to emit any pending stack adjustments before the tail
-+ recursion "call". That way we know any adjustment after the tail
-+ recursion call can be ignored if we indeed use the tail recursion
-+ call expansion. */
-+ int save_pending_stack_adjust = 0;
-+ int save_stack_pointer_delta = 0;
-+ rtx insns;
-+ rtx before_call, next_arg_reg;
-+
-+ if (pass == 0)
-+ {
-+ if (! try_tail_call)
-+ continue;
-+
-+ /* Emit any queued insns now; otherwise they would end up in
-+ only one of the alternates. */
-+ emit_queue ();
-+
-+ /* State variables we need to save and restore between
-+ iterations. */
-+ save_pending_stack_adjust = pending_stack_adjust;
-+ save_stack_pointer_delta = stack_pointer_delta;
-+ }
-+ if (pass)
-+ flags &= ~ECF_SIBCALL;
-+ else
-+ flags |= ECF_SIBCALL;
-+
-+ /* Other state variables that we must reinitialize each time
-+ through the loop (that are not initialized by the loop itself). */
-+ argblock = 0;
-+ call_fusage = 0;
-+
-+ /* Start a new sequence for the normal call case.
-+
-+ From this point on, if the sibling call fails, we want to set
-+ sibcall_failure instead of continuing the loop. */
-+ start_sequence ();
-+
-+ if (pass == 0)
-+ {
-+ /* We know at this point that there are not currently any
-+ pending cleanups. If, however, in the process of evaluating
-+ the arguments we were to create some, we'll need to be
-+ able to get rid of them. */
-+ expand_start_target_temps ();
-+ }
-+
-+ /* Don't let pending stack adjusts add up to too much.
-+ Also, do all pending adjustments now if there is any chance
-+ this might be a call to alloca or if we are expanding a sibling
-+ call sequence or if we are calling a function that is to return
-+ with stack pointer depressed. */
-+ if (pending_stack_adjust >= 32
-+ || (pending_stack_adjust > 0
-+ && (flags & (ECF_MAY_BE_ALLOCA | ECF_SP_DEPRESSED)))
-+ || pass == 0)
-+ do_pending_stack_adjust ();
-+
-+ /* When calling a const function, we must pop the stack args right away,
-+ so that the pop is deleted or moved with the call. */
-+ if (pass && (flags & ECF_LIBCALL_BLOCK))
-+ NO_DEFER_POP;
-+
-+#ifdef FINAL_REG_PARM_STACK_SPACE
-+ reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant,
-+ args_size.var);
-+#endif
-+ /* Precompute any arguments as needed. */
-+ if (pass)
-+ precompute_arguments (flags, num_actuals, args);
-+
-+ /* Now we are about to start emitting insns that can be deleted
-+ if a libcall is deleted. */
-+ if (pass && (flags & (ECF_LIBCALL_BLOCK | ECF_MALLOC)))
-+ start_sequence ();
-+
-+ adjusted_args_size = args_size;
-+ /* Compute the actual size of the argument block required. The variable
-+ and constant sizes must be combined, the size may have to be rounded,
-+ and there may be a minimum required size. When generating a sibcall
-+ pattern, do not round up, since we'll be re-using whatever space our
-+ caller provided. */
-+ unadjusted_args_size
-+ = compute_argument_block_size (reg_parm_stack_space,
-+ &adjusted_args_size,
-+ (pass == 0 ? 0
-+ : preferred_stack_boundary));
-+
-+ old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
-+
-+ /* The argument block when performing a sibling call is the
-+ incoming argument block. */
-+ if (pass == 0)
-+ {
-+ argblock = virtual_incoming_args_rtx;
-+ argblock
-+#ifdef STACK_GROWS_DOWNWARD
-+ = plus_constant (argblock, current_function_pretend_args_size);
-+#else
-+ = plus_constant (argblock, -current_function_pretend_args_size);
-+#endif
-+ stored_args_map = sbitmap_alloc (args_size.constant);
-+ sbitmap_zero (stored_args_map);
-+ }
-+
-+ /* If we have no actual push instructions, or shouldn't use them,
-+ make space for all args right now. */
-+ else if (adjusted_args_size.var != 0)
-+ {
-+ if (old_stack_level == 0)
-+ {
-+ emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
-+ old_pending_adj = pending_stack_adjust;
-+ pending_stack_adjust = 0;
-+ /* stack_arg_under_construction says whether a stack arg is
-+ being constructed at the old stack level. Pushing the stack
-+ gets a clean outgoing argument block. */
-+ old_stack_arg_under_construction = stack_arg_under_construction;
-+ stack_arg_under_construction = 0;
-+ }
-+ argblock = push_block (ARGS_SIZE_RTX (adjusted_args_size), 0, 0);
-+ }
-+ else
-+ {
-+ /* Note that we must go through the motions of allocating an argument
-+ block even if the size is zero because we may be storing args
-+ in the area reserved for register arguments, which may be part of
-+ the stack frame. */
-+
-+ int needed = adjusted_args_size.constant;
-+
-+ /* Store the maximum argument space used. It will be pushed by
-+ the prologue (if ACCUMULATE_OUTGOING_ARGS, or stack overflow
-+ checking). */
-+
-+ if (needed > current_function_outgoing_args_size)
-+ current_function_outgoing_args_size = needed;
-+
-+ if (must_preallocate)
-+ {
-+ if (ACCUMULATE_OUTGOING_ARGS)
-+ {
-+ /* Since the stack pointer will never be pushed, it is
-+ possible for the evaluation of a parm to clobber
-+ something we have already written to the stack.
-+ Since most function calls on RISC machines do not use
-+ the stack, this is uncommon, but must work correctly.
-+
-+ Therefore, we save any area of the stack that was already
-+ written and that we are using. Here we set up to do this
-+ by making a new stack usage map from the old one. The
-+ actual save will be done by store_one_arg.
-+
-+ Another approach might be to try to reorder the argument
-+ evaluations to avoid this conflicting stack usage. */
-+
-+#ifndef OUTGOING_REG_PARM_STACK_SPACE
-+ /* Since we will be writing into the entire argument area,
-+ the map must be allocated for its entire size, not just
-+ the part that is the responsibility of the caller. */
-+ needed += reg_parm_stack_space;
-+#endif
-+
-+#ifdef ARGS_GROW_DOWNWARD
-+ highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
-+ needed + 1);
-+#else
-+ highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
-+ needed);
-+#endif
-+ stack_usage_map
-+ = (char *) alloca (highest_outgoing_arg_in_use);
-+
-+ if (initial_highest_arg_in_use)
-+ memcpy (stack_usage_map, initial_stack_usage_map,
-+ initial_highest_arg_in_use);
-+
-+ if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
-+ memset (&stack_usage_map[initial_highest_arg_in_use], 0,
-+ (highest_outgoing_arg_in_use
-+ - initial_highest_arg_in_use));
-+ needed = 0;
-+
-+ /* The address of the outgoing argument list must not be
-+ copied to a register here, because argblock would be left
-+ pointing to the wrong place after the call to
-+ allocate_dynamic_stack_space below. */
-+
-+ argblock = virtual_outgoing_args_rtx;
-+ }
-+ else
-+ {
-+ if (inhibit_defer_pop == 0)
-+ {
-+ /* Try to reuse some or all of the pending_stack_adjust
-+ to get this space. */
-+ needed
-+ = (combine_pending_stack_adjustment_and_call
-+ (unadjusted_args_size,
-+ &adjusted_args_size,
-+ preferred_unit_stack_boundary));
-+
-+ /* combine_pending_stack_adjustment_and_call computes
-+ an adjustment before the arguments are allocated.
-+ Account for them and see whether or not the stack
-+ needs to go up or down. */
-+ needed = unadjusted_args_size - needed;
-+
-+ if (needed < 0)
-+ {
-+ /* We're releasing stack space. */
-+ /* ??? We can avoid any adjustment at all if we're
-+ already aligned. FIXME. */
-+ pending_stack_adjust = -needed;
-+ do_pending_stack_adjust ();
-+ needed = 0;
-+ }
-+ else
-+ /* We need to allocate space. We'll do that in
-+ push_block below. */
-+ pending_stack_adjust = 0;
-+ }
-+
-+ /* Special case this because overhead of `push_block' in
-+ this case is non-trivial. */
-+ if (needed == 0)
-+ argblock = virtual_outgoing_args_rtx;
-+ else
-+ argblock = push_block (GEN_INT (needed), 0, 0);
-+
-+ /* We only really need to call `copy_to_reg' in the case
-+ where push insns are going to be used to pass ARGBLOCK
-+ to a function call in ARGS. In that case, the stack
-+ pointer changes value from the allocation point to the
-+ call point, and hence the value of
-+ VIRTUAL_OUTGOING_ARGS_RTX changes as well. But might
-+ as well always do it. */
-+ argblock = copy_to_reg (argblock);
-+
-+ /* The save/restore code in store_one_arg handles all
-+ cases except one: a constructor call (including a C
-+ function returning a BLKmode struct) to initialize
-+ an argument. */
-+ if (stack_arg_under_construction)
-+ {
-+#ifndef OUTGOING_REG_PARM_STACK_SPACE
-+ rtx push_size = GEN_INT (reg_parm_stack_space
-+ + adjusted_args_size.constant);
-+#else
-+ rtx push_size = GEN_INT (adjusted_args_size.constant);
-+#endif
-+ if (old_stack_level == 0)
-+ {
-+ emit_stack_save (SAVE_BLOCK, &old_stack_level,
-+ NULL_RTX);
-+ old_pending_adj = pending_stack_adjust;
-+ pending_stack_adjust = 0;
-+ /* stack_arg_under_construction says whether a stack
-+ arg is being constructed at the old stack level.
-+ Pushing the stack gets a clean outgoing argument
-+ block. */
-+ old_stack_arg_under_construction
-+ = stack_arg_under_construction;
-+ stack_arg_under_construction = 0;
-+ /* Make a new map for the new argument list. */
-+ stack_usage_map = (char *)
-+ alloca (highest_outgoing_arg_in_use);
-+ memset (stack_usage_map, 0, highest_outgoing_arg_in_use);
-+ highest_outgoing_arg_in_use = 0;
-+ }
-+ allocate_dynamic_stack_space (push_size, NULL_RTX,
-+ BITS_PER_UNIT);
-+ }
-+ /* If argument evaluation might modify the stack pointer,
-+ copy the address of the argument list to a register. */
-+ for (i = 0; i < num_actuals; i++)
-+ if (args[i].pass_on_stack)
-+ {
-+ argblock = copy_addr_to_reg (argblock);
-+ break;
-+ }
-+ }
-+ }
-+ }
-+
-+ compute_argument_addresses (args, argblock, num_actuals);
-+
-+ /* If we push args individually in reverse order, perform stack alignment
-+ before the first push (the last arg). */
-+ if (PUSH_ARGS_REVERSED && argblock == 0
-+ && adjusted_args_size.constant != unadjusted_args_size)
-+ {
-+ /* When the stack adjustment is pending, we get better code
-+ by combining the adjustments. */
-+ if (pending_stack_adjust
-+ && ! (flags & ECF_LIBCALL_BLOCK)
-+ && ! inhibit_defer_pop)
-+ {
-+ pending_stack_adjust
-+ = (combine_pending_stack_adjustment_and_call
-+ (unadjusted_args_size,
-+ &adjusted_args_size,
-+ preferred_unit_stack_boundary));
-+ do_pending_stack_adjust ();
-+ }
-+ else if (argblock == 0)
-+ anti_adjust_stack (GEN_INT (adjusted_args_size.constant
-+ - unadjusted_args_size));
-+ }
-+ /* Now that the stack is properly aligned, pops can't safely
-+ be deferred during the evaluation of the arguments. */
-+ NO_DEFER_POP;
-+
-+ funexp = rtx_for_function_call (fndecl, addr);
-+
-+ /* Figure out the register where the value, if any, will come back. */
-+ valreg = 0;
-+ if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
-+ && ! structure_value_addr)
-+ {
-+ if (pcc_struct_value)
-+ valreg = hard_function_value (build_pointer_type (TREE_TYPE (exp)),
-+ fndecl, (pass == 0));
-+ else
-+ valreg = hard_function_value (TREE_TYPE (exp), fndecl, (pass == 0));
-+ }
-+
-+ /* Precompute all register parameters. It isn't safe to compute anything
-+ once we have started filling any specific hard regs. */
-+ precompute_register_parameters (num_actuals, args, ®_parm_seen);
-+
-+#ifdef REG_PARM_STACK_SPACE
-+ /* Save the fixed argument area if it's part of the caller's frame and
-+ is clobbered by argument setup for this call. */
-+ if (ACCUMULATE_OUTGOING_ARGS && pass)
-+ save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
-+ &low_to_save, &high_to_save);
-+#endif
-+
-+ /* Now store (and compute if necessary) all non-register parms.
-+ These come before register parms, since they can require block-moves,
-+ which could clobber the registers used for register parms.
-+ Parms which have partial registers are not stored here,
-+ but we do preallocate space here if they want that. */
-+
-+ for (i = 0; i < num_actuals; i++)
-+ if (args[i].reg == 0 || args[i].pass_on_stack)
-+ {
-+ rtx before_arg = get_last_insn ();
-+
-+ if (store_one_arg (&args[i], argblock, flags,
-+ adjusted_args_size.var != 0,
-+ reg_parm_stack_space)
-+ || (pass == 0
-+ && check_sibcall_argument_overlap (before_arg,
-+ &args[i])))
-+ sibcall_failure = 1;
-+ }
-+
-+ /* If we have a parm that is passed in registers but not in memory
-+ and whose alignment does not permit a direct copy into registers,
-+ make a group of pseudos that correspond to each register that we
-+ will later fill. */
-+ if (STRICT_ALIGNMENT)
-+ store_unaligned_arguments_into_pseudos (args, num_actuals);
-+
-+ /* Now store any partially-in-registers parm.
-+ This is the last place a block-move can happen. */
-+ if (reg_parm_seen)
-+ for (i = 0; i < num_actuals; i++)
-+ if (args[i].partial != 0 && ! args[i].pass_on_stack)
-+ {
-+ rtx before_arg = get_last_insn ();
-+
-+ if (store_one_arg (&args[i], argblock, flags,
-+ adjusted_args_size.var != 0,
-+ reg_parm_stack_space)
-+ || (pass == 0
-+ && check_sibcall_argument_overlap (before_arg,
-+ &args[i])))
-+ sibcall_failure = 1;
-+ }
-+
-+ /* If we pushed args in forward order, perform stack alignment
-+ after pushing the last arg. */
-+ if (!PUSH_ARGS_REVERSED && argblock == 0)
-+ anti_adjust_stack (GEN_INT (adjusted_args_size.constant
-+ - unadjusted_args_size));
-+
-+ /* If register arguments require space on the stack and stack space
-+ was not preallocated, allocate stack space here for arguments
-+ passed in registers. */
-+#ifdef OUTGOING_REG_PARM_STACK_SPACE
-+ if (!ACCUMULATE_OUTGOING_ARGS
-+ && must_preallocate == 0 && reg_parm_stack_space > 0)
-+ anti_adjust_stack (GEN_INT (reg_parm_stack_space));
-+#endif
-+
-+ /* Pass the function the address in which to return a
-+ structure value. */
-+ if (pass != 0 && structure_value_addr && ! structure_value_addr_parm)
-+ {
-+ emit_move_insn (struct_value_rtx,
-+ force_reg (Pmode,
-+ force_operand (structure_value_addr,
-+ NULL_RTX)));
-+
-+ if (GET_CODE (struct_value_rtx) == REG)
-+ use_reg (&call_fusage, struct_value_rtx);
-+ }
-+
-+ funexp = prepare_call_address (funexp, fndecl, &call_fusage,
-+ reg_parm_seen, pass == 0);
-+
-+ load_register_parameters (args, num_actuals, &call_fusage, flags);
-+
-+ /* Perform postincrements before actually calling the function. */
-+ emit_queue ();
-+
-+ /* Save a pointer to the last insn before the call, so that we can
-+ later safely search backwards to find the CALL_INSN. */
-+ before_call = get_last_insn ();
-+
-+ /* Set up next argument register. For sibling calls on machines
-+ with register windows this should be the incoming register. */
-+#ifdef FUNCTION_INCOMING_ARG
-+ if (pass == 0)
-+ next_arg_reg = FUNCTION_INCOMING_ARG (args_so_far, VOIDmode,
-+ void_type_node, 1);
-+ else
-+#endif
-+ next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode,
-+ void_type_node, 1);
-+
-+ /* All arguments and registers used for the call must be set up by
-+ now! */
-+
-+ /* Stack must be properly aligned now. */
-+ if (pass && stack_pointer_delta % preferred_unit_stack_boundary)
-+ abort ();
-+
-+ /* Generate the actual call instruction. */
-+ emit_call_1 (funexp, fndecl, funtype, unadjusted_args_size,
-+ adjusted_args_size.constant, struct_value_size,
-+ next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
-+ flags, & args_so_far);
-+
-+ /* Verify that we've deallocated all the stack we used. */
-+ if (pass
-+ && old_stack_allocated != stack_pointer_delta - pending_stack_adjust)
-+ abort ();
-+
-+ /* If call is cse'able, make appropriate pair of reg-notes around it.
-+ Test valreg so we don't crash; may safely ignore `const'
-+ if return type is void. Disable for PARALLEL return values, because
-+ we have no way to move such values into a pseudo register. */
-+ if (pass && (flags & ECF_LIBCALL_BLOCK))
-+ {
-+ rtx insns;
-+
-+ if (valreg == 0 || GET_CODE (valreg) == PARALLEL)
-+ {
-+ insns = get_insns ();
-+ end_sequence ();
-+ emit_insn (insns);
-+ }
-+ else
-+ {
-+ rtx note = 0;
-+ rtx temp = gen_reg_rtx (GET_MODE (valreg));
-+
-+ /* Mark the return value as a pointer if needed. */
-+ if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
-+ mark_reg_pointer (temp,
-+ TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))));
-+
-+ /* Construct an "equal form" for the value which mentions all the
-+ arguments in order as well as the function name. */
-+ for (i = 0; i < num_actuals; i++)
-+ note = gen_rtx_EXPR_LIST (VOIDmode,
-+ args[i].initial_value, note);
-+ note = gen_rtx_EXPR_LIST (VOIDmode, funexp, note);
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ if (flags & ECF_PURE)
-+ note = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_USE (VOIDmode,
-+ gen_rtx_MEM (BLKmode,
-+ gen_rtx_SCRATCH (VOIDmode))),
-+ note);
-+
-+ emit_libcall_block (insns, temp, valreg, note);
-+
-+ valreg = temp;
-+ }
-+ }
-+ else if (pass && (flags & ECF_MALLOC))
-+ {
-+ rtx temp = gen_reg_rtx (GET_MODE (valreg));
-+ rtx last, insns;
-+
-+ /* The return value from a malloc-like function is a pointer. */
-+ if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
-+ mark_reg_pointer (temp, BIGGEST_ALIGNMENT);
-+
-+ emit_move_insn (temp, valreg);
-+
-+ /* The return value from a malloc-like function can not alias
-+ anything else. */
-+ last = get_last_insn ();
-+ REG_NOTES (last) =
-+ gen_rtx_EXPR_LIST (REG_NOALIAS, temp, REG_NOTES (last));
-+
-+ /* Write out the sequence. */
-+ insns = get_insns ();
-+ end_sequence ();
-+ emit_insn (insns);
-+ valreg = temp;
-+ }
-+
-+ /* For calls to `setjmp', etc., inform flow.c it should complain
-+ if nonvolatile values are live. For functions that cannot return,
-+ inform flow that control does not fall through. */
-+
-+ if ((flags & (ECF_NORETURN | ECF_LONGJMP)) || pass == 0)
-+ {
-+ /* The barrier must be emitted
-+ immediately after the CALL_INSN. Some ports emit more
-+ than just a CALL_INSN above, so we must search for it here. */
-+
-+ rtx last = get_last_insn ();
-+ while (GET_CODE (last) != CALL_INSN)
-+ {
-+ last = PREV_INSN (last);
-+ /* There was no CALL_INSN? */
-+ if (last == before_call)
-+ abort ();
-+ }
-+
-+ emit_barrier_after (last);
-+ }
-+
-+ if (flags & ECF_LONGJMP)
-+ current_function_calls_longjmp = 1;
-+
-+ /* If this function is returning into a memory location marked as
-+ readonly, it means it is initializing that location. But we normally
-+ treat functions as not clobbering such locations, so we need to
-+ specify that this one does. */
-+ if (target != 0 && GET_CODE (target) == MEM
-+ && structure_value_addr != 0 && RTX_UNCHANGING_P (target))
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
-+
-+ /* If value type not void, return an rtx for the value. */
-+
-+ /* If there are cleanups to be called, don't use a hard reg as target.
-+ We need to double check this and see if it matters anymore. */
-+ if (any_pending_cleanups (1))
-+ {
-+ if (target && REG_P (target)
-+ && REGNO (target) < FIRST_PSEUDO_REGISTER)
-+ target = 0;
-+ sibcall_failure = 1;
-+ }
-+
-+ if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
-+ || ignore)
-+ target = const0_rtx;
-+ else if (structure_value_addr)
-+ {
-+ if (target == 0 || GET_CODE (target) != MEM)
-+ {
-+ target
-+ = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
-+ memory_address (TYPE_MODE (TREE_TYPE (exp)),
-+ structure_value_addr));
-+ set_mem_attributes (target, exp, 1);
-+ }
-+ }
-+ else if (pcc_struct_value)
-+ {
-+ /* This is the special C++ case where we need to
-+ know what the true target was. We take care to
-+ never use this value more than once in one expression. */
-+ target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
-+ copy_to_reg (valreg));
-+ set_mem_attributes (target, exp, 1);
-+ }
-+ /* Handle calls that return values in multiple non-contiguous locations.
-+ The Irix 6 ABI has examples of this. */
-+ else if (GET_CODE (valreg) == PARALLEL)
-+ {
-+ if (target == 0)
-+ {
-+ /* This will only be assigned once, so it can be readonly. */
-+ tree nt = build_qualified_type (TREE_TYPE (exp),
-+ (TYPE_QUALS (TREE_TYPE (exp))
-+ | TYPE_QUAL_CONST));
-+
-+ target = assign_temp (nt, 0, 1, 1);
-+ preserve_temp_slots (target);
-+ }
-+
-+ if (! rtx_equal_p (target, valreg))
-+ emit_group_store (target, valreg,
-+ int_size_in_bytes (TREE_TYPE (exp)));
-+
-+ /* We can not support sibling calls for this case. */
-+ sibcall_failure = 1;
-+ }
-+ else if (target
-+ && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp))
-+ && GET_MODE (target) == GET_MODE (valreg))
-+ {
-+ /* TARGET and VALREG cannot be equal at this point because the
-+ latter would not have REG_FUNCTION_VALUE_P true, while the
-+ former would if it were referring to the same register.
-+
-+ If they refer to the same register, this move will be a no-op,
-+ except when function inlining is being done. */
-+ emit_move_insn (target, valreg);
-+ }
-+ else if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
-+ {
-+ target = copy_blkmode_from_reg (target, valreg, TREE_TYPE (exp));
-+
-+ /* We can not support sibling calls for this case. */
-+ sibcall_failure = 1;
-+ }
-+ else
-+ target = copy_to_reg (valreg);
-+
-+#ifdef PROMOTE_FUNCTION_RETURN
-+ /* If we promoted this return value, make the proper SUBREG. TARGET
-+ might be const0_rtx here, so be careful. */
-+ if (GET_CODE (target) == REG
-+ && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
-+ && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
-+ {
-+ tree type = TREE_TYPE (exp);
-+ int unsignedp = TREE_UNSIGNED (type);
-+ int offset = 0;
-+
-+ /* If we don't promote as expected, something is wrong. */
-+ if (GET_MODE (target)
-+ != promote_mode (type, TYPE_MODE (type), &unsignedp, 1))
-+ abort ();
-+
-+ if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
-+ && GET_MODE_SIZE (GET_MODE (target))
-+ > GET_MODE_SIZE (TYPE_MODE (type)))
-+ {
-+ offset = GET_MODE_SIZE (GET_MODE (target))
-+ - GET_MODE_SIZE (TYPE_MODE (type));
-+ if (! BYTES_BIG_ENDIAN)
-+ offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
-+ else if (! WORDS_BIG_ENDIAN)
-+ offset %= UNITS_PER_WORD;
-+ }
-+ target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
-+ SUBREG_PROMOTED_VAR_P (target) = 1;
-+ SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
-+ }
-+#endif
-+
-+ /* If size of args is variable or this was a constructor call for a stack
-+ argument, restore saved stack-pointer value. */
-+
-+ if (old_stack_level && ! (flags & ECF_SP_DEPRESSED))
-+ {
-+ emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
-+ pending_stack_adjust = old_pending_adj;
-+ stack_arg_under_construction = old_stack_arg_under_construction;
-+ highest_outgoing_arg_in_use = initial_highest_arg_in_use;
-+ stack_usage_map = initial_stack_usage_map;
-+ sibcall_failure = 1;
-+ }
-+ else if (ACCUMULATE_OUTGOING_ARGS && pass)
-+ {
-+#ifdef REG_PARM_STACK_SPACE
-+ if (save_area)
-+ {
-+ restore_fixed_argument_area (save_area, argblock,
-+ high_to_save, low_to_save);
-+ }
-+#endif
-+
-+ /* If we saved any argument areas, restore them. */
-+ for (i = 0; i < num_actuals; i++)
-+ if (args[i].save_area)
-+ {
-+ enum machine_mode save_mode = GET_MODE (args[i].save_area);
-+ rtx stack_area
-+ = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ XEXP (args[i].stack_slot, 0)));
-+
-+ if (save_mode != BLKmode)
-+ emit_move_insn (stack_area, args[i].save_area);
-+ else
-+ emit_block_move (stack_area, args[i].save_area,
-+ GEN_INT (args[i].size.constant),
-+ BLOCK_OP_CALL_PARM);
-+ }
-+
-+ highest_outgoing_arg_in_use = initial_highest_arg_in_use;
-+ stack_usage_map = initial_stack_usage_map;
-+ }
-+
-+ /* If this was alloca, record the new stack level for nonlocal gotos.
-+ Check for the handler slots since we might not have a save area
-+ for non-local gotos. */
-+
-+ if ((flags & ECF_MAY_BE_ALLOCA) && nonlocal_goto_handler_slots != 0)
-+ emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
-+
-+ /* Free up storage we no longer need. */
-+ for (i = 0; i < num_actuals; ++i)
-+ if (args[i].aligned_regs)
-+ free (args[i].aligned_regs);
-+
-+ if (pass == 0)
-+ {
-+ /* Undo the fake expand_start_target_temps we did earlier. If
-+ there had been any cleanups created, we've already set
-+ sibcall_failure. */
-+ expand_end_target_temps ();
-+ }
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ if (pass == 0)
-+ {
-+ tail_call_insns = insns;
-+
-+ /* Restore the pending stack adjustment now that we have
-+ finished generating the sibling call sequence. */
-+
-+ pending_stack_adjust = save_pending_stack_adjust;
-+ stack_pointer_delta = save_stack_pointer_delta;
-+
-+ /* Prepare arg structure for next iteration. */
-+ for (i = 0; i < num_actuals; i++)
-+ {
-+ args[i].value = 0;
-+ args[i].aligned_regs = 0;
-+ args[i].stack = 0;
-+ }
-+
-+ sbitmap_free (stored_args_map);
-+ }
-+ else
-+ normal_call_insns = insns;
-+
-+ /* If something prevents making this a sibling call,
-+ zero out the sequence. */
-+ if (sibcall_failure)
-+ tail_call_insns = NULL_RTX;
-+ }
-+
-+ /* The function optimize_sibling_and_tail_recursive_calls doesn't
-+ handle CALL_PLACEHOLDERs inside other CALL_PLACEHOLDERs. This
-+ can happen if the arguments to this function call an inline
-+ function who's expansion contains another CALL_PLACEHOLDER.
-+
-+ If there are any C_Ps in any of these sequences, replace them
-+ with their normal call. */
-+
-+ for (insn = normal_call_insns; insn; insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) == CALL_INSN
-+ && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-+ replace_call_placeholder (insn, sibcall_use_normal);
-+
-+ for (insn = tail_call_insns; insn; insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) == CALL_INSN
-+ && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-+ replace_call_placeholder (insn, sibcall_use_normal);
-+
-+ for (insn = tail_recursion_insns; insn; insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) == CALL_INSN
-+ && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-+ replace_call_placeholder (insn, sibcall_use_normal);
-+
-+ /* If this was a potential tail recursion site, then emit a
-+ CALL_PLACEHOLDER with the normal and the tail recursion streams.
-+ One of them will be selected later. */
-+ if (tail_recursion_insns || tail_call_insns)
-+ {
-+ /* The tail recursion label must be kept around. We could expose
-+ its use in the CALL_PLACEHOLDER, but that creates unwanted edges
-+ and makes determining true tail recursion sites difficult.
-+
-+ So we set LABEL_PRESERVE_P here, then clear it when we select
-+ one of the call sequences after rtl generation is complete. */
-+ if (tail_recursion_insns)
-+ LABEL_PRESERVE_P (tail_recursion_label) = 1;
-+ emit_call_insn (gen_rtx_CALL_PLACEHOLDER (VOIDmode, normal_call_insns,
-+ tail_call_insns,
-+ tail_recursion_insns,
-+ tail_recursion_label));
-+ }
-+ else
-+ emit_insn (normal_call_insns);
-+
-+ currently_expanding_call--;
-+
-+ /* If this function returns with the stack pointer depressed, ensure
-+ this block saves and restores the stack pointer, show it was
-+ changed, and adjust for any outgoing arg space. */
-+ if (flags & ECF_SP_DEPRESSED)
-+ {
-+ clear_pending_stack_adjust ();
-+ emit_insn (gen_rtx (CLOBBER, VOIDmode, stack_pointer_rtx));
-+ emit_move_insn (virtual_stack_dynamic_rtx, stack_pointer_rtx);
-+ save_stack_pointer ();
-+ }
-+
-+ return target;
-+}
-+\f
-+/* Output a library call to function FUN (a SYMBOL_REF rtx).
-+ The RETVAL parameter specifies whether return value needs to be saved, other
-+ parameters are documented in the emit_library_call function below. */
-+
-+static rtx
-+emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p)
-+ int retval;
-+ rtx orgfun;
-+ rtx value;
-+ enum libcall_type fn_type;
-+ enum machine_mode outmode;
-+ int nargs;
-+ va_list p;
-+{
-+ /* Total size in bytes of all the stack-parms scanned so far. */
-+ struct args_size args_size;
-+ /* Size of arguments before any adjustments (such as rounding). */
-+ struct args_size original_args_size;
-+ int argnum;
-+ rtx fun;
-+ int inc;
-+ int count;
-+ struct args_size alignment_pad;
-+ rtx argblock = 0;
-+ CUMULATIVE_ARGS args_so_far;
-+ struct arg
-+ {
-+ rtx value;
-+ enum machine_mode mode;
-+ rtx reg;
-+ int partial;
-+ struct args_size offset;
-+ struct args_size size;
-+ rtx save_area;
-+ };
-+ struct arg *argvec;
-+ int old_inhibit_defer_pop = inhibit_defer_pop;
-+ rtx call_fusage = 0;
-+ rtx mem_value = 0;
-+ rtx valreg;
-+ int pcc_struct_value = 0;
-+ int struct_value_size = 0;
-+ int flags;
-+ int reg_parm_stack_space = 0;
-+ int needed;
-+ rtx before_call;
-+ tree tfom; /* type_for_mode (outmode, 0) */
-+
-+#ifdef REG_PARM_STACK_SPACE
-+ /* Define the boundary of the register parm stack space that needs to be
-+ save, if any. */
-+ int low_to_save = -1, high_to_save = 0;
-+ rtx save_area = 0; /* Place that it is saved. */
-+#endif
-+
-+ /* Size of the stack reserved for parameter registers. */
-+ int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
-+ char *initial_stack_usage_map = stack_usage_map;
-+
-+#ifdef REG_PARM_STACK_SPACE
-+#ifdef MAYBE_REG_PARM_STACK_SPACE
-+ reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
-+#else
-+ reg_parm_stack_space = REG_PARM_STACK_SPACE ((tree) 0);
-+#endif
-+#endif
-+
-+ /* By default, library functions can not throw. */
-+ flags = ECF_NOTHROW;
-+
-+ switch (fn_type)
-+ {
-+ case LCT_NORMAL:
-+ break;
-+ case LCT_CONST:
-+ flags |= ECF_CONST;
-+ break;
-+ case LCT_PURE:
-+ flags |= ECF_PURE;
-+ break;
-+ case LCT_CONST_MAKE_BLOCK:
-+ flags |= ECF_CONST | ECF_LIBCALL_BLOCK;
-+ break;
-+ case LCT_PURE_MAKE_BLOCK:
-+ flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
-+ break;
-+ case LCT_NORETURN:
-+ flags |= ECF_NORETURN;
-+ break;
-+ case LCT_THROW:
-+ flags = ECF_NORETURN;
-+ break;
-+ case LCT_ALWAYS_RETURN:
-+ flags = ECF_ALWAYS_RETURN;
-+ break;
-+ case LCT_RETURNS_TWICE:
-+ flags = ECF_RETURNS_TWICE;
-+ break;
-+ }
-+ fun = orgfun;
-+
-+ /* Ensure current function's preferred stack boundary is at least
-+ what we need. */
-+ if (cfun->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
-+ cfun->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
-+
-+ /* If this kind of value comes back in memory,
-+ decide where in memory it should come back. */
-+ if (outmode != VOIDmode)
-+ {
-+ tfom = (*lang_hooks.types.type_for_mode) (outmode, 0);
-+ if (aggregate_value_p (tfom))
-+ {
-+#ifdef PCC_STATIC_STRUCT_RETURN
-+ rtx pointer_reg
-+ = hard_function_value (build_pointer_type (tfom), 0, 0);
-+ mem_value = gen_rtx_MEM (outmode, pointer_reg);
-+ pcc_struct_value = 1;
-+ if (value == 0)
-+ value = gen_reg_rtx (outmode);
-+#else /* not PCC_STATIC_STRUCT_RETURN */
-+ struct_value_size = GET_MODE_SIZE (outmode);
-+ if (value != 0 && GET_CODE (value) == MEM)
-+ mem_value = value;
-+ else
-+ mem_value = assign_temp (tfom, 0, 1, 1);
-+#endif
-+ /* This call returns a big structure. */
-+ flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
-+ }
-+ }
-+ else
-+ tfom = void_type_node;
-+
-+ /* ??? Unfinished: must pass the memory address as an argument. */
-+
-+ /* Copy all the libcall-arguments out of the varargs data
-+ and into a vector ARGVEC.
-+
-+ Compute how to pass each argument. We only support a very small subset
-+ of the full argument passing conventions to limit complexity here since
-+ library functions shouldn't have many args. */
-+
-+ argvec = (struct arg *) alloca ((nargs + 1) * sizeof (struct arg));
-+ memset ((char *) argvec, 0, (nargs + 1) * sizeof (struct arg));
-+
-+#ifdef INIT_CUMULATIVE_LIBCALL_ARGS
-+ INIT_CUMULATIVE_LIBCALL_ARGS (args_so_far, outmode, fun);
-+#else
-+ INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun, 0);
-+#endif
-+
-+ args_size.constant = 0;
-+ args_size.var = 0;
-+
-+ count = 0;
-+
-+ /* Now we are about to start emitting insns that can be deleted
-+ if a libcall is deleted. */
-+ if (flags & ECF_LIBCALL_BLOCK)
-+ start_sequence ();
-+
-+ push_temp_slots ();
-+
-+ /* If there's a structure value address to be passed,
-+ either pass it in the special place, or pass it as an extra argument. */
-+ if (mem_value && struct_value_rtx == 0 && ! pcc_struct_value)
-+ {
-+ rtx addr = XEXP (mem_value, 0);
-+ nargs++;
-+
-+ /* Make sure it is a reasonable operand for a move or push insn. */
-+ if (GET_CODE (addr) != REG && GET_CODE (addr) != MEM
-+ && ! (CONSTANT_P (addr) && LEGITIMATE_CONSTANT_P (addr)))
-+ addr = force_operand (addr, NULL_RTX);
-+
-+ argvec[count].value = addr;
-+ argvec[count].mode = Pmode;
-+ argvec[count].partial = 0;
-+
-+ argvec[count].reg = FUNCTION_ARG (args_so_far, Pmode, NULL_TREE, 1);
-+#ifdef FUNCTION_ARG_PARTIAL_NREGS
-+ if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, Pmode, NULL_TREE, 1))
-+ abort ();
-+#endif
-+
-+ locate_and_pad_parm (Pmode, NULL_TREE,
-+#ifdef STACK_PARMS_IN_REG_PARM_AREA
-+ 1,
-+#else
-+ argvec[count].reg != 0,
-+#endif
-+ NULL_TREE, &args_size, &argvec[count].offset,
-+ &argvec[count].size, &alignment_pad);
-+
-+ if (argvec[count].reg == 0 || argvec[count].partial != 0
-+ || reg_parm_stack_space > 0)
-+ args_size.constant += argvec[count].size.constant;
-+
-+ FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree) 0, 1);
-+
-+ count++;
-+ }
-+
-+ for (; count < nargs; count++)
-+ {
-+ rtx val = va_arg (p, rtx);
-+ enum machine_mode mode = va_arg (p, enum machine_mode);
-+
-+ /* We cannot convert the arg value to the mode the library wants here;
-+ must do it earlier where we know the signedness of the arg. */
-+ if (mode == BLKmode
-+ || (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode))
-+ abort ();
-+
-+ /* On some machines, there's no way to pass a float to a library fcn.
-+ Pass it as a double instead. */
-+#ifdef LIBGCC_NEEDS_DOUBLE
-+ if (LIBGCC_NEEDS_DOUBLE && mode == SFmode)
-+ val = convert_modes (DFmode, SFmode, val, 0), mode = DFmode;
-+#endif
-+
-+ /* There's no need to call protect_from_queue, because
-+ either emit_move_insn or emit_push_insn will do that. */
-+
-+ /* Make sure it is a reasonable operand for a move or push insn. */
-+ if (GET_CODE (val) != REG && GET_CODE (val) != MEM
-+ && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val)))
-+ val = force_operand (val, NULL_RTX);
-+
-+#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
-+ if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, NULL_TREE, 1))
-+ {
-+ rtx slot;
-+ int must_copy = 1
-+#ifdef FUNCTION_ARG_CALLEE_COPIES
-+ && ! FUNCTION_ARG_CALLEE_COPIES (args_so_far, mode,
-+ NULL_TREE, 1)
-+#endif
-+ ;
-+
-+ /* loop.c won't look at CALL_INSN_FUNCTION_USAGE of const/pure
-+ functions, so we have to pretend this isn't such a function. */
-+ if (flags & ECF_LIBCALL_BLOCK)
-+ {
-+ rtx insns = get_insns ();
-+ end_sequence ();
-+ emit_insn (insns);
-+ }
-+ flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
-+
-+ /* If this was a CONST function, it is now PURE since
-+ it now reads memory. */
-+ if (flags & ECF_CONST)
-+ {
-+ flags &= ~ECF_CONST;
-+ flags |= ECF_PURE;
-+ }
-+
-+ if (GET_MODE (val) == MEM && ! must_copy)
-+ slot = val;
-+ else if (must_copy)
-+ {
-+ slot = assign_temp ((*lang_hooks.types.type_for_mode) (mode, 0),
-+ 0, 1, 1);
-+ emit_move_insn (slot, val);
-+ }
-+ else
-+ {
-+ tree type = (*lang_hooks.types.type_for_mode) (mode, 0);
-+
-+ slot = gen_rtx_MEM (mode,
-+ expand_expr (build1 (ADDR_EXPR,
-+ build_pointer_type
-+ (type),
-+ make_tree (type, val)),
-+ NULL_RTX, VOIDmode, 0));
-+ }
-+
-+ call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_USE (VOIDmode, slot),
-+ call_fusage);
-+ if (must_copy)
-+ call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_CLOBBER (VOIDmode,
-+ slot),
-+ call_fusage);
-+
-+ mode = Pmode;
-+ val = force_operand (XEXP (slot, 0), NULL_RTX);
-+ }
-+#endif
-+
-+ argvec[count].value = val;
-+ argvec[count].mode = mode;
-+
-+ argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
-+
-+#ifdef FUNCTION_ARG_PARTIAL_NREGS
-+ argvec[count].partial
-+ = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, NULL_TREE, 1);
-+#else
-+ argvec[count].partial = 0;
-+#endif
-+
-+ locate_and_pad_parm (mode, NULL_TREE,
-+#ifdef STACK_PARMS_IN_REG_PARM_AREA
-+ 1,
-+#else
-+ argvec[count].reg != 0,
-+#endif
-+ NULL_TREE, &args_size, &argvec[count].offset,
-+ &argvec[count].size, &alignment_pad);
-+
-+ if (argvec[count].size.var)
-+ abort ();
-+
-+ if (reg_parm_stack_space == 0 && argvec[count].partial)
-+ argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD;
-+
-+ if (argvec[count].reg == 0 || argvec[count].partial != 0
-+ || reg_parm_stack_space > 0)
-+ args_size.constant += argvec[count].size.constant;
-+
-+ FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
-+ }
-+
-+#ifdef FINAL_REG_PARM_STACK_SPACE
-+ reg_parm_stack_space = FINAL_REG_PARM_STACK_SPACE (args_size.constant,
-+ args_size.var);
-+#endif
-+ /* If this machine requires an external definition for library
-+ functions, write one out. */
-+ assemble_external_libcall (fun);
-+
-+ original_args_size = args_size;
-+ args_size.constant = (((args_size.constant
-+ + stack_pointer_delta
-+ + STACK_BYTES - 1)
-+ / STACK_BYTES
-+ * STACK_BYTES)
-+ - stack_pointer_delta);
-+
-+ args_size.constant = MAX (args_size.constant,
-+ reg_parm_stack_space);
-+
-+#ifndef OUTGOING_REG_PARM_STACK_SPACE
-+ args_size.constant -= reg_parm_stack_space;
-+#endif
-+
-+ if (args_size.constant > current_function_outgoing_args_size)
-+ current_function_outgoing_args_size = args_size.constant;
-+
-+ if (ACCUMULATE_OUTGOING_ARGS)
-+ {
-+ /* Since the stack pointer will never be pushed, it is possible for
-+ the evaluation of a parm to clobber something we have already
-+ written to the stack. Since most function calls on RISC machines
-+ do not use the stack, this is uncommon, but must work correctly.
-+
-+ Therefore, we save any area of the stack that was already written
-+ and that we are using. Here we set up to do this by making a new
-+ stack usage map from the old one.
-+
-+ Another approach might be to try to reorder the argument
-+ evaluations to avoid this conflicting stack usage. */
-+
-+ needed = args_size.constant;
-+
-+#ifndef OUTGOING_REG_PARM_STACK_SPACE
-+ /* Since we will be writing into the entire argument area, the
-+ map must be allocated for its entire size, not just the part that
-+ is the responsibility of the caller. */
-+ needed += reg_parm_stack_space;
-+#endif
-+
-+#ifdef ARGS_GROW_DOWNWARD
-+ highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
-+ needed + 1);
-+#else
-+ highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
-+ needed);
-+#endif
-+ stack_usage_map = (char *) alloca (highest_outgoing_arg_in_use);
-+
-+ if (initial_highest_arg_in_use)
-+ memcpy (stack_usage_map, initial_stack_usage_map,
-+ initial_highest_arg_in_use);
-+
-+ if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
-+ memset (&stack_usage_map[initial_highest_arg_in_use], 0,
-+ highest_outgoing_arg_in_use - initial_highest_arg_in_use);
-+ needed = 0;
-+
-+ /* We must be careful to use virtual regs before they're instantiated,
-+ and real regs afterwards. Loop optimization, for example, can create
-+ new libcalls after we've instantiated the virtual regs, and if we
-+ use virtuals anyway, they won't match the rtl patterns. */
-+
-+ if (virtuals_instantiated)
-+ argblock = plus_constant (stack_pointer_rtx, STACK_POINTER_OFFSET);
-+ else
-+ argblock = virtual_outgoing_args_rtx;
-+ }
-+ else
-+ {
-+ if (!PUSH_ARGS)
-+ argblock = push_block (GEN_INT (args_size.constant), 0, 0);
-+ }
-+
-+ /* If we push args individually in reverse order, perform stack alignment
-+ before the first push (the last arg). */
-+ if (argblock == 0 && PUSH_ARGS_REVERSED)
-+ anti_adjust_stack (GEN_INT (args_size.constant
-+ - original_args_size.constant));
-+
-+ if (PUSH_ARGS_REVERSED)
-+ {
-+ inc = -1;
-+ argnum = nargs - 1;
-+ }
-+ else
-+ {
-+ inc = 1;
-+ argnum = 0;
-+ }
-+
-+#ifdef REG_PARM_STACK_SPACE
-+ if (ACCUMULATE_OUTGOING_ARGS)
-+ {
-+ /* The argument list is the property of the called routine and it
-+ may clobber it. If the fixed area has been used for previous
-+ parameters, we must save and restore it.
-+
-+ Here we compute the boundary of the that needs to be saved, if any. */
-+
-+#ifdef ARGS_GROW_DOWNWARD
-+ for (count = 0; count < reg_parm_stack_space + 1; count++)
-+#else
-+ for (count = 0; count < reg_parm_stack_space; count++)
-+#endif
-+ {
-+ if (count >= highest_outgoing_arg_in_use
-+ || stack_usage_map[count] == 0)
-+ continue;
-+
-+ if (low_to_save == -1)
-+ low_to_save = count;
-+
-+ high_to_save = count;
-+ }
-+
-+ if (low_to_save >= 0)
-+ {
-+ int num_to_save = high_to_save - low_to_save + 1;
-+ enum machine_mode save_mode
-+ = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
-+ rtx stack_area;
-+
-+ /* If we don't have the required alignment, must do this in BLKmode. */
-+ if ((low_to_save & (MIN (GET_MODE_SIZE (save_mode),
-+ BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
-+ save_mode = BLKmode;
-+
-+#ifdef ARGS_GROW_DOWNWARD
-+ stack_area = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ plus_constant (argblock,
-+ -high_to_save)));
-+#else
-+ stack_area = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ plus_constant (argblock,
-+ low_to_save)));
-+#endif
-+ if (save_mode == BLKmode)
-+ {
-+ save_area = assign_stack_temp (BLKmode, num_to_save, 0);
-+ set_mem_align (save_area, PARM_BOUNDARY);
-+ emit_block_move (save_area, stack_area, GEN_INT (num_to_save),
-+ BLOCK_OP_CALL_PARM);
-+ }
-+ else
-+ {
-+ save_area = gen_reg_rtx (save_mode);
-+ emit_move_insn (save_area, stack_area);
-+ }
-+ }
-+ }
-+#endif
-+
-+ /* Push the args that need to be pushed. */
-+
-+ /* ARGNUM indexes the ARGVEC array in the order in which the arguments
-+ are to be pushed. */
-+ for (count = 0; count < nargs; count++, argnum += inc)
-+ {
-+ enum machine_mode mode = argvec[argnum].mode;
-+ rtx val = argvec[argnum].value;
-+ rtx reg = argvec[argnum].reg;
-+ int partial = argvec[argnum].partial;
-+ int lower_bound = 0, upper_bound = 0, i;
-+
-+ if (! (reg != 0 && partial == 0))
-+ {
-+ if (ACCUMULATE_OUTGOING_ARGS)
-+ {
-+ /* If this is being stored into a pre-allocated, fixed-size,
-+ stack area, save any previous data at that location. */
-+
-+#ifdef ARGS_GROW_DOWNWARD
-+ /* stack_slot is negative, but we want to index stack_usage_map
-+ with positive values. */
-+ upper_bound = -argvec[argnum].offset.constant + 1;
-+ lower_bound = upper_bound - argvec[argnum].size.constant;
-+#else
-+ lower_bound = argvec[argnum].offset.constant;
-+ upper_bound = lower_bound + argvec[argnum].size.constant;
-+#endif
-+
-+ for (i = lower_bound; i < upper_bound; i++)
-+ if (stack_usage_map[i]
-+ /* Don't store things in the fixed argument area at this
-+ point; it has already been saved. */
-+ && i > reg_parm_stack_space)
-+ break;
-+
-+ if (i != upper_bound)
-+ {
-+ /* We need to make a save area. See what mode we can make
-+ it. */
-+ enum machine_mode save_mode
-+ = mode_for_size (argvec[argnum].size.constant
-+ * BITS_PER_UNIT,
-+ MODE_INT, 1);
-+ rtx stack_area
-+ = gen_rtx_MEM
-+ (save_mode,
-+ memory_address
-+ (save_mode,
-+ plus_constant (argblock,
-+ argvec[argnum].offset.constant)));
-+ argvec[argnum].save_area = gen_reg_rtx (save_mode);
-+
-+ emit_move_insn (argvec[argnum].save_area, stack_area);
-+ }
-+ }
-+
-+ emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY,
-+ partial, reg, 0, argblock,
-+ GEN_INT (argvec[argnum].offset.constant),
-+ reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad));
-+
-+ /* Now mark the segment we just used. */
-+ if (ACCUMULATE_OUTGOING_ARGS)
-+ for (i = lower_bound; i < upper_bound; i++)
-+ stack_usage_map[i] = 1;
-+
-+ NO_DEFER_POP;
-+ }
-+ }
-+
-+ /* If we pushed args in forward order, perform stack alignment
-+ after pushing the last arg. */
-+ if (argblock == 0 && !PUSH_ARGS_REVERSED)
-+ anti_adjust_stack (GEN_INT (args_size.constant
-+ - original_args_size.constant));
-+
-+ if (PUSH_ARGS_REVERSED)
-+ argnum = nargs - 1;
-+ else
-+ argnum = 0;
-+
-+ fun = prepare_call_address (fun, NULL_TREE, &call_fusage, 0, 0);
-+
-+ /* Now load any reg parms into their regs. */
-+
-+ /* ARGNUM indexes the ARGVEC array in the order in which the arguments
-+ are to be pushed. */
-+ for (count = 0; count < nargs; count++, argnum += inc)
-+ {
-+ rtx val = argvec[argnum].value;
-+ rtx reg = argvec[argnum].reg;
-+ int partial = argvec[argnum].partial;
-+
-+ /* Handle calls that pass values in multiple non-contiguous
-+ locations. The PA64 has examples of this for library calls. */
-+ if (reg != 0 && GET_CODE (reg) == PARALLEL)
-+ emit_group_load (reg, val, GET_MODE_SIZE (GET_MODE (val)));
-+ else if (reg != 0 && partial == 0)
-+ emit_move_insn (reg, val);
-+
-+ NO_DEFER_POP;
-+ }
-+
-+ /* Any regs containing parms remain in use through the call. */
-+ for (count = 0; count < nargs; count++)
-+ {
-+ rtx reg = argvec[count].reg;
-+ if (reg != 0 && GET_CODE (reg) == PARALLEL)
-+ use_group_regs (&call_fusage, reg);
-+ else if (reg != 0)
-+ use_reg (&call_fusage, reg);
-+ }
-+
-+ /* Pass the function the address in which to return a structure value. */
-+ if (mem_value != 0 && struct_value_rtx != 0 && ! pcc_struct_value)
-+ {
-+ emit_move_insn (struct_value_rtx,
-+ force_reg (Pmode,
-+ force_operand (XEXP (mem_value, 0),
-+ NULL_RTX)));
-+ if (GET_CODE (struct_value_rtx) == REG)
-+ use_reg (&call_fusage, struct_value_rtx);
-+ }
-+
-+ /* Don't allow popping to be deferred, since then
-+ cse'ing of library calls could delete a call and leave the pop. */
-+ NO_DEFER_POP;
-+ valreg = (mem_value == 0 && outmode != VOIDmode
-+ ? hard_libcall_value (outmode) : NULL_RTX);
-+
-+ /* Stack must be properly aligned now. */
-+ if (stack_pointer_delta & (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1))
-+ abort ();
-+
-+ before_call = get_last_insn ();
-+
-+ /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
-+ will set inhibit_defer_pop to that value. */
-+ /* The return type is needed to decide how many bytes the function pops.
-+ Signedness plays no role in that, so for simplicity, we pretend it's
-+ always signed. We also assume that the list of arguments passed has
-+ no impact, so we pretend it is unknown. */
-+
-+ emit_call_1 (fun,
-+ get_identifier (XSTR (orgfun, 0)),
-+ build_function_type (tfom, NULL_TREE),
-+ original_args_size.constant, args_size.constant,
-+ struct_value_size,
-+ FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
-+ valreg,
-+ old_inhibit_defer_pop + 1, call_fusage, flags, & args_so_far);
-+
-+ /* For calls to `setjmp', etc., inform flow.c it should complain
-+ if nonvolatile values are live. For functions that cannot return,
-+ inform flow that control does not fall through. */
-+
-+ if (flags & (ECF_NORETURN | ECF_LONGJMP))
-+ {
-+ /* The barrier note must be emitted
-+ immediately after the CALL_INSN. Some ports emit more than
-+ just a CALL_INSN above, so we must search for it here. */
-+
-+ rtx last = get_last_insn ();
-+ while (GET_CODE (last) != CALL_INSN)
-+ {
-+ last = PREV_INSN (last);
-+ /* There was no CALL_INSN? */
-+ if (last == before_call)
-+ abort ();
-+ }
-+
-+ emit_barrier_after (last);
-+ }
-+
-+ /* Now restore inhibit_defer_pop to its actual original value. */
-+ OK_DEFER_POP;
-+
-+ /* If call is cse'able, make appropriate pair of reg-notes around it.
-+ Test valreg so we don't crash; may safely ignore `const'
-+ if return type is void. Disable for PARALLEL return values, because
-+ we have no way to move such values into a pseudo register. */
-+ if (flags & ECF_LIBCALL_BLOCK)
-+ {
-+ rtx insns;
-+
-+ if (valreg == 0)
-+ {
-+ insns = get_insns ();
-+ end_sequence ();
-+ emit_insn (insns);
-+ }
-+ else
-+ {
-+ rtx note = 0;
-+ rtx temp;
-+ int i;
-+
-+ if (GET_CODE (valreg) == PARALLEL)
-+ {
-+ temp = gen_reg_rtx (outmode);
-+ emit_group_store (temp, valreg, outmode);
-+ valreg = temp;
-+ }
-+
-+ temp = gen_reg_rtx (GET_MODE (valreg));
-+
-+ /* Construct an "equal form" for the value which mentions all the
-+ arguments in order as well as the function name. */
-+ for (i = 0; i < nargs; i++)
-+ note = gen_rtx_EXPR_LIST (VOIDmode, argvec[i].value, note);
-+ note = gen_rtx_EXPR_LIST (VOIDmode, fun, note);
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ if (flags & ECF_PURE)
-+ note = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_USE (VOIDmode,
-+ gen_rtx_MEM (BLKmode,
-+ gen_rtx_SCRATCH (VOIDmode))),
-+ note);
-+
-+ emit_libcall_block (insns, temp, valreg, note);
-+
-+ valreg = temp;
-+ }
-+ }
-+ pop_temp_slots ();
-+
-+ /* Copy the value to the right place. */
-+ if (outmode != VOIDmode && retval)
-+ {
-+ if (mem_value)
-+ {
-+ if (value == 0)
-+ value = mem_value;
-+ if (value != mem_value)
-+ emit_move_insn (value, mem_value);
-+ }
-+ else if (GET_CODE (valreg) == PARALLEL)
-+ {
-+ if (value == 0)
-+ value = gen_reg_rtx (outmode);
-+ emit_group_store (value, valreg, outmode);
-+ }
-+ else if (value != 0)
-+ emit_move_insn (value, valreg);
-+ else
-+ value = valreg;
-+ }
-+
-+ if (ACCUMULATE_OUTGOING_ARGS)
-+ {
-+#ifdef REG_PARM_STACK_SPACE
-+ if (save_area)
-+ {
-+ enum machine_mode save_mode = GET_MODE (save_area);
-+#ifdef ARGS_GROW_DOWNWARD
-+ rtx stack_area
-+ = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ plus_constant (argblock,
-+ - high_to_save)));
-+#else
-+ rtx stack_area
-+ = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ plus_constant (argblock, low_to_save)));
-+#endif
-+
-+ set_mem_align (stack_area, PARM_BOUNDARY);
-+ if (save_mode != BLKmode)
-+ emit_move_insn (stack_area, save_area);
-+ else
-+ emit_block_move (stack_area, save_area,
-+ GEN_INT (high_to_save - low_to_save + 1),
-+ BLOCK_OP_CALL_PARM);
-+ }
-+#endif
-+
-+ /* If we saved any argument areas, restore them. */
-+ for (count = 0; count < nargs; count++)
-+ if (argvec[count].save_area)
-+ {
-+ enum machine_mode save_mode = GET_MODE (argvec[count].save_area);
-+ rtx stack_area
-+ = gen_rtx_MEM (save_mode,
-+ memory_address
-+ (save_mode,
-+ plus_constant (argblock,
-+ argvec[count].offset.constant)));
-+
-+ emit_move_insn (stack_area, argvec[count].save_area);
-+ }
-+
-+ highest_outgoing_arg_in_use = initial_highest_arg_in_use;
-+ stack_usage_map = initial_stack_usage_map;
-+ }
-+
-+ return value;
-+
-+}
-+\f
-+/* Output a library call to function FUN (a SYMBOL_REF rtx)
-+ (emitting the queue unless NO_QUEUE is nonzero),
-+ for a value of mode OUTMODE,
-+ with NARGS different arguments, passed as alternating rtx values
-+ and machine_modes to convert them to.
-+ The rtx values should have been passed through protect_from_queue already.
-+
-+ FN_TYPE should be LCT_NORMAL for `normal' calls, LCT_CONST for `const'
-+ calls, LCT_PURE for `pure' calls, LCT_CONST_MAKE_BLOCK for `const' calls
-+ which should be enclosed in REG_LIBCALL/REG_RETVAL notes,
-+ LCT_PURE_MAKE_BLOCK for `purep' calls which should be enclosed in
-+ REG_LIBCALL/REG_RETVAL notes with extra (use (memory (scratch)),
-+ or other LCT_ value for other types of library calls. */
-+
-+void
-+emit_library_call VPARAMS((rtx orgfun, enum libcall_type fn_type,
-+ enum machine_mode outmode, int nargs, ...))
-+{
-+ VA_OPEN (p, nargs);
-+ VA_FIXEDARG (p, rtx, orgfun);
-+ VA_FIXEDARG (p, int, fn_type);
-+ VA_FIXEDARG (p, enum machine_mode, outmode);
-+ VA_FIXEDARG (p, int, nargs);
-+
-+ emit_library_call_value_1 (0, orgfun, NULL_RTX, fn_type, outmode, nargs, p);
-+
-+ VA_CLOSE (p);
-+}
-+\f
-+/* Like emit_library_call except that an extra argument, VALUE,
-+ comes second and says where to store the result.
-+ (If VALUE is zero, this function chooses a convenient way
-+ to return the value.
-+
-+ This function returns an rtx for where the value is to be found.
-+ If VALUE is nonzero, VALUE is returned. */
-+
-+rtx
-+emit_library_call_value VPARAMS((rtx orgfun, rtx value,
-+ enum libcall_type fn_type,
-+ enum machine_mode outmode, int nargs, ...))
-+{
-+ rtx result;
-+
-+ VA_OPEN (p, nargs);
-+ VA_FIXEDARG (p, rtx, orgfun);
-+ VA_FIXEDARG (p, rtx, value);
-+ VA_FIXEDARG (p, int, fn_type);
-+ VA_FIXEDARG (p, enum machine_mode, outmode);
-+ VA_FIXEDARG (p, int, nargs);
-+
-+ result = emit_library_call_value_1 (1, orgfun, value, fn_type, outmode,
-+ nargs, p);
-+
-+ VA_CLOSE (p);
-+
-+ return result;
-+}
-+\f
-+/* Store a single argument for a function call
-+ into the register or memory area where it must be passed.
-+ *ARG describes the argument value and where to pass it.
-+
-+ ARGBLOCK is the address of the stack-block for all the arguments,
-+ or 0 on a machine where arguments are pushed individually.
-+
-+ MAY_BE_ALLOCA nonzero says this could be a call to `alloca'
-+ so must be careful about how the stack is used.
-+
-+ VARIABLE_SIZE nonzero says that this was a variable-sized outgoing
-+ argument stack. This is used if ACCUMULATE_OUTGOING_ARGS to indicate
-+ that we need not worry about saving and restoring the stack.
-+
-+ FNDECL is the declaration of the function we are calling.
-+
-+ Return nonzero if this arg should cause sibcall failure,
-+ zero otherwise. */
-+
-+static int
-+store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
-+ struct arg_data *arg;
-+ rtx argblock;
-+ int flags;
-+ int variable_size ATTRIBUTE_UNUSED;
-+ int reg_parm_stack_space;
-+{
-+ tree pval = arg->tree_value;
-+ rtx reg = 0;
-+ int partial = 0;
-+ int used = 0;
-+ int i, lower_bound = 0, upper_bound = 0;
-+ int sibcall_failure = 0;
-+
-+ if (TREE_CODE (pval) == ERROR_MARK)
-+ return 1;
-+
-+ /* Push a new temporary level for any temporaries we make for
-+ this argument. */
-+ push_temp_slots ();
-+
-+ if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL))
-+ {
-+ /* If this is being stored into a pre-allocated, fixed-size, stack area,
-+ save any previous data at that location. */
-+ if (argblock && ! variable_size && arg->stack)
-+ {
-+#ifdef ARGS_GROW_DOWNWARD
-+ /* stack_slot is negative, but we want to index stack_usage_map
-+ with positive values. */
-+ if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS)
-+ upper_bound = -INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)) + 1;
-+ else
-+ upper_bound = 0;
-+
-+ lower_bound = upper_bound - arg->size.constant;
-+#else
-+ if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS)
-+ lower_bound = INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1));
-+ else
-+ lower_bound = 0;
-+
-+ upper_bound = lower_bound + arg->size.constant;
-+#endif
-+
-+ for (i = lower_bound; i < upper_bound; i++)
-+ if (stack_usage_map[i]
-+ /* Don't store things in the fixed argument area at this point;
-+ it has already been saved. */
-+ && i > reg_parm_stack_space)
-+ break;
-+
-+ if (i != upper_bound)
-+ {
-+ /* We need to make a save area. See what mode we can make it. */
-+ enum machine_mode save_mode
-+ = mode_for_size (arg->size.constant * BITS_PER_UNIT, MODE_INT, 1);
-+ rtx stack_area
-+ = gen_rtx_MEM (save_mode,
-+ memory_address (save_mode,
-+ XEXP (arg->stack_slot, 0)));
-+
-+ if (save_mode == BLKmode)
-+ {
-+ tree ot = TREE_TYPE (arg->tree_value);
-+ tree nt = build_qualified_type (ot, (TYPE_QUALS (ot)
-+ | TYPE_QUAL_CONST));
-+
-+ arg->save_area = assign_temp (nt, 0, 1, 1);
-+ preserve_temp_slots (arg->save_area);
-+ emit_block_move (validize_mem (arg->save_area), stack_area,
-+ expr_size (arg->tree_value),
-+ BLOCK_OP_CALL_PARM);
-+ }
-+ else
-+ {
-+ arg->save_area = gen_reg_rtx (save_mode);
-+ emit_move_insn (arg->save_area, stack_area);
-+ }
-+ }
-+ }
-+ }
-+
-+ /* If this isn't going to be placed on both the stack and in registers,
-+ set up the register and number of words. */
-+ if (! arg->pass_on_stack)
-+ {
-+ if (flags & ECF_SIBCALL)
-+ reg = arg->tail_call_reg;
-+ else
-+ reg = arg->reg;
-+ partial = arg->partial;
-+ }
-+
-+ if (reg != 0 && partial == 0)
-+ /* Being passed entirely in a register. We shouldn't be called in
-+ this case. */
-+ abort ();
-+
-+ /* If this arg needs special alignment, don't load the registers
-+ here. */
-+ if (arg->n_aligned_regs != 0)
-+ reg = 0;
-+
-+ /* If this is being passed partially in a register, we can't evaluate
-+ it directly into its stack slot. Otherwise, we can. */
-+ if (arg->value == 0)
-+ {
-+ /* stack_arg_under_construction is nonzero if a function argument is
-+ being evaluated directly into the outgoing argument list and
-+ expand_call must take special action to preserve the argument list
-+ if it is called recursively.
-+
-+ For scalar function arguments stack_usage_map is sufficient to
-+ determine which stack slots must be saved and restored. Scalar
-+ arguments in general have pass_on_stack == 0.
-+
-+ If this argument is initialized by a function which takes the
-+ address of the argument (a C++ constructor or a C function
-+ returning a BLKmode structure), then stack_usage_map is
-+ insufficient and expand_call must push the stack around the
-+ function call. Such arguments have pass_on_stack == 1.
-+
-+ Note that it is always safe to set stack_arg_under_construction,
-+ but this generates suboptimal code if set when not needed. */
-+
-+ if (arg->pass_on_stack)
-+ stack_arg_under_construction++;
-+
-+ arg->value = expand_expr (pval,
-+ (partial
-+ || TYPE_MODE (TREE_TYPE (pval)) != arg->mode)
-+ ? NULL_RTX : arg->stack,
-+ VOIDmode, EXPAND_STACK_PARM);
-+
-+ /* If we are promoting object (or for any other reason) the mode
-+ doesn't agree, convert the mode. */
-+
-+ if (arg->mode != TYPE_MODE (TREE_TYPE (pval)))
-+ arg->value = convert_modes (arg->mode, TYPE_MODE (TREE_TYPE (pval)),
-+ arg->value, arg->unsignedp);
-+
-+ if (arg->pass_on_stack)
-+ stack_arg_under_construction--;
-+ }
-+
-+ /* Don't allow anything left on stack from computation
-+ of argument to alloca. */
-+ if (flags & ECF_MAY_BE_ALLOCA)
-+ do_pending_stack_adjust ();
-+
-+ if (arg->value == arg->stack)
-+ /* If the value is already in the stack slot, we are done. */
-+ ;
-+ else if (arg->mode != BLKmode)
-+ {
-+ int size;
-+
-+ /* Argument is a scalar, not entirely passed in registers.
-+ (If part is passed in registers, arg->partial says how much
-+ and emit_push_insn will take care of putting it there.)
-+
-+ Push it, and if its size is less than the
-+ amount of space allocated to it,
-+ also bump stack pointer by the additional space.
-+ Note that in C the default argument promotions
-+ will prevent such mismatches. */
-+
-+ size = GET_MODE_SIZE (arg->mode);
-+ /* Compute how much space the push instruction will push.
-+ On many machines, pushing a byte will advance the stack
-+ pointer by a halfword. */
-+#ifdef PUSH_ROUNDING
-+ size = PUSH_ROUNDING (size);
-+#endif
-+ used = size;
-+
-+ /* Compute how much space the argument should get:
-+ round up to a multiple of the alignment for arguments. */
-+ if (none != FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)))
-+ used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
-+ / (PARM_BOUNDARY / BITS_PER_UNIT))
-+ * (PARM_BOUNDARY / BITS_PER_UNIT));
-+
-+ /* This isn't already where we want it on the stack, so put it there.
-+ This can either be done with push or copy insns. */
-+ emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX,
-+ PARM_BOUNDARY, partial, reg, used - size, argblock,
-+ ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
-+ ARGS_SIZE_RTX (arg->alignment_pad));
-+
-+ /* Unless this is a partially-in-register argument, the argument is now
-+ in the stack. */
-+ if (partial == 0)
-+ arg->value = arg->stack;
-+ }
-+ else
-+ {
-+ /* BLKmode, at least partly to be pushed. */
-+
-+ unsigned int parm_align;
-+ int excess;
-+ rtx size_rtx;
-+
-+ /* Pushing a nonscalar.
-+ If part is passed in registers, PARTIAL says how much
-+ and emit_push_insn will take care of putting it there. */
-+
-+ /* Round its size up to a multiple
-+ of the allocation unit for arguments. */
-+
-+ if (arg->size.var != 0)
-+ {
-+ excess = 0;
-+ size_rtx = ARGS_SIZE_RTX (arg->size);
-+ }
-+ else
-+ {
-+ /* PUSH_ROUNDING has no effect on us, because
-+ emit_push_insn for BLKmode is careful to avoid it. */
-+ excess = (arg->size.constant - int_size_in_bytes (TREE_TYPE (pval))
-+ + partial * UNITS_PER_WORD);
-+ size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)),
-+ NULL_RTX, TYPE_MODE (sizetype), 0);
-+ }
-+
-+ /* Some types will require stricter alignment, which will be
-+ provided for elsewhere in argument layout. */
-+ parm_align = MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval)));
-+
-+ /* When an argument is padded down, the block is aligned to
-+ PARM_BOUNDARY, but the actual argument isn't. */
-+ if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
-+ {
-+ if (arg->size.var)
-+ parm_align = BITS_PER_UNIT;
-+ else if (excess)
-+ {
-+ unsigned int excess_align = (excess & -excess) * BITS_PER_UNIT;
-+ parm_align = MIN (parm_align, excess_align);
-+ }
-+ }
-+
-+ if ((flags & ECF_SIBCALL) && GET_CODE (arg->value) == MEM)
-+ {
-+ /* emit_push_insn might not work properly if arg->value and
-+ argblock + arg->offset areas overlap. */
-+ rtx x = arg->value;
-+ int i = 0;
-+
-+ if (XEXP (x, 0) == current_function_internal_arg_pointer
-+ || (GET_CODE (XEXP (x, 0)) == PLUS
-+ && XEXP (XEXP (x, 0), 0) ==
-+ current_function_internal_arg_pointer
-+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
-+ {
-+ if (XEXP (x, 0) != current_function_internal_arg_pointer)
-+ i = INTVAL (XEXP (XEXP (x, 0), 1));
-+
-+ /* expand_call should ensure this */
-+ if (arg->offset.var || GET_CODE (size_rtx) != CONST_INT)
-+ abort ();
-+
-+ if (arg->offset.constant > i)
-+ {
-+ if (arg->offset.constant < i + INTVAL (size_rtx))
-+ sibcall_failure = 1;
-+ }
-+ else if (arg->offset.constant < i)
-+ {
-+ if (i < arg->offset.constant + INTVAL (size_rtx))
-+ sibcall_failure = 1;
-+ }
-+ }
-+ }
-+
-+ emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
-+ parm_align, partial, reg, excess, argblock,
-+ ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space,
-+ ARGS_SIZE_RTX (arg->alignment_pad));
-+
-+ /* Unless this is a partially-in-register argument, the argument is now
-+ in the stack.
-+
-+ ??? Unlike the case above, in which we want the actual
-+ address of the data, so that we can load it directly into a
-+ register, here we want the address of the stack slot, so that
-+ it's properly aligned for word-by-word copying or something
-+ like that. It's not clear that this is always correct. */
-+ if (partial == 0)
-+ arg->value = arg->stack_slot;
-+ }
-+
-+ /* Mark all slots this store used. */
-+ if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL)
-+ && argblock && ! variable_size && arg->stack)
-+ for (i = lower_bound; i < upper_bound; i++)
-+ stack_usage_map[i] = 1;
-+
-+ /* Once we have pushed something, pops can't safely
-+ be deferred during the rest of the arguments. */
-+ NO_DEFER_POP;
-+
-+ /* ANSI doesn't require a sequence point here,
-+ but PCC has one, so this will avoid some problems. */
-+ emit_queue ();
-+
-+ /* Free any temporary slots made in processing this argument. Show
-+ that we might have taken the address of something and pushed that
-+ as an operand. */
-+ preserve_temp_slots (NULL_RTX);
-+ free_temp_slots ();
-+ pop_temp_slots ();
-+
-+ return sibcall_failure;
-+}
-diff -ruN gcc-3.3.1/gcc/combine.c gcc-3.3.1.pp/gcc/combine.c
---- gcc-3.3.1/gcc/combine.c 2003-03-24 11:37:32.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/combine.c 2003-09-05 11:58:59.000000000 +0000
-@@ -3859,7 +3859,17 @@
- rtx inner_op0 = XEXP (XEXP (x, 0), 1);
- rtx inner_op1 = XEXP (x, 1);
- rtx inner;
--
-+
-+#ifndef FRAME_GROWS_DOWNWARD
-+ if (flag_propolice_protection
-+ && code == PLUS
-+ && other == frame_pointer_rtx
-+ && GET_CODE (inner_op0) == CONST_INT
-+ && GET_CODE (inner_op1) == CONST_INT
-+ && INTVAL (inner_op0) > 0
-+ && INTVAL (inner_op0) + INTVAL (inner_op1) <= 0)
-+ return x;
-+#endif
- /* Make sure we pass the constant operand if any as the second
- one if this is a commutative operation. */
- if (CONSTANT_P (inner_op0) && GET_RTX_CLASS (code) == 'c')
-@@ -4272,6 +4282,11 @@
- they are now checked elsewhere. */
- if (GET_CODE (XEXP (x, 0)) == PLUS
- && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
-+#ifndef FRAME_GROWS_DOWNWARD
-+ if (! (flag_propolice_protection
-+ && XEXP (XEXP (x, 0), 0) == frame_pointer_rtx
-+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
-+#endif
- return gen_binary (PLUS, mode,
- gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0),
- XEXP (x, 1)),
-@@ -4400,7 +4415,10 @@
-
- /* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for
- integers. */
-- if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode))
-+ if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode)
-+ && (! (flag_propolice_protection
-+ && XEXP (XEXP (x, 1), 0) == frame_pointer_rtx
-+ && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)))
- return gen_binary (MINUS, mode,
- gen_binary (MINUS, mode, XEXP (x, 0),
- XEXP (XEXP (x, 1), 0)),
-diff -ruN gcc-3.3.1/gcc/config/t-linux gcc-3.3.1.pp/gcc/config/t-linux
---- gcc-3.3.1/gcc/config/t-linux 2003-06-04 16:56:11.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/config/t-linux 2003-09-05 11:58:59.000000000 +0000
-@@ -4,7 +4,7 @@
- # Compile crtbeginS.o and crtendS.o with pic.
- CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
- # Compile libgcc2.a with pic.
--TARGET_LIBGCC2_CFLAGS = -fPIC
-+TARGET_LIBGCC2_CFLAGS = -fPIC -DHAVE_SYSLOG
-
- # Override t-slibgcc-elf-ver to export some libgcc symbols with
- # the symbol versions that glibc used.
-diff -ruN gcc-3.3.1/gcc/cse.c gcc-3.3.1.pp/gcc/cse.c
---- gcc-3.3.1/gcc/cse.c 2003-04-29 19:16:40.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/cse.c 2003-09-05 11:58:59.000000000 +0000
-@@ -4288,7 +4288,14 @@
-
- if (new_const == 0)
- break;
--
-+#ifndef FRAME_GROWS_DOWNWARD
-+ if (flag_propolice_protection
-+ && GET_CODE (y) == PLUS
-+ && XEXP (y, 0) == frame_pointer_rtx
-+ && INTVAL (inner_const) > 0
-+ && INTVAL (new_const) <= 0)
-+ break;
-+#endif
- /* If we are associating shift operations, don't let this
- produce a shift of the size of the object or larger.
- This could occur when we follow a sign-extend by a right
-@@ -4823,6 +4830,13 @@
- if (SET_DEST (x) == pc_rtx
- && GET_CODE (SET_SRC (x)) == LABEL_REF)
- ;
-+ /* cut the reg propagation of stack-protected argument */
-+ else if (x->volatil) {
-+ rtx x1 = SET_DEST (x);
-+ if (GET_CODE (x1) == SUBREG && GET_CODE (SUBREG_REG (x1)) == REG)
-+ x1 = SUBREG_REG (x1);
-+ make_new_qty (REGNO (x1), GET_MODE (x1));
-+ }
-
- /* Don't count call-insns, (set (reg 0) (call ...)), as a set.
- The hard function value register is used only once, to copy to
-diff -ruN gcc-3.3.1/gcc/explow.c gcc-3.3.1.pp/gcc/explow.c
---- gcc-3.3.1/gcc/explow.c 2003-04-07 22:58:12.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/explow.c 2003-09-05 11:58:59.000000000 +0000
-@@ -86,7 +86,8 @@
- rtx tem;
- int all_constant = 0;
-
-- if (c == 0)
-+ if (c == 0
-+ && !(flag_propolice_protection && x == virtual_stack_vars_rtx))
- return x;
-
- restart:
-@@ -187,7 +188,8 @@
- break;
- }
-
-- if (c != 0)
-+ if (c != 0
-+ || (flag_propolice_protection && x == virtual_stack_vars_rtx))
- x = gen_rtx_PLUS (mode, x, GEN_INT (c));
-
- if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
-@@ -531,6 +533,21 @@
- in certain cases. This is not necessary since the code
- below can handle all possible cases, but machine-dependent
- transformations can make better code. */
-+ if (flag_propolice_protection)
-+ {
-+#define FRAMEADDR_P(X) (GET_CODE (X) == PLUS \
-+ && XEXP (X, 0) == virtual_stack_vars_rtx \
-+ && GET_CODE (XEXP (X, 1)) == CONST_INT)
-+ rtx y;
-+ if (FRAMEADDR_P (x)) goto win;
-+ for (y=x; y!=0 && GET_CODE (y)==PLUS; y = XEXP (y, 0))
-+ {
-+ if (FRAMEADDR_P (XEXP (y, 0)))
-+ XEXP (y, 0) = force_reg (GET_MODE (XEXP (y, 0)), XEXP (y, 0));
-+ if (FRAMEADDR_P (XEXP (y, 1)))
-+ XEXP (y, 1) = force_reg (GET_MODE (XEXP (y, 1)), XEXP (y, 1));
-+ }
-+ }
- LEGITIMIZE_ADDRESS (x, oldx, mode, win);
-
- /* PLUS and MULT can appear in special ways
-diff -ruN gcc-3.3.1/gcc/expr.c gcc-3.3.1.pp/gcc/expr.c
---- gcc-3.3.1/gcc/expr.c 2003-07-24 19:11:20.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/expr.c 2003-09-05 11:58:59.000000000 +0000
-@@ -45,6 +45,7 @@
- #include "langhooks.h"
- #include "intl.h"
- #include "tm_p.h"
-+#include "protector.h"
-
- /* Decide whether a function's arguments should be processed
- from first to last or from last to first.
-@@ -1518,7 +1519,7 @@
-
- if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
- {
-- data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
-+ data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len-GET_MODE_SIZE (mode)));
- data.autinc_from = 1;
- data.explicit_inc_from = -1;
- }
-@@ -1532,7 +1533,7 @@
- data.from_addr = copy_addr_to_reg (from_addr);
- if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
- {
-- data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
-+ data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len-GET_MODE_SIZE (mode)));
- data.autinc_to = 1;
- data.explicit_inc_to = -1;
- }
-@@ -1649,11 +1650,13 @@
- from1 = adjust_address (data->from, mode, data->offset);
-
- if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
-- emit_insn (gen_add2_insn (data->to_addr,
-- GEN_INT (-(HOST_WIDE_INT)size)));
-+ if (data->explicit_inc_to < -1)
-+ emit_insn (gen_add2_insn (data->to_addr,
-+ GEN_INT (-(HOST_WIDE_INT)size)));
- if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
-- emit_insn (gen_add2_insn (data->from_addr,
-- GEN_INT (-(HOST_WIDE_INT)size)));
-+ if (data->explicit_inc_from < -1)
-+ emit_insn (gen_add2_insn (data->from_addr,
-+ GEN_INT (-(HOST_WIDE_INT)size)));
-
- if (data->to)
- emit_insn ((*genfun) (to1, from1));
-@@ -2826,7 +2829,7 @@
-
- if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
- {
-- data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
-+ data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len-GET_MODE_SIZE (mode)));
- data->autinc_to = 1;
- data->explicit_inc_to = -1;
- }
-@@ -2897,8 +2900,9 @@
- to1 = adjust_address (data->to, mode, data->offset);
-
- if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
-- emit_insn (gen_add2_insn (data->to_addr,
-- GEN_INT (-(HOST_WIDE_INT) size)));
-+ if (data->explicit_inc_to < -1)
-+ emit_insn (gen_add2_insn (data->to_addr,
-+ GEN_INT (-(HOST_WIDE_INT) size)));
-
- cst = (*data->constfun) (data->constfundata, data->offset, mode);
- emit_insn ((*genfun) (to1, cst));
-@@ -5894,7 +5898,9 @@
- && GET_CODE (XEXP (value, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
- && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
-- && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
-+ && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER
-+ && (!flag_propolice_protection
-+ || XEXP (XEXP (value, 0), 0) != virtual_stack_vars_rtx))
- {
- rtx temp = expand_simple_binop (GET_MODE (value), code,
- XEXP (XEXP (value, 0), 0), op2,
-@@ -8070,7 +8076,8 @@
- /* If adding to a sum including a constant,
- associate it to put the constant outside. */
- if (GET_CODE (op1) == PLUS
-- && CONSTANT_P (XEXP (op1, 1)))
-+ && CONSTANT_P (XEXP (op1, 1))
-+ && !(flag_propolice_protection && (contains_fp (op0) || contains_fp (op1))))
- {
- rtx constant_term = const0_rtx;
-
-diff -ruN gcc-3.3.1/gcc/expr.c.orig gcc-3.3.1.pp/gcc/expr.c.orig
---- gcc-3.3.1/gcc/expr.c.orig 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/expr.c.orig 2003-07-24 19:11:20.000000000 +0000
-@@ -0,0 +1,11287 @@
-+/* Convert tree expression to rtl instructions, for GNU compiler.
-+ Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-+ 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-+
-+This file is part of GCC.
-+
-+GCC is free software; you can redistribute it and/or modify it under
-+the terms of the GNU General Public License as published by the Free
-+Software Foundation; either version 2, or (at your option) any later
-+version.
-+
-+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-+WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GCC; see the file COPYING. If not, write to the Free
-+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-+02111-1307, USA. */
-+
-+#include "config.h"
-+#include "system.h"
-+#include "machmode.h"
-+#include "real.h"
-+#include "rtl.h"
-+#include "tree.h"
-+#include "flags.h"
-+#include "regs.h"
-+#include "hard-reg-set.h"
-+#include "except.h"
-+#include "function.h"
-+#include "insn-config.h"
-+#include "insn-attr.h"
-+/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
-+#include "expr.h"
-+#include "optabs.h"
-+#include "libfuncs.h"
-+#include "recog.h"
-+#include "reload.h"
-+#include "output.h"
-+#include "typeclass.h"
-+#include "toplev.h"
-+#include "ggc.h"
-+#include "langhooks.h"
-+#include "intl.h"
-+#include "tm_p.h"
-+
-+/* Decide whether a function's arguments should be processed
-+ from first to last or from last to first.
-+
-+ They should if the stack and args grow in opposite directions, but
-+ only if we have push insns. */
-+
-+#ifdef PUSH_ROUNDING
-+
-+#ifndef PUSH_ARGS_REVERSED
-+#if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
-+#define PUSH_ARGS_REVERSED /* If it's last to first. */
-+#endif
-+#endif
-+
-+#endif
-+
-+#ifndef STACK_PUSH_CODE
-+#ifdef STACK_GROWS_DOWNWARD
-+#define STACK_PUSH_CODE PRE_DEC
-+#else
-+#define STACK_PUSH_CODE PRE_INC
-+#endif
-+#endif
-+
-+/* Assume that case vectors are not pc-relative. */
-+#ifndef CASE_VECTOR_PC_RELATIVE
-+#define CASE_VECTOR_PC_RELATIVE 0
-+#endif
-+
-+/* Convert defined/undefined to boolean. */
-+#ifdef TARGET_MEM_FUNCTIONS
-+#undef TARGET_MEM_FUNCTIONS
-+#define TARGET_MEM_FUNCTIONS 1
-+#else
-+#define TARGET_MEM_FUNCTIONS 0
-+#endif
-+
-+
-+/* If this is nonzero, we do not bother generating VOLATILE
-+ around volatile memory references, and we are willing to
-+ output indirect addresses. If cse is to follow, we reject
-+ indirect addresses so a useful potential cse is generated;
-+ if it is used only once, instruction combination will produce
-+ the same indirect address eventually. */
-+int cse_not_expected;
-+
-+/* Chain of pending expressions for PLACEHOLDER_EXPR to replace. */
-+static tree placeholder_list = 0;
-+
-+/* This structure is used by move_by_pieces to describe the move to
-+ be performed. */
-+struct move_by_pieces
-+{
-+ rtx to;
-+ rtx to_addr;
-+ int autinc_to;
-+ int explicit_inc_to;
-+ rtx from;
-+ rtx from_addr;
-+ int autinc_from;
-+ int explicit_inc_from;
-+ unsigned HOST_WIDE_INT len;
-+ HOST_WIDE_INT offset;
-+ int reverse;
-+};
-+
-+/* This structure is used by store_by_pieces to describe the clear to
-+ be performed. */
-+
-+struct store_by_pieces
-+{
-+ rtx to;
-+ rtx to_addr;
-+ int autinc_to;
-+ int explicit_inc_to;
-+ unsigned HOST_WIDE_INT len;
-+ HOST_WIDE_INT offset;
-+ rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
-+ PTR constfundata;
-+ int reverse;
-+};
-+
-+static rtx enqueue_insn PARAMS ((rtx, rtx));
-+static unsigned HOST_WIDE_INT move_by_pieces_ninsns
-+ PARAMS ((unsigned HOST_WIDE_INT,
-+ unsigned int));
-+static void move_by_pieces_1 PARAMS ((rtx (*) (rtx, ...), enum machine_mode,
-+ struct move_by_pieces *));
-+static bool block_move_libcall_safe_for_call_parm PARAMS ((void));
-+static bool emit_block_move_via_movstr PARAMS ((rtx, rtx, rtx, unsigned));
-+static rtx emit_block_move_via_libcall PARAMS ((rtx, rtx, rtx));
-+static tree emit_block_move_libcall_fn PARAMS ((int));
-+static void emit_block_move_via_loop PARAMS ((rtx, rtx, rtx, unsigned));
-+static rtx clear_by_pieces_1 PARAMS ((PTR, HOST_WIDE_INT,
-+ enum machine_mode));
-+static void clear_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
-+ unsigned int));
-+static void store_by_pieces_1 PARAMS ((struct store_by_pieces *,
-+ unsigned int));
-+static void store_by_pieces_2 PARAMS ((rtx (*) (rtx, ...),
-+ enum machine_mode,
-+ struct store_by_pieces *));
-+static bool clear_storage_via_clrstr PARAMS ((rtx, rtx, unsigned));
-+static rtx clear_storage_via_libcall PARAMS ((rtx, rtx));
-+static tree clear_storage_libcall_fn PARAMS ((int));
-+static rtx compress_float_constant PARAMS ((rtx, rtx));
-+static rtx get_subtarget PARAMS ((rtx));
-+static int is_zeros_p PARAMS ((tree));
-+static int mostly_zeros_p PARAMS ((tree));
-+static void store_constructor_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
-+ HOST_WIDE_INT, enum machine_mode,
-+ tree, tree, int, int));
-+static void store_constructor PARAMS ((tree, rtx, int, HOST_WIDE_INT));
-+static rtx store_field PARAMS ((rtx, HOST_WIDE_INT,
-+ HOST_WIDE_INT, enum machine_mode,
-+ tree, enum machine_mode, int, tree,
-+ int));
-+static rtx var_rtx PARAMS ((tree));
-+static HOST_WIDE_INT highest_pow2_factor PARAMS ((tree));
-+static HOST_WIDE_INT highest_pow2_factor_for_type PARAMS ((tree, tree));
-+static int is_aligning_offset PARAMS ((tree, tree));
-+static rtx expand_increment PARAMS ((tree, int, int));
-+static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
-+static void do_jump_by_parts_equality PARAMS ((tree, rtx, rtx));
-+static void do_compare_and_jump PARAMS ((tree, enum rtx_code, enum rtx_code,
-+ rtx, rtx));
-+static rtx do_store_flag PARAMS ((tree, rtx, enum machine_mode, int));
-+#ifdef PUSH_ROUNDING
-+static void emit_single_push_insn PARAMS ((enum machine_mode, rtx, tree));
-+#endif
-+static void do_tablejump PARAMS ((rtx, enum machine_mode, rtx, rtx, rtx));
-+static rtx const_vector_from_tree PARAMS ((tree));
-+
-+/* Record for each mode whether we can move a register directly to or
-+ from an object of that mode in memory. If we can't, we won't try
-+ to use that mode directly when accessing a field of that mode. */
-+
-+static char direct_load[NUM_MACHINE_MODES];
-+static char direct_store[NUM_MACHINE_MODES];
-+
-+/* Record for each mode whether we can float-extend from memory. */
-+
-+static bool float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
-+
-+/* If a memory-to-memory move would take MOVE_RATIO or more simple
-+ move-instruction sequences, we will do a movstr or libcall instead. */
-+
-+#ifndef MOVE_RATIO
-+#if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
-+#define MOVE_RATIO 2
-+#else
-+/* If we are optimizing for space (-Os), cut down the default move ratio. */
-+#define MOVE_RATIO (optimize_size ? 3 : 15)
-+#endif
-+#endif
-+
-+/* This macro is used to determine whether move_by_pieces should be called
-+ to perform a structure copy. */
-+#ifndef MOVE_BY_PIECES_P
-+#define MOVE_BY_PIECES_P(SIZE, ALIGN) \
-+ (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) MOVE_RATIO)
-+#endif
-+
-+/* If a clear memory operation would take CLEAR_RATIO or more simple
-+ move-instruction sequences, we will do a clrstr or libcall instead. */
-+
-+#ifndef CLEAR_RATIO
-+#if defined (HAVE_clrstrqi) || defined (HAVE_clrstrhi) || defined (HAVE_clrstrsi) || defined (HAVE_clrstrdi) || defined (HAVE_clrstrti)
-+#define CLEAR_RATIO 2
-+#else
-+/* If we are optimizing for space, cut down the default clear ratio. */
-+#define CLEAR_RATIO (optimize_size ? 3 : 15)
-+#endif
-+#endif
-+
-+/* This macro is used to determine whether clear_by_pieces should be
-+ called to clear storage. */
-+#ifndef CLEAR_BY_PIECES_P
-+#define CLEAR_BY_PIECES_P(SIZE, ALIGN) \
-+ (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) CLEAR_RATIO)
-+#endif
-+
-+/* This array records the insn_code of insns to perform block moves. */
-+enum insn_code movstr_optab[NUM_MACHINE_MODES];
-+
-+/* This array records the insn_code of insns to perform block clears. */
-+enum insn_code clrstr_optab[NUM_MACHINE_MODES];
-+
-+/* SLOW_UNALIGNED_ACCESS is nonzero if unaligned accesses are very slow. */
-+
-+#ifndef SLOW_UNALIGNED_ACCESS
-+#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
-+#endif
-+\f
-+/* This is run once per compilation to set up which modes can be used
-+ directly in memory and to initialize the block move optab. */
-+
-+void
-+init_expr_once ()
-+{
-+ rtx insn, pat;
-+ enum machine_mode mode;
-+ int num_clobbers;
-+ rtx mem, mem1;
-+ rtx reg;
-+
-+ /* Try indexing by frame ptr and try by stack ptr.
-+ It is known that on the Convex the stack ptr isn't a valid index.
-+ With luck, one or the other is valid on any machine. */
-+ mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
-+ mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
-+
-+ /* A scratch register we can modify in-place below to avoid
-+ useless RTL allocations. */
-+ reg = gen_rtx_REG (VOIDmode, -1);
-+
-+ insn = rtx_alloc (INSN);
-+ pat = gen_rtx_SET (0, NULL_RTX, NULL_RTX);
-+ PATTERN (insn) = pat;
-+
-+ for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
-+ mode = (enum machine_mode) ((int) mode + 1))
-+ {
-+ int regno;
-+
-+ direct_load[(int) mode] = direct_store[(int) mode] = 0;
-+ PUT_MODE (mem, mode);
-+ PUT_MODE (mem1, mode);
-+ PUT_MODE (reg, mode);
-+
-+ /* See if there is some register that can be used in this mode and
-+ directly loaded or stored from memory. */
-+
-+ if (mode != VOIDmode && mode != BLKmode)
-+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER
-+ && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0);
-+ regno++)
-+ {
-+ if (! HARD_REGNO_MODE_OK (regno, mode))
-+ continue;
-+
-+ REGNO (reg) = regno;
-+
-+ SET_SRC (pat) = mem;
-+ SET_DEST (pat) = reg;
-+ if (recog (pat, insn, &num_clobbers) >= 0)
-+ direct_load[(int) mode] = 1;
-+
-+ SET_SRC (pat) = mem1;
-+ SET_DEST (pat) = reg;
-+ if (recog (pat, insn, &num_clobbers) >= 0)
-+ direct_load[(int) mode] = 1;
-+
-+ SET_SRC (pat) = reg;
-+ SET_DEST (pat) = mem;
-+ if (recog (pat, insn, &num_clobbers) >= 0)
-+ direct_store[(int) mode] = 1;
-+
-+ SET_SRC (pat) = reg;
-+ SET_DEST (pat) = mem1;
-+ if (recog (pat, insn, &num_clobbers) >= 0)
-+ direct_store[(int) mode] = 1;
-+ }
-+ }
-+
-+ mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
-+
-+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
-+ mode = GET_MODE_WIDER_MODE (mode))
-+ {
-+ enum machine_mode srcmode;
-+ for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
-+ srcmode = GET_MODE_WIDER_MODE (srcmode))
-+ {
-+ enum insn_code ic;
-+
-+ ic = can_extend_p (mode, srcmode, 0);
-+ if (ic == CODE_FOR_nothing)
-+ continue;
-+
-+ PUT_MODE (mem, srcmode);
-+
-+ if ((*insn_data[ic].operand[1].predicate) (mem, srcmode))
-+ float_extend_from_mem[mode][srcmode] = true;
-+ }
-+ }
-+}
-+
-+/* This is run at the start of compiling a function. */
-+
-+void
-+init_expr ()
-+{
-+ cfun->expr = (struct expr_status *) ggc_alloc (sizeof (struct expr_status));
-+
-+ pending_chain = 0;
-+ pending_stack_adjust = 0;
-+ stack_pointer_delta = 0;
-+ inhibit_defer_pop = 0;
-+ saveregs_value = 0;
-+ apply_args_value = 0;
-+ forced_labels = 0;
-+}
-+
-+/* Small sanity check that the queue is empty at the end of a function. */
-+
-+void
-+finish_expr_for_function ()
-+{
-+ if (pending_chain)
-+ abort ();
-+}
-+\f
-+/* Manage the queue of increment instructions to be output
-+ for POSTINCREMENT_EXPR expressions, etc. */
-+
-+/* Queue up to increment (or change) VAR later. BODY says how:
-+ BODY should be the same thing you would pass to emit_insn
-+ to increment right away. It will go to emit_insn later on.
-+
-+ The value is a QUEUED expression to be used in place of VAR
-+ where you want to guarantee the pre-incrementation value of VAR. */
-+
-+static rtx
-+enqueue_insn (var, body)
-+ rtx var, body;
-+{
-+ pending_chain = gen_rtx_QUEUED (GET_MODE (var), var, NULL_RTX, NULL_RTX,
-+ body, pending_chain);
-+ return pending_chain;
-+}
-+
-+/* Use protect_from_queue to convert a QUEUED expression
-+ into something that you can put immediately into an instruction.
-+ If the queued incrementation has not happened yet,
-+ protect_from_queue returns the variable itself.
-+ If the incrementation has happened, protect_from_queue returns a temp
-+ that contains a copy of the old value of the variable.
-+
-+ Any time an rtx which might possibly be a QUEUED is to be put
-+ into an instruction, it must be passed through protect_from_queue first.
-+ QUEUED expressions are not meaningful in instructions.
-+
-+ Do not pass a value through protect_from_queue and then hold
-+ on to it for a while before putting it in an instruction!
-+ If the queue is flushed in between, incorrect code will result. */
-+
-+rtx
-+protect_from_queue (x, modify)
-+ rtx x;
-+ int modify;
-+{
-+ RTX_CODE code = GET_CODE (x);
-+
-+#if 0 /* A QUEUED can hang around after the queue is forced out. */
-+ /* Shortcut for most common case. */
-+ if (pending_chain == 0)
-+ return x;
-+#endif
-+
-+ if (code != QUEUED)
-+ {
-+ /* A special hack for read access to (MEM (QUEUED ...)) to facilitate
-+ use of autoincrement. Make a copy of the contents of the memory
-+ location rather than a copy of the address, but not if the value is
-+ of mode BLKmode. Don't modify X in place since it might be
-+ shared. */
-+ if (code == MEM && GET_MODE (x) != BLKmode
-+ && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
-+ {
-+ rtx y = XEXP (x, 0);
-+ rtx new = replace_equiv_address_nv (x, QUEUED_VAR (y));
-+
-+ if (QUEUED_INSN (y))
-+ {
-+ rtx temp = gen_reg_rtx (GET_MODE (x));
-+
-+ emit_insn_before (gen_move_insn (temp, new),
-+ QUEUED_INSN (y));
-+ return temp;
-+ }
-+
-+ /* Copy the address into a pseudo, so that the returned value
-+ remains correct across calls to emit_queue. */
-+ return replace_equiv_address (new, copy_to_reg (XEXP (new, 0)));
-+ }
-+
-+ /* Otherwise, recursively protect the subexpressions of all
-+ the kinds of rtx's that can contain a QUEUED. */
-+ if (code == MEM)
-+ {
-+ rtx tem = protect_from_queue (XEXP (x, 0), 0);
-+ if (tem != XEXP (x, 0))
-+ {
-+ x = copy_rtx (x);
-+ XEXP (x, 0) = tem;
-+ }
-+ }
-+ else if (code == PLUS || code == MULT)
-+ {
-+ rtx new0 = protect_from_queue (XEXP (x, 0), 0);
-+ rtx new1 = protect_from_queue (XEXP (x, 1), 0);
-+ if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
-+ {
-+ x = copy_rtx (x);
-+ XEXP (x, 0) = new0;
-+ XEXP (x, 1) = new1;
-+ }
-+ }
-+ return x;
-+ }
-+ /* If the increment has not happened, use the variable itself. Copy it
-+ into a new pseudo so that the value remains correct across calls to
-+ emit_queue. */
-+ if (QUEUED_INSN (x) == 0)
-+ return copy_to_reg (QUEUED_VAR (x));
-+ /* If the increment has happened and a pre-increment copy exists,
-+ use that copy. */
-+ if (QUEUED_COPY (x) != 0)
-+ return QUEUED_COPY (x);
-+ /* The increment has happened but we haven't set up a pre-increment copy.
-+ Set one up now, and use it. */
-+ QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
-+ emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
-+ QUEUED_INSN (x));
-+ return QUEUED_COPY (x);
-+}
-+
-+/* Return nonzero if X contains a QUEUED expression:
-+ if it contains anything that will be altered by a queued increment.
-+ We handle only combinations of MEM, PLUS, MINUS and MULT operators
-+ since memory addresses generally contain only those. */
-+
-+int
-+queued_subexp_p (x)
-+ rtx x;
-+{
-+ enum rtx_code code = GET_CODE (x);
-+ switch (code)
-+ {
-+ case QUEUED:
-+ return 1;
-+ case MEM:
-+ return queued_subexp_p (XEXP (x, 0));
-+ case MULT:
-+ case PLUS:
-+ case MINUS:
-+ return (queued_subexp_p (XEXP (x, 0))
-+ || queued_subexp_p (XEXP (x, 1)));
-+ default:
-+ return 0;
-+ }
-+}
-+
-+/* Perform all the pending incrementations. */
-+
-+void
-+emit_queue ()
-+{
-+ rtx p;
-+ while ((p = pending_chain))
-+ {
-+ rtx body = QUEUED_BODY (p);
-+
-+ switch (GET_CODE (body))
-+ {
-+ case INSN:
-+ case JUMP_INSN:
-+ case CALL_INSN:
-+ case CODE_LABEL:
-+ case BARRIER:
-+ case NOTE:
-+ QUEUED_INSN (p) = body;
-+ emit_insn (body);
-+ break;
-+
-+#ifdef ENABLE_CHECKING
-+ case SEQUENCE:
-+ abort ();
-+ break;
-+#endif
-+
-+ default:
-+ QUEUED_INSN (p) = emit_insn (body);
-+ break;
-+ }
-+
-+ pending_chain = QUEUED_NEXT (p);
-+ }
-+}
-+\f
-+/* Copy data from FROM to TO, where the machine modes are not the same.
-+ Both modes may be integer, or both may be floating.
-+ UNSIGNEDP should be nonzero if FROM is an unsigned type.
-+ This causes zero-extension instead of sign-extension. */
-+
-+void
-+convert_move (to, from, unsignedp)
-+ rtx to, from;
-+ int unsignedp;
-+{
-+ enum machine_mode to_mode = GET_MODE (to);
-+ enum machine_mode from_mode = GET_MODE (from);
-+ int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT;
-+ int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT;
-+ enum insn_code code;
-+ rtx libcall;
-+
-+ /* rtx code for making an equivalent value. */
-+ enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
-+ : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
-+
-+ to = protect_from_queue (to, 1);
-+ from = protect_from_queue (from, 0);
-+
-+ if (to_real != from_real)
-+ abort ();
-+
-+ /* If FROM is a SUBREG that indicates that we have already done at least
-+ the required extension, strip it. We don't handle such SUBREGs as
-+ TO here. */
-+
-+ if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from)
-+ && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from)))
-+ >= GET_MODE_SIZE (to_mode))
-+ && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp)
-+ from = gen_lowpart (to_mode, from), from_mode = to_mode;
-+
-+ if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to))
-+ abort ();
-+
-+ if (to_mode == from_mode
-+ || (from_mode == VOIDmode && CONSTANT_P (from)))
-+ {
-+ emit_move_insn (to, from);
-+ return;
-+ }
-+
-+ if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode))
-+ {
-+ if (GET_MODE_BITSIZE (from_mode) != GET_MODE_BITSIZE (to_mode))
-+ abort ();
-+
-+ if (VECTOR_MODE_P (to_mode))
-+ from = simplify_gen_subreg (to_mode, from, GET_MODE (from), 0);
-+ else
-+ to = simplify_gen_subreg (from_mode, to, GET_MODE (to), 0);
-+
-+ emit_move_insn (to, from);
-+ return;
-+ }
-+
-+ if (to_real != from_real)
-+ abort ();
-+
-+ if (to_real)
-+ {
-+ rtx value, insns;
-+
-+ if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode))
-+ {
-+ /* Try converting directly if the insn is supported. */
-+ if ((code = can_extend_p (to_mode, from_mode, 0))
-+ != CODE_FOR_nothing)
-+ {
-+ emit_unop_insn (code, to, from, UNKNOWN);
-+ return;
-+ }
-+ }
-+
-+#ifdef HAVE_trunchfqf2
-+ if (HAVE_trunchfqf2 && from_mode == HFmode && to_mode == QFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_trunchfqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_trunctqfqf2
-+ if (HAVE_trunctqfqf2 && from_mode == TQFmode && to_mode == QFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctqfqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncsfqf2
-+ if (HAVE_truncsfqf2 && from_mode == SFmode && to_mode == QFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncsfqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncdfqf2
-+ if (HAVE_truncdfqf2 && from_mode == DFmode && to_mode == QFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncdfqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncxfqf2
-+ if (HAVE_truncxfqf2 && from_mode == XFmode && to_mode == QFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncxfqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_trunctfqf2
-+ if (HAVE_trunctfqf2 && from_mode == TFmode && to_mode == QFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctfqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+
-+#ifdef HAVE_trunctqfhf2
-+ if (HAVE_trunctqfhf2 && from_mode == TQFmode && to_mode == HFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctqfhf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncsfhf2
-+ if (HAVE_truncsfhf2 && from_mode == SFmode && to_mode == HFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncsfhf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncdfhf2
-+ if (HAVE_truncdfhf2 && from_mode == DFmode && to_mode == HFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncdfhf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncxfhf2
-+ if (HAVE_truncxfhf2 && from_mode == XFmode && to_mode == HFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncxfhf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_trunctfhf2
-+ if (HAVE_trunctfhf2 && from_mode == TFmode && to_mode == HFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctfhf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+
-+#ifdef HAVE_truncsftqf2
-+ if (HAVE_truncsftqf2 && from_mode == SFmode && to_mode == TQFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncsftqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncdftqf2
-+ if (HAVE_truncdftqf2 && from_mode == DFmode && to_mode == TQFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncdftqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncxftqf2
-+ if (HAVE_truncxftqf2 && from_mode == XFmode && to_mode == TQFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncxftqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_trunctftqf2
-+ if (HAVE_trunctftqf2 && from_mode == TFmode && to_mode == TQFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctftqf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+
-+#ifdef HAVE_truncdfsf2
-+ if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncxfsf2
-+ if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_trunctfsf2
-+ if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_truncxfdf2
-+ if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+#ifdef HAVE_trunctfdf2
-+ if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+
-+ libcall = (rtx) 0;
-+ switch (from_mode)
-+ {
-+ case SFmode:
-+ switch (to_mode)
-+ {
-+ case DFmode:
-+ libcall = extendsfdf2_libfunc;
-+ break;
-+
-+ case XFmode:
-+ libcall = extendsfxf2_libfunc;
-+ break;
-+
-+ case TFmode:
-+ libcall = extendsftf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ break;
-+
-+ case DFmode:
-+ switch (to_mode)
-+ {
-+ case SFmode:
-+ libcall = truncdfsf2_libfunc;
-+ break;
-+
-+ case XFmode:
-+ libcall = extenddfxf2_libfunc;
-+ break;
-+
-+ case TFmode:
-+ libcall = extenddftf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ break;
-+
-+ case XFmode:
-+ switch (to_mode)
-+ {
-+ case SFmode:
-+ libcall = truncxfsf2_libfunc;
-+ break;
-+
-+ case DFmode:
-+ libcall = truncxfdf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ break;
-+
-+ case TFmode:
-+ switch (to_mode)
-+ {
-+ case SFmode:
-+ libcall = trunctfsf2_libfunc;
-+ break;
-+
-+ case DFmode:
-+ libcall = trunctfdf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (libcall == (rtx) 0)
-+ /* This conversion is not implemented yet. */
-+ abort ();
-+
-+ start_sequence ();
-+ value = emit_library_call_value (libcall, NULL_RTX, LCT_CONST, to_mode,
-+ 1, from, from_mode);
-+ insns = get_insns ();
-+ end_sequence ();
-+ emit_libcall_block (insns, to, value, gen_rtx_FLOAT_TRUNCATE (to_mode,
-+ from));
-+ return;
-+ }
-+
-+ /* Now both modes are integers. */
-+
-+ /* Handle expanding beyond a word. */
-+ if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode)
-+ && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD)
-+ {
-+ rtx insns;
-+ rtx lowpart;
-+ rtx fill_value;
-+ rtx lowfrom;
-+ int i;
-+ enum machine_mode lowpart_mode;
-+ int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD);
-+
-+ /* Try converting directly if the insn is supported. */
-+ if ((code = can_extend_p (to_mode, from_mode, unsignedp))
-+ != CODE_FOR_nothing)
-+ {
-+ /* If FROM is a SUBREG, put it into a register. Do this
-+ so that we always generate the same set of insns for
-+ better cse'ing; if an intermediate assignment occurred,
-+ we won't be doing the operation directly on the SUBREG. */
-+ if (optimize > 0 && GET_CODE (from) == SUBREG)
-+ from = force_reg (from_mode, from);
-+ emit_unop_insn (code, to, from, equiv_code);
-+ return;
-+ }
-+ /* Next, try converting via full word. */
-+ else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD
-+ && ((code = can_extend_p (to_mode, word_mode, unsignedp))
-+ != CODE_FOR_nothing))
-+ {
-+ if (GET_CODE (to) == REG)
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, to));
-+ convert_move (gen_lowpart (word_mode, to), from, unsignedp);
-+ emit_unop_insn (code, to,
-+ gen_lowpart (word_mode, to), equiv_code);
-+ return;
-+ }
-+
-+ /* No special multiword conversion insn; do it by hand. */
-+ start_sequence ();
-+
-+ /* Since we will turn this into a no conflict block, we must ensure
-+ that the source does not overlap the target. */
-+
-+ if (reg_overlap_mentioned_p (to, from))
-+ from = force_reg (from_mode, from);
-+
-+ /* Get a copy of FROM widened to a word, if necessary. */
-+ if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD)
-+ lowpart_mode = word_mode;
-+ else
-+ lowpart_mode = from_mode;
-+
-+ lowfrom = convert_to_mode (lowpart_mode, from, unsignedp);
-+
-+ lowpart = gen_lowpart (lowpart_mode, to);
-+ emit_move_insn (lowpart, lowfrom);
-+
-+ /* Compute the value to put in each remaining word. */
-+ if (unsignedp)
-+ fill_value = const0_rtx;
-+ else
-+ {
-+#ifdef HAVE_slt
-+ if (HAVE_slt
-+ && insn_data[(int) CODE_FOR_slt].operand[0].mode == word_mode
-+ && STORE_FLAG_VALUE == -1)
-+ {
-+ emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX,
-+ lowpart_mode, 0);
-+ fill_value = gen_reg_rtx (word_mode);
-+ emit_insn (gen_slt (fill_value));
-+ }
-+ else
-+#endif
-+ {
-+ fill_value
-+ = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom,
-+ size_int (GET_MODE_BITSIZE (lowpart_mode) - 1),
-+ NULL_RTX, 0);
-+ fill_value = convert_to_mode (word_mode, fill_value, 1);
-+ }
-+ }
-+
-+ /* Fill the remaining words. */
-+ for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
-+ {
-+ int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
-+ rtx subword = operand_subword (to, index, 1, to_mode);
-+
-+ if (subword == 0)
-+ abort ();
-+
-+ if (fill_value != subword)
-+ emit_move_insn (subword, fill_value);
-+ }
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ emit_no_conflict_block (insns, to, from, NULL_RTX,
-+ gen_rtx_fmt_e (equiv_code, to_mode, copy_rtx (from)));
-+ return;
-+ }
-+
-+ /* Truncating multi-word to a word or less. */
-+ if (GET_MODE_BITSIZE (from_mode) > BITS_PER_WORD
-+ && GET_MODE_BITSIZE (to_mode) <= BITS_PER_WORD)
-+ {
-+ if (!((GET_CODE (from) == MEM
-+ && ! MEM_VOLATILE_P (from)
-+ && direct_load[(int) to_mode]
-+ && ! mode_dependent_address_p (XEXP (from, 0)))
-+ || GET_CODE (from) == REG
-+ || GET_CODE (from) == SUBREG))
-+ from = force_reg (from_mode, from);
-+ convert_move (to, gen_lowpart (word_mode, from), 0);
-+ return;
-+ }
-+
-+ /* Handle pointer conversion. */ /* SPEE 900220. */
-+ if (to_mode == PQImode)
-+ {
-+ if (from_mode != QImode)
-+ from = convert_to_mode (QImode, from, unsignedp);
-+
-+#ifdef HAVE_truncqipqi2
-+ if (HAVE_truncqipqi2)
-+ {
-+ emit_unop_insn (CODE_FOR_truncqipqi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif /* HAVE_truncqipqi2 */
-+ abort ();
-+ }
-+
-+ if (from_mode == PQImode)
-+ {
-+ if (to_mode != QImode)
-+ {
-+ from = convert_to_mode (QImode, from, unsignedp);
-+ from_mode = QImode;
-+ }
-+ else
-+ {
-+#ifdef HAVE_extendpqiqi2
-+ if (HAVE_extendpqiqi2)
-+ {
-+ emit_unop_insn (CODE_FOR_extendpqiqi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif /* HAVE_extendpqiqi2 */
-+ abort ();
-+ }
-+ }
-+
-+ if (to_mode == PSImode)
-+ {
-+ if (from_mode != SImode)
-+ from = convert_to_mode (SImode, from, unsignedp);
-+
-+#ifdef HAVE_truncsipsi2
-+ if (HAVE_truncsipsi2)
-+ {
-+ emit_unop_insn (CODE_FOR_truncsipsi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif /* HAVE_truncsipsi2 */
-+ abort ();
-+ }
-+
-+ if (from_mode == PSImode)
-+ {
-+ if (to_mode != SImode)
-+ {
-+ from = convert_to_mode (SImode, from, unsignedp);
-+ from_mode = SImode;
-+ }
-+ else
-+ {
-+#ifdef HAVE_extendpsisi2
-+ if (! unsignedp && HAVE_extendpsisi2)
-+ {
-+ emit_unop_insn (CODE_FOR_extendpsisi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif /* HAVE_extendpsisi2 */
-+#ifdef HAVE_zero_extendpsisi2
-+ if (unsignedp && HAVE_zero_extendpsisi2)
-+ {
-+ emit_unop_insn (CODE_FOR_zero_extendpsisi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif /* HAVE_zero_extendpsisi2 */
-+ abort ();
-+ }
-+ }
-+
-+ if (to_mode == PDImode)
-+ {
-+ if (from_mode != DImode)
-+ from = convert_to_mode (DImode, from, unsignedp);
-+
-+#ifdef HAVE_truncdipdi2
-+ if (HAVE_truncdipdi2)
-+ {
-+ emit_unop_insn (CODE_FOR_truncdipdi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif /* HAVE_truncdipdi2 */
-+ abort ();
-+ }
-+
-+ if (from_mode == PDImode)
-+ {
-+ if (to_mode != DImode)
-+ {
-+ from = convert_to_mode (DImode, from, unsignedp);
-+ from_mode = DImode;
-+ }
-+ else
-+ {
-+#ifdef HAVE_extendpdidi2
-+ if (HAVE_extendpdidi2)
-+ {
-+ emit_unop_insn (CODE_FOR_extendpdidi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif /* HAVE_extendpdidi2 */
-+ abort ();
-+ }
-+ }
-+
-+ /* Now follow all the conversions between integers
-+ no more than a word long. */
-+
-+ /* For truncation, usually we can just refer to FROM in a narrower mode. */
-+ if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
-+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
-+ GET_MODE_BITSIZE (from_mode)))
-+ {
-+ if (!((GET_CODE (from) == MEM
-+ && ! MEM_VOLATILE_P (from)
-+ && direct_load[(int) to_mode]
-+ && ! mode_dependent_address_p (XEXP (from, 0)))
-+ || GET_CODE (from) == REG
-+ || GET_CODE (from) == SUBREG))
-+ from = force_reg (from_mode, from);
-+ if (GET_CODE (from) == REG && REGNO (from) < FIRST_PSEUDO_REGISTER
-+ && ! HARD_REGNO_MODE_OK (REGNO (from), to_mode))
-+ from = copy_to_reg (from);
-+ emit_move_insn (to, gen_lowpart (to_mode, from));
-+ return;
-+ }
-+
-+ /* Handle extension. */
-+ if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode))
-+ {
-+ /* Convert directly if that works. */
-+ if ((code = can_extend_p (to_mode, from_mode, unsignedp))
-+ != CODE_FOR_nothing)
-+ {
-+ if (flag_force_mem)
-+ from = force_not_mem (from);
-+
-+ emit_unop_insn (code, to, from, equiv_code);
-+ return;
-+ }
-+ else
-+ {
-+ enum machine_mode intermediate;
-+ rtx tmp;
-+ tree shift_amount;
-+
-+ /* Search for a mode to convert via. */
-+ for (intermediate = from_mode; intermediate != VOIDmode;
-+ intermediate = GET_MODE_WIDER_MODE (intermediate))
-+ if (((can_extend_p (to_mode, intermediate, unsignedp)
-+ != CODE_FOR_nothing)
-+ || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
-+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
-+ GET_MODE_BITSIZE (intermediate))))
-+ && (can_extend_p (intermediate, from_mode, unsignedp)
-+ != CODE_FOR_nothing))
-+ {
-+ convert_move (to, convert_to_mode (intermediate, from,
-+ unsignedp), unsignedp);
-+ return;
-+ }
-+
-+ /* No suitable intermediate mode.
-+ Generate what we need with shifts. */
-+ shift_amount = build_int_2 (GET_MODE_BITSIZE (to_mode)
-+ - GET_MODE_BITSIZE (from_mode), 0);
-+ from = gen_lowpart (to_mode, force_reg (from_mode, from));
-+ tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
-+ to, unsignedp);
-+ tmp = expand_shift (RSHIFT_EXPR, to_mode, tmp, shift_amount,
-+ to, unsignedp);
-+ if (tmp != to)
-+ emit_move_insn (to, tmp);
-+ return;
-+ }
-+ }
-+
-+ /* Support special truncate insns for certain modes. */
-+
-+ if (from_mode == DImode && to_mode == SImode)
-+ {
-+#ifdef HAVE_truncdisi2
-+ if (HAVE_truncdisi2)
-+ {
-+ emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == DImode && to_mode == HImode)
-+ {
-+#ifdef HAVE_truncdihi2
-+ if (HAVE_truncdihi2)
-+ {
-+ emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == DImode && to_mode == QImode)
-+ {
-+#ifdef HAVE_truncdiqi2
-+ if (HAVE_truncdiqi2)
-+ {
-+ emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == SImode && to_mode == HImode)
-+ {
-+#ifdef HAVE_truncsihi2
-+ if (HAVE_truncsihi2)
-+ {
-+ emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == SImode && to_mode == QImode)
-+ {
-+#ifdef HAVE_truncsiqi2
-+ if (HAVE_truncsiqi2)
-+ {
-+ emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == HImode && to_mode == QImode)
-+ {
-+#ifdef HAVE_trunchiqi2
-+ if (HAVE_trunchiqi2)
-+ {
-+ emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == TImode && to_mode == DImode)
-+ {
-+#ifdef HAVE_trunctidi2
-+ if (HAVE_trunctidi2)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctidi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == TImode && to_mode == SImode)
-+ {
-+#ifdef HAVE_trunctisi2
-+ if (HAVE_trunctisi2)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctisi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == TImode && to_mode == HImode)
-+ {
-+#ifdef HAVE_trunctihi2
-+ if (HAVE_trunctihi2)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctihi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ if (from_mode == TImode && to_mode == QImode)
-+ {
-+#ifdef HAVE_trunctiqi2
-+ if (HAVE_trunctiqi2)
-+ {
-+ emit_unop_insn (CODE_FOR_trunctiqi2, to, from, UNKNOWN);
-+ return;
-+ }
-+#endif
-+ convert_move (to, force_reg (from_mode, from), unsignedp);
-+ return;
-+ }
-+
-+ /* Handle truncation of volatile memrefs, and so on;
-+ the things that couldn't be truncated directly,
-+ and for which there was no special instruction. */
-+ if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode))
-+ {
-+ rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from));
-+ emit_move_insn (to, temp);
-+ return;
-+ }
-+
-+ /* Mode combination is not recognized. */
-+ abort ();
-+}
-+
-+/* Return an rtx for a value that would result
-+ from converting X to mode MODE.
-+ Both X and MODE may be floating, or both integer.
-+ UNSIGNEDP is nonzero if X is an unsigned value.
-+ This can be done by referring to a part of X in place
-+ or by copying to a new temporary with conversion.
-+
-+ This function *must not* call protect_from_queue
-+ except when putting X into an insn (in which case convert_move does it). */
-+
-+rtx
-+convert_to_mode (mode, x, unsignedp)
-+ enum machine_mode mode;
-+ rtx x;
-+ int unsignedp;
-+{
-+ return convert_modes (mode, VOIDmode, x, unsignedp);
-+}
-+
-+/* Return an rtx for a value that would result
-+ from converting X from mode OLDMODE to mode MODE.
-+ Both modes may be floating, or both integer.
-+ UNSIGNEDP is nonzero if X is an unsigned value.
-+
-+ This can be done by referring to a part of X in place
-+ or by copying to a new temporary with conversion.
-+
-+ You can give VOIDmode for OLDMODE, if you are sure X has a nonvoid mode.
-+
-+ This function *must not* call protect_from_queue
-+ except when putting X into an insn (in which case convert_move does it). */
-+
-+rtx
-+convert_modes (mode, oldmode, x, unsignedp)
-+ enum machine_mode mode, oldmode;
-+ rtx x;
-+ int unsignedp;
-+{
-+ rtx temp;
-+
-+ /* If FROM is a SUBREG that indicates that we have already done at least
-+ the required extension, strip it. */
-+
-+ if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
-+ && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode)
-+ && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp)
-+ x = gen_lowpart (mode, x);
-+
-+ if (GET_MODE (x) != VOIDmode)
-+ oldmode = GET_MODE (x);
-+
-+ if (mode == oldmode)
-+ return x;
-+
-+ /* There is one case that we must handle specially: If we are converting
-+ a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and
-+ we are to interpret the constant as unsigned, gen_lowpart will do
-+ the wrong if the constant appears negative. What we want to do is
-+ make the high-order word of the constant zero, not all ones. */
-+
-+ if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT
-+ && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT
-+ && GET_CODE (x) == CONST_INT && INTVAL (x) < 0)
-+ {
-+ HOST_WIDE_INT val = INTVAL (x);
-+
-+ if (oldmode != VOIDmode
-+ && HOST_BITS_PER_WIDE_INT > GET_MODE_BITSIZE (oldmode))
-+ {
-+ int width = GET_MODE_BITSIZE (oldmode);
-+
-+ /* We need to zero extend VAL. */
-+ val &= ((HOST_WIDE_INT) 1 << width) - 1;
-+ }
-+
-+ return immed_double_const (val, (HOST_WIDE_INT) 0, mode);
-+ }
-+
-+ /* We can do this with a gen_lowpart if both desired and current modes
-+ are integer, and this is either a constant integer, a register, or a
-+ non-volatile MEM. Except for the constant case where MODE is no
-+ wider than HOST_BITS_PER_WIDE_INT, we must be narrowing the operand. */
-+
-+ if ((GET_CODE (x) == CONST_INT
-+ && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
-+ || (GET_MODE_CLASS (mode) == MODE_INT
-+ && GET_MODE_CLASS (oldmode) == MODE_INT
-+ && (GET_CODE (x) == CONST_DOUBLE
-+ || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (oldmode)
-+ && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x)
-+ && direct_load[(int) mode])
-+ || (GET_CODE (x) == REG
-+ && (! HARD_REGISTER_P (x)
-+ || HARD_REGNO_MODE_OK (REGNO (x), mode))
-+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
-+ GET_MODE_BITSIZE (GET_MODE (x)))))))))
-+ {
-+ /* ?? If we don't know OLDMODE, we have to assume here that
-+ X does not need sign- or zero-extension. This may not be
-+ the case, but it's the best we can do. */
-+ if (GET_CODE (x) == CONST_INT && oldmode != VOIDmode
-+ && GET_MODE_SIZE (mode) > GET_MODE_SIZE (oldmode))
-+ {
-+ HOST_WIDE_INT val = INTVAL (x);
-+ int width = GET_MODE_BITSIZE (oldmode);
-+
-+ /* We must sign or zero-extend in this case. Start by
-+ zero-extending, then sign extend if we need to. */
-+ val &= ((HOST_WIDE_INT) 1 << width) - 1;
-+ if (! unsignedp
-+ && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
-+ val |= (HOST_WIDE_INT) (-1) << width;
-+
-+ return gen_int_mode (val, mode);
-+ }
-+
-+ return gen_lowpart (mode, x);
-+ }
-+
-+ temp = gen_reg_rtx (mode);
-+ convert_move (temp, x, unsignedp);
-+ return temp;
-+}
-+\f
-+/* This macro is used to determine what the largest unit size that
-+ move_by_pieces can use is. */
-+
-+/* MOVE_MAX_PIECES is the number of bytes at a time which we can
-+ move efficiently, as opposed to MOVE_MAX which is the maximum
-+ number of bytes we can move with a single instruction. */
-+
-+#ifndef MOVE_MAX_PIECES
-+#define MOVE_MAX_PIECES MOVE_MAX
-+#endif
-+
-+/* STORE_MAX_PIECES is the number of bytes at a time that we can
-+ store efficiently. Due to internal GCC limitations, this is
-+ MOVE_MAX_PIECES limited by the number of bytes GCC can represent
-+ for an immediate constant. */
-+
-+#define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT))
-+
-+/* Generate several move instructions to copy LEN bytes from block FROM to
-+ block TO. (These are MEM rtx's with BLKmode). The caller must pass FROM
-+ and TO through protect_from_queue before calling.
-+
-+ If PUSH_ROUNDING is defined and TO is NULL, emit_single_push_insn is
-+ used to push FROM to the stack.
-+
-+ ALIGN is maximum alignment we can assume. */
-+
-+void
-+move_by_pieces (to, from, len, align)
-+ rtx to, from;
-+ unsigned HOST_WIDE_INT len;
-+ unsigned int align;
-+{
-+ struct move_by_pieces data;
-+ rtx to_addr, from_addr = XEXP (from, 0);
-+ unsigned int max_size = MOVE_MAX_PIECES + 1;
-+ enum machine_mode mode = VOIDmode, tmode;
-+ enum insn_code icode;
-+
-+ data.offset = 0;
-+ data.from_addr = from_addr;
-+ if (to)
-+ {
-+ to_addr = XEXP (to, 0);
-+ data.to = to;
-+ data.autinc_to
-+ = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
-+ || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
-+ data.reverse
-+ = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
-+ }
-+ else
-+ {
-+ to_addr = NULL_RTX;
-+ data.to = NULL_RTX;
-+ data.autinc_to = 1;
-+#ifdef STACK_GROWS_DOWNWARD
-+ data.reverse = 1;
-+#else
-+ data.reverse = 0;
-+#endif
-+ }
-+ data.to_addr = to_addr;
-+ data.from = from;
-+ data.autinc_from
-+ = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
-+ || GET_CODE (from_addr) == POST_INC
-+ || GET_CODE (from_addr) == POST_DEC);
-+
-+ data.explicit_inc_from = 0;
-+ data.explicit_inc_to = 0;
-+ if (data.reverse) data.offset = len;
-+ data.len = len;
-+
-+ /* If copying requires more than two move insns,
-+ copy addresses to registers (to make displacements shorter)
-+ and use post-increment if available. */
-+ if (!(data.autinc_from && data.autinc_to)
-+ && move_by_pieces_ninsns (len, align) > 2)
-+ {
-+ /* Find the mode of the largest move... */
-+ for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-+ tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
-+ if (GET_MODE_SIZE (tmode) < max_size)
-+ mode = tmode;
-+
-+ if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
-+ {
-+ data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
-+ data.autinc_from = 1;
-+ data.explicit_inc_from = -1;
-+ }
-+ if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from)
-+ {
-+ data.from_addr = copy_addr_to_reg (from_addr);
-+ data.autinc_from = 1;
-+ data.explicit_inc_from = 1;
-+ }
-+ if (!data.autinc_from && CONSTANT_P (from_addr))
-+ data.from_addr = copy_addr_to_reg (from_addr);
-+ if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
-+ {
-+ data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
-+ data.autinc_to = 1;
-+ data.explicit_inc_to = -1;
-+ }
-+ if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
-+ {
-+ data.to_addr = copy_addr_to_reg (to_addr);
-+ data.autinc_to = 1;
-+ data.explicit_inc_to = 1;
-+ }
-+ if (!data.autinc_to && CONSTANT_P (to_addr))
-+ data.to_addr = copy_addr_to_reg (to_addr);
-+ }
-+
-+ if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-+ || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
-+ align = MOVE_MAX * BITS_PER_UNIT;
-+
-+ /* First move what we can in the largest integer mode, then go to
-+ successively smaller modes. */
-+
-+ while (max_size > 1)
-+ {
-+ for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-+ tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
-+ if (GET_MODE_SIZE (tmode) < max_size)
-+ mode = tmode;
-+
-+ if (mode == VOIDmode)
-+ break;
-+
-+ icode = mov_optab->handlers[(int) mode].insn_code;
-+ if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
-+ move_by_pieces_1 (GEN_FCN (icode), mode, &data);
-+
-+ max_size = GET_MODE_SIZE (mode);
-+ }
-+
-+ /* The code above should have handled everything. */
-+ if (data.len > 0)
-+ abort ();
-+}
-+
-+/* Return number of insns required to move L bytes by pieces.
-+ ALIGN (in bits) is maximum alignment we can assume. */
-+
-+static unsigned HOST_WIDE_INT
-+move_by_pieces_ninsns (l, align)
-+ unsigned HOST_WIDE_INT l;
-+ unsigned int align;
-+{
-+ unsigned HOST_WIDE_INT n_insns = 0;
-+ unsigned HOST_WIDE_INT max_size = MOVE_MAX + 1;
-+
-+ if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-+ || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
-+ align = MOVE_MAX * BITS_PER_UNIT;
-+
-+ while (max_size > 1)
-+ {
-+ enum machine_mode mode = VOIDmode, tmode;
-+ enum insn_code icode;
-+
-+ for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-+ tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
-+ if (GET_MODE_SIZE (tmode) < max_size)
-+ mode = tmode;
-+
-+ if (mode == VOIDmode)
-+ break;
-+
-+ icode = mov_optab->handlers[(int) mode].insn_code;
-+ if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
-+ n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
-+
-+ max_size = GET_MODE_SIZE (mode);
-+ }
-+
-+ if (l)
-+ abort ();
-+ return n_insns;
-+}
-+
-+/* Subroutine of move_by_pieces. Move as many bytes as appropriate
-+ with move instructions for mode MODE. GENFUN is the gen_... function
-+ to make a move insn for that mode. DATA has all the other info. */
-+
-+static void
-+move_by_pieces_1 (genfun, mode, data)
-+ rtx (*genfun) PARAMS ((rtx, ...));
-+ enum machine_mode mode;
-+ struct move_by_pieces *data;
-+{
-+ unsigned int size = GET_MODE_SIZE (mode);
-+ rtx to1 = NULL_RTX, from1;
-+
-+ while (data->len >= size)
-+ {
-+ if (data->reverse)
-+ data->offset -= size;
-+
-+ if (data->to)
-+ {
-+ if (data->autinc_to)
-+ to1 = adjust_automodify_address (data->to, mode, data->to_addr,
-+ data->offset);
-+ else
-+ to1 = adjust_address (data->to, mode, data->offset);
-+ }
-+
-+ if (data->autinc_from)
-+ from1 = adjust_automodify_address (data->from, mode, data->from_addr,
-+ data->offset);
-+ else
-+ from1 = adjust_address (data->from, mode, data->offset);
-+
-+ if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
-+ emit_insn (gen_add2_insn (data->to_addr,
-+ GEN_INT (-(HOST_WIDE_INT)size)));
-+ if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
-+ emit_insn (gen_add2_insn (data->from_addr,
-+ GEN_INT (-(HOST_WIDE_INT)size)));
-+
-+ if (data->to)
-+ emit_insn ((*genfun) (to1, from1));
-+ else
-+ {
-+#ifdef PUSH_ROUNDING
-+ emit_single_push_insn (mode, from1, NULL);
-+#else
-+ abort ();
-+#endif
-+ }
-+
-+ if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
-+ emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
-+ if (HAVE_POST_INCREMENT && data->explicit_inc_from > 0)
-+ emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
-+
-+ if (! data->reverse)
-+ data->offset += size;
-+
-+ data->len -= size;
-+ }
-+}
-+\f
-+/* Emit code to move a block Y to a block X. This may be done with
-+ string-move instructions, with multiple scalar move instructions,
-+ or with a library call.
-+
-+ Both X and Y must be MEM rtx's (perhaps inside VOLATILE) with mode BLKmode.
-+ SIZE is an rtx that says how long they are.
-+ ALIGN is the maximum alignment we can assume they have.
-+ METHOD describes what kind of copy this is, and what mechanisms may be used.
-+
-+ Return the address of the new block, if memcpy is called and returns it,
-+ 0 otherwise. */
-+
-+rtx
-+emit_block_move (x, y, size, method)
-+ rtx x, y, size;
-+ enum block_op_methods method;
-+{
-+ bool may_use_call;
-+ rtx retval = 0;
-+ unsigned int align;
-+
-+ switch (method)
-+ {
-+ case BLOCK_OP_NORMAL:
-+ may_use_call = true;
-+ break;
-+
-+ case BLOCK_OP_CALL_PARM:
-+ may_use_call = block_move_libcall_safe_for_call_parm ();
-+
-+ /* Make inhibit_defer_pop nonzero around the library call
-+ to force it to pop the arguments right away. */
-+ NO_DEFER_POP;
-+ break;
-+
-+ case BLOCK_OP_NO_LIBCALL:
-+ may_use_call = false;
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+
-+ align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
-+
-+ if (GET_MODE (x) != BLKmode)
-+ abort ();
-+ if (GET_MODE (y) != BLKmode)
-+ abort ();
-+
-+ x = protect_from_queue (x, 1);
-+ y = protect_from_queue (y, 0);
-+ size = protect_from_queue (size, 0);
-+
-+ if (GET_CODE (x) != MEM)
-+ abort ();
-+ if (GET_CODE (y) != MEM)
-+ abort ();
-+ if (size == 0)
-+ abort ();
-+
-+ /* Set MEM_SIZE as appropriate for this block copy. The main place this
-+ can be incorrect is coming from __builtin_memcpy. */
-+ if (GET_CODE (size) == CONST_INT)
-+ {
-+ x = shallow_copy_rtx (x);
-+ y = shallow_copy_rtx (y);
-+ set_mem_size (x, size);
-+ set_mem_size (y, size);
-+ }
-+
-+ if (GET_CODE (size) == CONST_INT && MOVE_BY_PIECES_P (INTVAL (size), align))
-+ move_by_pieces (x, y, INTVAL (size), align);
-+ else if (emit_block_move_via_movstr (x, y, size, align))
-+ ;
-+ else if (may_use_call)
-+ retval = emit_block_move_via_libcall (x, y, size);
-+ else
-+ emit_block_move_via_loop (x, y, size, align);
-+
-+ if (method == BLOCK_OP_CALL_PARM)
-+ OK_DEFER_POP;
-+
-+ return retval;
-+}
-+
-+/* A subroutine of emit_block_move. Returns true if calling the
-+ block move libcall will not clobber any parameters which may have
-+ already been placed on the stack. */
-+
-+static bool
-+block_move_libcall_safe_for_call_parm ()
-+{
-+ if (PUSH_ARGS)
-+ return true;
-+ else
-+ {
-+ /* Check to see whether memcpy takes all register arguments. */
-+ static enum {
-+ takes_regs_uninit, takes_regs_no, takes_regs_yes
-+ } takes_regs = takes_regs_uninit;
-+
-+ switch (takes_regs)
-+ {
-+ case takes_regs_uninit:
-+ {
-+ CUMULATIVE_ARGS args_so_far;
-+ tree fn, arg;
-+
-+ fn = emit_block_move_libcall_fn (false);
-+ INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (fn), NULL_RTX, 0);
-+
-+ arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
-+ for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
-+ {
-+ enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
-+ rtx tmp = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
-+ if (!tmp || !REG_P (tmp))
-+ goto fail_takes_regs;
-+#ifdef FUNCTION_ARG_PARTIAL_NREGS
-+ if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode,
-+ NULL_TREE, 1))
-+ goto fail_takes_regs;
-+#endif
-+ FUNCTION_ARG_ADVANCE (args_so_far, mode, NULL_TREE, 1);
-+ }
-+ }
-+ takes_regs = takes_regs_yes;
-+ /* FALLTHRU */
-+
-+ case takes_regs_yes:
-+ return true;
-+
-+ fail_takes_regs:
-+ takes_regs = takes_regs_no;
-+ /* FALLTHRU */
-+ case takes_regs_no:
-+ return false;
-+
-+ default:
-+ abort ();
-+ }
-+ }
-+}
-+
-+/* A subroutine of emit_block_move. Expand a movstr pattern;
-+ return true if successful. */
-+
-+static bool
-+emit_block_move_via_movstr (x, y, size, align)
-+ rtx x, y, size;
-+ unsigned int align;
-+{
-+ /* Try the most limited insn first, because there's no point
-+ including more than one in the machine description unless
-+ the more limited one has some advantage. */
-+
-+ rtx opalign = GEN_INT (align / BITS_PER_UNIT);
-+ enum machine_mode mode;
-+
-+ /* Since this is a move insn, we don't care about volatility. */
-+ volatile_ok = 1;
-+
-+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
-+ mode = GET_MODE_WIDER_MODE (mode))
-+ {
-+ enum insn_code code = movstr_optab[(int) mode];
-+ insn_operand_predicate_fn pred;
-+
-+ if (code != CODE_FOR_nothing
-+ /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
-+ here because if SIZE is less than the mode mask, as it is
-+ returned by the macro, it will definitely be less than the
-+ actual mode mask. */
-+ && ((GET_CODE (size) == CONST_INT
-+ && ((unsigned HOST_WIDE_INT) INTVAL (size)
-+ <= (GET_MODE_MASK (mode) >> 1)))
-+ || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
-+ && ((pred = insn_data[(int) code].operand[0].predicate) == 0
-+ || (*pred) (x, BLKmode))
-+ && ((pred = insn_data[(int) code].operand[1].predicate) == 0
-+ || (*pred) (y, BLKmode))
-+ && ((pred = insn_data[(int) code].operand[3].predicate) == 0
-+ || (*pred) (opalign, VOIDmode)))
-+ {
-+ rtx op2;
-+ rtx last = get_last_insn ();
-+ rtx pat;
-+
-+ op2 = convert_to_mode (mode, size, 1);
-+ pred = insn_data[(int) code].operand[2].predicate;
-+ if (pred != 0 && ! (*pred) (op2, mode))
-+ op2 = copy_to_mode_reg (mode, op2);
-+
-+ /* ??? When called via emit_block_move_for_call, it'd be
-+ nice if there were some way to inform the backend, so
-+ that it doesn't fail the expansion because it thinks
-+ emitting the libcall would be more efficient. */
-+
-+ pat = GEN_FCN ((int) code) (x, y, op2, opalign);
-+ if (pat)
-+ {
-+ emit_insn (pat);
-+ volatile_ok = 0;
-+ return true;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+
-+ volatile_ok = 0;
-+ return false;
-+}
-+
-+/* A subroutine of emit_block_move. Expand a call to memcpy or bcopy.
-+ Return the return value from memcpy, 0 otherwise. */
-+
-+static rtx
-+emit_block_move_via_libcall (dst, src, size)
-+ rtx dst, src, size;
-+{
-+ tree call_expr, arg_list, fn, src_tree, dst_tree, size_tree;
-+ enum machine_mode size_mode;
-+ rtx retval;
-+
-+ /* DST, SRC, or SIZE may have been passed through protect_from_queue.
-+
-+ It is unsafe to save the value generated by protect_from_queue
-+ and reuse it later. Consider what happens if emit_queue is
-+ called before the return value from protect_from_queue is used.
-+
-+ Expansion of the CALL_EXPR below will call emit_queue before
-+ we are finished emitting RTL for argument setup. So if we are
-+ not careful we could get the wrong value for an argument.
-+
-+ To avoid this problem we go ahead and emit code to copy X, Y &
-+ SIZE into new pseudos. We can then place those new pseudos
-+ into an RTL_EXPR and use them later, even after a call to
-+ emit_queue.
-+
-+ Note this is not strictly needed for library calls since they
-+ do not call emit_queue before loading their arguments. However,
-+ we may need to have library calls call emit_queue in the future
-+ since failing to do so could cause problems for targets which
-+ define SMALL_REGISTER_CLASSES and pass arguments in registers. */
-+
-+ dst = copy_to_mode_reg (Pmode, XEXP (dst, 0));
-+ src = copy_to_mode_reg (Pmode, XEXP (src, 0));
-+
-+ if (TARGET_MEM_FUNCTIONS)
-+ size_mode = TYPE_MODE (sizetype);
-+ else
-+ size_mode = TYPE_MODE (unsigned_type_node);
-+ size = convert_to_mode (size_mode, size, 1);
-+ size = copy_to_mode_reg (size_mode, size);
-+
-+ /* It is incorrect to use the libcall calling conventions to call
-+ memcpy in this context. This could be a user call to memcpy and
-+ the user may wish to examine the return value from memcpy. For
-+ targets where libcalls and normal calls have different conventions
-+ for returning pointers, we could end up generating incorrect code.
-+
-+ For convenience, we generate the call to bcopy this way as well. */
-+
-+ dst_tree = make_tree (ptr_type_node, dst);
-+ src_tree = make_tree (ptr_type_node, src);
-+ if (TARGET_MEM_FUNCTIONS)
-+ size_tree = make_tree (sizetype, size);
-+ else
-+ size_tree = make_tree (unsigned_type_node, size);
-+
-+ fn = emit_block_move_libcall_fn (true);
-+ arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
-+ if (TARGET_MEM_FUNCTIONS)
-+ {
-+ arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
-+ arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
-+ }
-+ else
-+ {
-+ arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
-+ arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
-+ }
-+
-+ /* Now we have to build up the CALL_EXPR itself. */
-+ call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
-+ call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
-+ call_expr, arg_list, NULL_TREE);
-+ TREE_SIDE_EFFECTS (call_expr) = 1;
-+
-+ retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
-+
-+ /* If we are initializing a readonly value, show the above call
-+ clobbered it. Otherwise, a load from it may erroneously be
-+ hoisted from a loop. */
-+ if (RTX_UNCHANGING_P (dst))
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, dst));
-+
-+ return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
-+}
-+
-+/* A subroutine of emit_block_move_via_libcall. Create the tree node
-+ for the function we use for block copies. The first time FOR_CALL
-+ is true, we call assemble_external. */
-+
-+static GTY(()) tree block_move_fn;
-+
-+static tree
-+emit_block_move_libcall_fn (for_call)
-+ int for_call;
-+{
-+ static bool emitted_extern;
-+ tree fn = block_move_fn, args;
-+
-+ if (!fn)
-+ {
-+ if (TARGET_MEM_FUNCTIONS)
-+ {
-+ fn = get_identifier ("memcpy");
-+ args = build_function_type_list (ptr_type_node, ptr_type_node,
-+ const_ptr_type_node, sizetype,
-+ NULL_TREE);
-+ }
-+ else
-+ {
-+ fn = get_identifier ("bcopy");
-+ args = build_function_type_list (void_type_node, const_ptr_type_node,
-+ ptr_type_node, unsigned_type_node,
-+ NULL_TREE);
-+ }
-+
-+ fn = build_decl (FUNCTION_DECL, fn, args);
-+ DECL_EXTERNAL (fn) = 1;
-+ TREE_PUBLIC (fn) = 1;
-+ DECL_ARTIFICIAL (fn) = 1;
-+ TREE_NOTHROW (fn) = 1;
-+
-+ block_move_fn = fn;
-+ }
-+
-+ if (for_call && !emitted_extern)
-+ {
-+ emitted_extern = true;
-+ make_decl_rtl (fn, NULL);
-+ assemble_external (fn);
-+ }
-+
-+ return fn;
-+}
-+
-+/* A subroutine of emit_block_move. Copy the data via an explicit
-+ loop. This is used only when libcalls are forbidden. */
-+/* ??? It'd be nice to copy in hunks larger than QImode. */
-+
-+static void
-+emit_block_move_via_loop (x, y, size, align)
-+ rtx x, y, size;
-+ unsigned int align ATTRIBUTE_UNUSED;
-+{
-+ rtx cmp_label, top_label, iter, x_addr, y_addr, tmp;
-+ enum machine_mode iter_mode;
-+
-+ iter_mode = GET_MODE (size);
-+ if (iter_mode == VOIDmode)
-+ iter_mode = word_mode;
-+
-+ top_label = gen_label_rtx ();
-+ cmp_label = gen_label_rtx ();
-+ iter = gen_reg_rtx (iter_mode);
-+
-+ emit_move_insn (iter, const0_rtx);
-+
-+ x_addr = force_operand (XEXP (x, 0), NULL_RTX);
-+ y_addr = force_operand (XEXP (y, 0), NULL_RTX);
-+ do_pending_stack_adjust ();
-+
-+ emit_note (NULL, NOTE_INSN_LOOP_BEG);
-+
-+ emit_jump (cmp_label);
-+ emit_label (top_label);
-+
-+ tmp = convert_modes (Pmode, iter_mode, iter, true);
-+ x_addr = gen_rtx_PLUS (Pmode, x_addr, tmp);
-+ y_addr = gen_rtx_PLUS (Pmode, y_addr, tmp);
-+ x = change_address (x, QImode, x_addr);
-+ y = change_address (y, QImode, y_addr);
-+
-+ emit_move_insn (x, y);
-+
-+ tmp = expand_simple_binop (iter_mode, PLUS, iter, const1_rtx, iter,
-+ true, OPTAB_LIB_WIDEN);
-+ if (tmp != iter)
-+ emit_move_insn (iter, tmp);
-+
-+ emit_note (NULL, NOTE_INSN_LOOP_CONT);
-+ emit_label (cmp_label);
-+
-+ emit_cmp_and_jump_insns (iter, size, LT, NULL_RTX, iter_mode,
-+ true, top_label);
-+
-+ emit_note (NULL, NOTE_INSN_LOOP_END);
-+}
-+\f
-+/* Copy all or part of a value X into registers starting at REGNO.
-+ The number of registers to be filled is NREGS. */
-+
-+void
-+move_block_to_reg (regno, x, nregs, mode)
-+ int regno;
-+ rtx x;
-+ int nregs;
-+ enum machine_mode mode;
-+{
-+ int i;
-+#ifdef HAVE_load_multiple
-+ rtx pat;
-+ rtx last;
-+#endif
-+
-+ if (nregs == 0)
-+ return;
-+
-+ if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
-+ x = validize_mem (force_const_mem (mode, x));
-+
-+ /* See if the machine can do this with a load multiple insn. */
-+#ifdef HAVE_load_multiple
-+ if (HAVE_load_multiple)
-+ {
-+ last = get_last_insn ();
-+ pat = gen_load_multiple (gen_rtx_REG (word_mode, regno), x,
-+ GEN_INT (nregs));
-+ if (pat)
-+ {
-+ emit_insn (pat);
-+ return;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+#endif
-+
-+ for (i = 0; i < nregs; i++)
-+ emit_move_insn (gen_rtx_REG (word_mode, regno + i),
-+ operand_subword_force (x, i, mode));
-+}
-+
-+/* Copy all or part of a BLKmode value X out of registers starting at REGNO.
-+ The number of registers to be filled is NREGS. SIZE indicates the number
-+ of bytes in the object X. */
-+
-+void
-+move_block_from_reg (regno, x, nregs, size)
-+ int regno;
-+ rtx x;
-+ int nregs;
-+ int size;
-+{
-+ int i;
-+#ifdef HAVE_store_multiple
-+ rtx pat;
-+ rtx last;
-+#endif
-+ enum machine_mode mode;
-+
-+ if (nregs == 0)
-+ return;
-+
-+ /* If SIZE is that of a mode no bigger than a word, just use that
-+ mode's store operation. */
-+ if (size <= UNITS_PER_WORD
-+ && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode)
-+ {
-+ emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
-+ return;
-+ }
-+
-+ /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
-+ to the left before storing to memory. Note that the previous test
-+ doesn't handle all cases (e.g. SIZE == 3). */
-+ if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN)
-+ {
-+ rtx tem = operand_subword (x, 0, 1, BLKmode);
-+ rtx shift;
-+
-+ if (tem == 0)
-+ abort ();
-+
-+ shift = expand_shift (LSHIFT_EXPR, word_mode,
-+ gen_rtx_REG (word_mode, regno),
-+ build_int_2 ((UNITS_PER_WORD - size)
-+ * BITS_PER_UNIT, 0), NULL_RTX, 0);
-+ emit_move_insn (tem, shift);
-+ return;
-+ }
-+
-+ /* See if the machine can do this with a store multiple insn. */
-+#ifdef HAVE_store_multiple
-+ if (HAVE_store_multiple)
-+ {
-+ last = get_last_insn ();
-+ pat = gen_store_multiple (x, gen_rtx_REG (word_mode, regno),
-+ GEN_INT (nregs));
-+ if (pat)
-+ {
-+ emit_insn (pat);
-+ return;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+#endif
-+
-+ for (i = 0; i < nregs; i++)
-+ {
-+ rtx tem = operand_subword (x, i, 1, BLKmode);
-+
-+ if (tem == 0)
-+ abort ();
-+
-+ emit_move_insn (tem, gen_rtx_REG (word_mode, regno + i));
-+ }
-+}
-+
-+/* Generate a PARALLEL rtx for a new non-consecutive group of registers from
-+ ORIG, where ORIG is a non-consecutive group of registers represented by
-+ a PARALLEL. The clone is identical to the original except in that the
-+ original set of registers is replaced by a new set of pseudo registers.
-+ The new set has the same modes as the original set. */
-+
-+rtx
-+gen_group_rtx (orig)
-+ rtx orig;
-+{
-+ int i, length;
-+ rtx *tmps;
-+
-+ if (GET_CODE (orig) != PARALLEL)
-+ abort ();
-+
-+ length = XVECLEN (orig, 0);
-+ tmps = (rtx *) alloca (sizeof (rtx) * length);
-+
-+ /* Skip a NULL entry in first slot. */
-+ i = XEXP (XVECEXP (orig, 0, 0), 0) ? 0 : 1;
-+
-+ if (i)
-+ tmps[0] = 0;
-+
-+ for (; i < length; i++)
-+ {
-+ enum machine_mode mode = GET_MODE (XEXP (XVECEXP (orig, 0, i), 0));
-+ rtx offset = XEXP (XVECEXP (orig, 0, i), 1);
-+
-+ tmps[i] = gen_rtx_EXPR_LIST (VOIDmode, gen_reg_rtx (mode), offset);
-+ }
-+
-+ return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps));
-+}
-+
-+/* Emit code to move a block SRC to a block DST, where DST is non-consecutive
-+ registers represented by a PARALLEL. SSIZE represents the total size of
-+ block SRC in bytes, or -1 if not known. */
-+/* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatant assumption that
-+ the balance will be in what would be the low-order memory addresses, i.e.
-+ left justified for big endian, right justified for little endian. This
-+ happens to be true for the targets currently using this support. If this
-+ ever changes, a new target macro along the lines of FUNCTION_ARG_PADDING
-+ would be needed. */
-+
-+void
-+emit_group_load (dst, orig_src, ssize)
-+ rtx dst, orig_src;
-+ int ssize;
-+{
-+ rtx *tmps, src;
-+ int start, i;
-+
-+ if (GET_CODE (dst) != PARALLEL)
-+ abort ();
-+
-+ /* Check for a NULL entry, used to indicate that the parameter goes
-+ both on the stack and in registers. */
-+ if (XEXP (XVECEXP (dst, 0, 0), 0))
-+ start = 0;
-+ else
-+ start = 1;
-+
-+ tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0));
-+
-+ /* Process the pieces. */
-+ for (i = start; i < XVECLEN (dst, 0); i++)
-+ {
-+ enum machine_mode mode = GET_MODE (XEXP (XVECEXP (dst, 0, i), 0));
-+ HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (dst, 0, i), 1));
-+ unsigned int bytelen = GET_MODE_SIZE (mode);
-+ int shift = 0;
-+
-+ /* Handle trailing fragments that run over the size of the struct. */
-+ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
-+ {
-+ shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
-+ bytelen = ssize - bytepos;
-+ if (bytelen <= 0)
-+ abort ();
-+ }
-+
-+ /* If we won't be loading directly from memory, protect the real source
-+ from strange tricks we might play; but make sure that the source can
-+ be loaded directly into the destination. */
-+ src = orig_src;
-+ if (GET_CODE (orig_src) != MEM
-+ && (!CONSTANT_P (orig_src)
-+ || (GET_MODE (orig_src) != mode
-+ && GET_MODE (orig_src) != VOIDmode)))
-+ {
-+ if (GET_MODE (orig_src) == VOIDmode)
-+ src = gen_reg_rtx (mode);
-+ else
-+ src = gen_reg_rtx (GET_MODE (orig_src));
-+
-+ emit_move_insn (src, orig_src);
-+ }
-+
-+ /* Optimize the access just a bit. */
-+ if (GET_CODE (src) == MEM
-+ && MEM_ALIGN (src) >= GET_MODE_ALIGNMENT (mode)
-+ && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
-+ && bytelen == GET_MODE_SIZE (mode))
-+ {
-+ tmps[i] = gen_reg_rtx (mode);
-+ emit_move_insn (tmps[i], adjust_address (src, mode, bytepos));
-+ }
-+ else if (GET_CODE (src) == CONCAT)
-+ {
-+ unsigned int slen = GET_MODE_SIZE (GET_MODE (src));
-+ unsigned int slen0 = GET_MODE_SIZE (GET_MODE (XEXP (src, 0)));
-+
-+ if ((bytepos == 0 && bytelen == slen0)
-+ || (bytepos != 0 && bytepos + bytelen <= slen))
-+ {
-+ /* The following assumes that the concatenated objects all
-+ have the same size. In this case, a simple calculation
-+ can be used to determine the object and the bit field
-+ to be extracted. */
-+ tmps[i] = XEXP (src, bytepos / slen0);
-+ if (! CONSTANT_P (tmps[i])
-+ && (GET_CODE (tmps[i]) != REG || GET_MODE (tmps[i]) != mode))
-+ tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
-+ (bytepos % slen0) * BITS_PER_UNIT,
-+ 1, NULL_RTX, mode, mode, ssize);
-+ }
-+ else if (bytepos == 0)
-+ {
-+ rtx mem = assign_stack_temp (GET_MODE (src), slen, 0);
-+ emit_move_insn (mem, src);
-+ tmps[i] = adjust_address (mem, mode, 0);
-+ }
-+ else
-+ abort ();
-+ }
-+ else if (CONSTANT_P (src)
-+ || (GET_CODE (src) == REG && GET_MODE (src) == mode))
-+ tmps[i] = src;
-+ else
-+ tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
-+ bytepos * BITS_PER_UNIT, 1, NULL_RTX,
-+ mode, mode, ssize);
-+
-+ if (BYTES_BIG_ENDIAN && shift)
-+ expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
-+ tmps[i], 0, OPTAB_WIDEN);
-+ }
-+
-+ emit_queue ();
-+
-+ /* Copy the extracted pieces into the proper (probable) hard regs. */
-+ for (i = start; i < XVECLEN (dst, 0); i++)
-+ emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
-+}
-+
-+/* Emit code to move a block SRC to block DST, where SRC and DST are
-+ non-consecutive groups of registers, each represented by a PARALLEL. */
-+
-+void
-+emit_group_move (dst, src)
-+ rtx dst, src;
-+{
-+ int i;
-+
-+ if (GET_CODE (src) != PARALLEL
-+ || GET_CODE (dst) != PARALLEL
-+ || XVECLEN (src, 0) != XVECLEN (dst, 0))
-+ abort ();
-+
-+ /* Skip first entry if NULL. */
-+ for (i = XEXP (XVECEXP (src, 0, 0), 0) ? 0 : 1; i < XVECLEN (src, 0); i++)
-+ emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0),
-+ XEXP (XVECEXP (src, 0, i), 0));
-+}
-+
-+/* Emit code to move a block SRC to a block DST, where SRC is non-consecutive
-+ registers represented by a PARALLEL. SSIZE represents the total size of
-+ block DST, or -1 if not known. */
-+
-+void
-+emit_group_store (orig_dst, src, ssize)
-+ rtx orig_dst, src;
-+ int ssize;
-+{
-+ rtx *tmps, dst;
-+ int start, i;
-+
-+ if (GET_CODE (src) != PARALLEL)
-+ abort ();
-+
-+ /* Check for a NULL entry, used to indicate that the parameter goes
-+ both on the stack and in registers. */
-+ if (XEXP (XVECEXP (src, 0, 0), 0))
-+ start = 0;
-+ else
-+ start = 1;
-+
-+ tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (src, 0));
-+
-+ /* Copy the (probable) hard regs into pseudos. */
-+ for (i = start; i < XVECLEN (src, 0); i++)
-+ {
-+ rtx reg = XEXP (XVECEXP (src, 0, i), 0);
-+ tmps[i] = gen_reg_rtx (GET_MODE (reg));
-+ emit_move_insn (tmps[i], reg);
-+ }
-+ emit_queue ();
-+
-+ /* If we won't be storing directly into memory, protect the real destination
-+ from strange tricks we might play. */
-+ dst = orig_dst;
-+ if (GET_CODE (dst) == PARALLEL)
-+ {
-+ rtx temp;
-+
-+ /* We can get a PARALLEL dst if there is a conditional expression in
-+ a return statement. In that case, the dst and src are the same,
-+ so no action is necessary. */
-+ if (rtx_equal_p (dst, src))
-+ return;
-+
-+ /* It is unclear if we can ever reach here, but we may as well handle
-+ it. Allocate a temporary, and split this into a store/load to/from
-+ the temporary. */
-+
-+ temp = assign_stack_temp (GET_MODE (dst), ssize, 0);
-+ emit_group_store (temp, src, ssize);
-+ emit_group_load (dst, temp, ssize);
-+ return;
-+ }
-+ else if (GET_CODE (dst) != MEM && GET_CODE (dst) != CONCAT)
-+ {
-+ dst = gen_reg_rtx (GET_MODE (orig_dst));
-+ /* Make life a bit easier for combine. */
-+ emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst)));
-+ }
-+
-+ /* Process the pieces. */
-+ for (i = start; i < XVECLEN (src, 0); i++)
-+ {
-+ HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
-+ enum machine_mode mode = GET_MODE (tmps[i]);
-+ unsigned int bytelen = GET_MODE_SIZE (mode);
-+ rtx dest = dst;
-+
-+ /* Handle trailing fragments that run over the size of the struct. */
-+ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
-+ {
-+ if (BYTES_BIG_ENDIAN)
-+ {
-+ int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
-+ expand_binop (mode, ashr_optab, tmps[i], GEN_INT (shift),
-+ tmps[i], 0, OPTAB_WIDEN);
-+ }
-+ bytelen = ssize - bytepos;
-+ }
-+
-+ if (GET_CODE (dst) == CONCAT)
-+ {
-+ if (bytepos + bytelen <= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
-+ dest = XEXP (dst, 0);
-+ else if (bytepos >= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
-+ {
-+ bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
-+ dest = XEXP (dst, 1);
-+ }
-+ else if (bytepos == 0 && XVECLEN (src, 0))
-+ {
-+ dest = assign_stack_temp (GET_MODE (dest),
-+ GET_MODE_SIZE (GET_MODE (dest)), 0);
-+ emit_move_insn (adjust_address (dest, GET_MODE (tmps[i]), bytepos),
-+ tmps[i]);
-+ dst = dest;
-+ break;
-+ }
-+ else
-+ abort ();
-+ }
-+
-+ /* Optimize the access just a bit. */
-+ if (GET_CODE (dest) == MEM
-+ && MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)
-+ && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
-+ && bytelen == GET_MODE_SIZE (mode))
-+ emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
-+ else
-+ store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
-+ mode, tmps[i], ssize);
-+ }
-+
-+ emit_queue ();
-+
-+ /* Copy from the pseudo into the (probable) hard reg. */
-+ if (orig_dst != dst)
-+ emit_move_insn (orig_dst, dst);
-+}
-+
-+/* Generate code to copy a BLKmode object of TYPE out of a
-+ set of registers starting with SRCREG into TGTBLK. If TGTBLK
-+ is null, a stack temporary is created. TGTBLK is returned.
-+
-+ The primary purpose of this routine is to handle functions
-+ that return BLKmode structures in registers. Some machines
-+ (the PA for example) want to return all small structures
-+ in registers regardless of the structure's alignment. */
-+
-+rtx
-+copy_blkmode_from_reg (tgtblk, srcreg, type)
-+ rtx tgtblk;
-+ rtx srcreg;
-+ tree type;
-+{
-+ unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
-+ rtx src = NULL, dst = NULL;
-+ unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD);
-+ unsigned HOST_WIDE_INT bitpos, xbitpos, big_endian_correction = 0;
-+
-+ if (tgtblk == 0)
-+ {
-+ tgtblk = assign_temp (build_qualified_type (type,
-+ (TYPE_QUALS (type)
-+ | TYPE_QUAL_CONST)),
-+ 0, 1, 1);
-+ preserve_temp_slots (tgtblk);
-+ }
-+
-+ /* This code assumes srcreg is at least a full word. If it isn't, copy it
-+ into a new pseudo which is a full word. */
-+
-+ if (GET_MODE (srcreg) != BLKmode
-+ && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
-+ srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
-+
-+ /* Structures whose size is not a multiple of a word are aligned
-+ to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
-+ machine, this means we must skip the empty high order bytes when
-+ calculating the bit offset. */
-+ if (BYTES_BIG_ENDIAN
-+ && bytes % UNITS_PER_WORD)
-+ big_endian_correction
-+ = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
-+
-+ /* Copy the structure BITSIZE bites at a time.
-+
-+ We could probably emit more efficient code for machines which do not use
-+ strict alignment, but it doesn't seem worth the effort at the current
-+ time. */
-+ for (bitpos = 0, xbitpos = big_endian_correction;
-+ bitpos < bytes * BITS_PER_UNIT;
-+ bitpos += bitsize, xbitpos += bitsize)
-+ {
-+ /* We need a new source operand each time xbitpos is on a
-+ word boundary and when xbitpos == big_endian_correction
-+ (the first time through). */
-+ if (xbitpos % BITS_PER_WORD == 0
-+ || xbitpos == big_endian_correction)
-+ src = operand_subword_force (srcreg, xbitpos / BITS_PER_WORD,
-+ GET_MODE (srcreg));
-+
-+ /* We need a new destination operand each time bitpos is on
-+ a word boundary. */
-+ if (bitpos % BITS_PER_WORD == 0)
-+ dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode);
-+
-+ /* Use xbitpos for the source extraction (right justified) and
-+ xbitpos for the destination store (left justified). */
-+ store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
-+ extract_bit_field (src, bitsize,
-+ xbitpos % BITS_PER_WORD, 1,
-+ NULL_RTX, word_mode, word_mode,
-+ BITS_PER_WORD),
-+ BITS_PER_WORD);
-+ }
-+
-+ return tgtblk;
-+}
-+
-+/* Add a USE expression for REG to the (possibly empty) list pointed
-+ to by CALL_FUSAGE. REG must denote a hard register. */
-+
-+void
-+use_reg (call_fusage, reg)
-+ rtx *call_fusage, reg;
-+{
-+ if (GET_CODE (reg) != REG
-+ || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
-+ abort ();
-+
-+ *call_fusage
-+ = gen_rtx_EXPR_LIST (VOIDmode,
-+ gen_rtx_USE (VOIDmode, reg), *call_fusage);
-+}
-+
-+/* Add USE expressions to *CALL_FUSAGE for each of NREGS consecutive regs,
-+ starting at REGNO. All of these registers must be hard registers. */
-+
-+void
-+use_regs (call_fusage, regno, nregs)
-+ rtx *call_fusage;
-+ int regno;
-+ int nregs;
-+{
-+ int i;
-+
-+ if (regno + nregs > FIRST_PSEUDO_REGISTER)
-+ abort ();
-+
-+ for (i = 0; i < nregs; i++)
-+ use_reg (call_fusage, regno_reg_rtx[regno + i]);
-+}
-+
-+/* Add USE expressions to *CALL_FUSAGE for each REG contained in the
-+ PARALLEL REGS. This is for calls that pass values in multiple
-+ non-contiguous locations. The Irix 6 ABI has examples of this. */
-+
-+void
-+use_group_regs (call_fusage, regs)
-+ rtx *call_fusage;
-+ rtx regs;
-+{
-+ int i;
-+
-+ for (i = 0; i < XVECLEN (regs, 0); i++)
-+ {
-+ rtx reg = XEXP (XVECEXP (regs, 0, i), 0);
-+
-+ /* A NULL entry means the parameter goes both on the stack and in
-+ registers. This can also be a MEM for targets that pass values
-+ partially on the stack and partially in registers. */
-+ if (reg != 0 && GET_CODE (reg) == REG)
-+ use_reg (call_fusage, reg);
-+ }
-+}
-+\f
-+
-+/* Determine whether the LEN bytes generated by CONSTFUN can be
-+ stored to memory using several move instructions. CONSTFUNDATA is
-+ a pointer which will be passed as argument in every CONSTFUN call.
-+ ALIGN is maximum alignment we can assume. Return nonzero if a
-+ call to store_by_pieces should succeed. */
-+
-+int
-+can_store_by_pieces (len, constfun, constfundata, align)
-+ unsigned HOST_WIDE_INT len;
-+ rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
-+ PTR constfundata;
-+ unsigned int align;
-+{
-+ unsigned HOST_WIDE_INT max_size, l;
-+ HOST_WIDE_INT offset = 0;
-+ enum machine_mode mode, tmode;
-+ enum insn_code icode;
-+ int reverse;
-+ rtx cst;
-+
-+ if (len == 0)
-+ return 1;
-+
-+ if (! MOVE_BY_PIECES_P (len, align))
-+ return 0;
-+
-+ if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-+ || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
-+ align = MOVE_MAX * BITS_PER_UNIT;
-+
-+ /* We would first store what we can in the largest integer mode, then go to
-+ successively smaller modes. */
-+
-+ for (reverse = 0;
-+ reverse <= (HAVE_PRE_DECREMENT || HAVE_POST_DECREMENT);
-+ reverse++)
-+ {
-+ l = len;
-+ mode = VOIDmode;
-+ max_size = STORE_MAX_PIECES + 1;
-+ while (max_size > 1)
-+ {
-+ for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-+ tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
-+ if (GET_MODE_SIZE (tmode) < max_size)
-+ mode = tmode;
-+
-+ if (mode == VOIDmode)
-+ break;
-+
-+ icode = mov_optab->handlers[(int) mode].insn_code;
-+ if (icode != CODE_FOR_nothing
-+ && align >= GET_MODE_ALIGNMENT (mode))
-+ {
-+ unsigned int size = GET_MODE_SIZE (mode);
-+
-+ while (l >= size)
-+ {
-+ if (reverse)
-+ offset -= size;
-+
-+ cst = (*constfun) (constfundata, offset, mode);
-+ if (!LEGITIMATE_CONSTANT_P (cst))
-+ return 0;
-+
-+ if (!reverse)
-+ offset += size;
-+
-+ l -= size;
-+ }
-+ }
-+
-+ max_size = GET_MODE_SIZE (mode);
-+ }
-+
-+ /* The code above should have handled everything. */
-+ if (l != 0)
-+ abort ();
-+ }
-+
-+ return 1;
-+}
-+
-+/* Generate several move instructions to store LEN bytes generated by
-+ CONSTFUN to block TO. (A MEM rtx with BLKmode). CONSTFUNDATA is a
-+ pointer which will be passed as argument in every CONSTFUN call.
-+ ALIGN is maximum alignment we can assume. */
-+
-+void
-+store_by_pieces (to, len, constfun, constfundata, align)
-+ rtx to;
-+ unsigned HOST_WIDE_INT len;
-+ rtx (*constfun) PARAMS ((PTR, HOST_WIDE_INT, enum machine_mode));
-+ PTR constfundata;
-+ unsigned int align;
-+{
-+ struct store_by_pieces data;
-+
-+ if (len == 0)
-+ return;
-+
-+ if (! MOVE_BY_PIECES_P (len, align))
-+ abort ();
-+ to = protect_from_queue (to, 1);
-+ data.constfun = constfun;
-+ data.constfundata = constfundata;
-+ data.len = len;
-+ data.to = to;
-+ store_by_pieces_1 (&data, align);
-+}
-+
-+/* Generate several move instructions to clear LEN bytes of block TO. (A MEM
-+ rtx with BLKmode). The caller must pass TO through protect_from_queue
-+ before calling. ALIGN is maximum alignment we can assume. */
-+
-+static void
-+clear_by_pieces (to, len, align)
-+ rtx to;
-+ unsigned HOST_WIDE_INT len;
-+ unsigned int align;
-+{
-+ struct store_by_pieces data;
-+
-+ if (len == 0)
-+ return;
-+
-+ data.constfun = clear_by_pieces_1;
-+ data.constfundata = NULL;
-+ data.len = len;
-+ data.to = to;
-+ store_by_pieces_1 (&data, align);
-+}
-+
-+/* Callback routine for clear_by_pieces.
-+ Return const0_rtx unconditionally. */
-+
-+static rtx
-+clear_by_pieces_1 (data, offset, mode)
-+ PTR data ATTRIBUTE_UNUSED;
-+ HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
-+ enum machine_mode mode ATTRIBUTE_UNUSED;
-+{
-+ return const0_rtx;
-+}
-+
-+/* Subroutine of clear_by_pieces and store_by_pieces.
-+ Generate several move instructions to store LEN bytes of block TO. (A MEM
-+ rtx with BLKmode). The caller must pass TO through protect_from_queue
-+ before calling. ALIGN is maximum alignment we can assume. */
-+
-+static void
-+store_by_pieces_1 (data, align)
-+ struct store_by_pieces *data;
-+ unsigned int align;
-+{
-+ rtx to_addr = XEXP (data->to, 0);
-+ unsigned HOST_WIDE_INT max_size = STORE_MAX_PIECES + 1;
-+ enum machine_mode mode = VOIDmode, tmode;
-+ enum insn_code icode;
-+
-+ data->offset = 0;
-+ data->to_addr = to_addr;
-+ data->autinc_to
-+ = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
-+ || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
-+
-+ data->explicit_inc_to = 0;
-+ data->reverse
-+ = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
-+ if (data->reverse)
-+ data->offset = data->len;
-+
-+ /* If storing requires more than two move insns,
-+ copy addresses to registers (to make displacements shorter)
-+ and use post-increment if available. */
-+ if (!data->autinc_to
-+ && move_by_pieces_ninsns (data->len, align) > 2)
-+ {
-+ /* Determine the main mode we'll be using. */
-+ for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-+ tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
-+ if (GET_MODE_SIZE (tmode) < max_size)
-+ mode = tmode;
-+
-+ if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
-+ {
-+ data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
-+ data->autinc_to = 1;
-+ data->explicit_inc_to = -1;
-+ }
-+
-+ if (USE_STORE_POST_INCREMENT (mode) && ! data->reverse
-+ && ! data->autinc_to)
-+ {
-+ data->to_addr = copy_addr_to_reg (to_addr);
-+ data->autinc_to = 1;
-+ data->explicit_inc_to = 1;
-+ }
-+
-+ if ( !data->autinc_to && CONSTANT_P (to_addr))
-+ data->to_addr = copy_addr_to_reg (to_addr);
-+ }
-+
-+ if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
-+ || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
-+ align = MOVE_MAX * BITS_PER_UNIT;
-+
-+ /* First store what we can in the largest integer mode, then go to
-+ successively smaller modes. */
-+
-+ while (max_size > 1)
-+ {
-+ for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-+ tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
-+ if (GET_MODE_SIZE (tmode) < max_size)
-+ mode = tmode;
-+
-+ if (mode == VOIDmode)
-+ break;
-+
-+ icode = mov_optab->handlers[(int) mode].insn_code;
-+ if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode))
-+ store_by_pieces_2 (GEN_FCN (icode), mode, data);
-+
-+ max_size = GET_MODE_SIZE (mode);
-+ }
-+
-+ /* The code above should have handled everything. */
-+ if (data->len != 0)
-+ abort ();
-+}
-+
-+/* Subroutine of store_by_pieces_1. Store as many bytes as appropriate
-+ with move instructions for mode MODE. GENFUN is the gen_... function
-+ to make a move insn for that mode. DATA has all the other info. */
-+
-+static void
-+store_by_pieces_2 (genfun, mode, data)
-+ rtx (*genfun) PARAMS ((rtx, ...));
-+ enum machine_mode mode;
-+ struct store_by_pieces *data;
-+{
-+ unsigned int size = GET_MODE_SIZE (mode);
-+ rtx to1, cst;
-+
-+ while (data->len >= size)
-+ {
-+ if (data->reverse)
-+ data->offset -= size;
-+
-+ if (data->autinc_to)
-+ to1 = adjust_automodify_address (data->to, mode, data->to_addr,
-+ data->offset);
-+ else
-+ to1 = adjust_address (data->to, mode, data->offset);
-+
-+ if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
-+ emit_insn (gen_add2_insn (data->to_addr,
-+ GEN_INT (-(HOST_WIDE_INT) size)));
-+
-+ cst = (*data->constfun) (data->constfundata, data->offset, mode);
-+ emit_insn ((*genfun) (to1, cst));
-+
-+ if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
-+ emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
-+
-+ if (! data->reverse)
-+ data->offset += size;
-+
-+ data->len -= size;
-+ }
-+}
-+\f
-+/* Write zeros through the storage of OBJECT. If OBJECT has BLKmode, SIZE is
-+ its length in bytes. */
-+
-+rtx
-+clear_storage (object, size)
-+ rtx object;
-+ rtx size;
-+{
-+ rtx retval = 0;
-+ unsigned int align = (GET_CODE (object) == MEM ? MEM_ALIGN (object)
-+ : GET_MODE_ALIGNMENT (GET_MODE (object)));
-+
-+ /* If OBJECT is not BLKmode and SIZE is the same size as its mode,
-+ just move a zero. Otherwise, do this a piece at a time. */
-+ if (GET_MODE (object) != BLKmode
-+ && GET_CODE (size) == CONST_INT
-+ && INTVAL (size) == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (object)))
-+ emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
-+ else
-+ {
-+ object = protect_from_queue (object, 1);
-+ size = protect_from_queue (size, 0);
-+
-+ if (GET_CODE (size) == CONST_INT && INTVAL (size) == 0)
-+ ;
-+ else if (GET_CODE (size) == CONST_INT
-+ && CLEAR_BY_PIECES_P (INTVAL (size), align))
-+ clear_by_pieces (object, INTVAL (size), align);
-+ else if (clear_storage_via_clrstr (object, size, align))
-+ ;
-+ else
-+ retval = clear_storage_via_libcall (object, size);
-+ }
-+
-+ return retval;
-+}
-+
-+/* A subroutine of clear_storage. Expand a clrstr pattern;
-+ return true if successful. */
-+
-+static bool
-+clear_storage_via_clrstr (object, size, align)
-+ rtx object, size;
-+ unsigned int align;
-+{
-+ /* Try the most limited insn first, because there's no point
-+ including more than one in the machine description unless
-+ the more limited one has some advantage. */
-+
-+ rtx opalign = GEN_INT (align / BITS_PER_UNIT);
-+ enum machine_mode mode;
-+
-+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
-+ mode = GET_MODE_WIDER_MODE (mode))
-+ {
-+ enum insn_code code = clrstr_optab[(int) mode];
-+ insn_operand_predicate_fn pred;
-+
-+ if (code != CODE_FOR_nothing
-+ /* We don't need MODE to be narrower than
-+ BITS_PER_HOST_WIDE_INT here because if SIZE is less than
-+ the mode mask, as it is returned by the macro, it will
-+ definitely be less than the actual mode mask. */
-+ && ((GET_CODE (size) == CONST_INT
-+ && ((unsigned HOST_WIDE_INT) INTVAL (size)
-+ <= (GET_MODE_MASK (mode) >> 1)))
-+ || GET_MODE_BITSIZE (mode) >= BITS_PER_WORD)
-+ && ((pred = insn_data[(int) code].operand[0].predicate) == 0
-+ || (*pred) (object, BLKmode))
-+ && ((pred = insn_data[(int) code].operand[2].predicate) == 0
-+ || (*pred) (opalign, VOIDmode)))
-+ {
-+ rtx op1;
-+ rtx last = get_last_insn ();
-+ rtx pat;
-+
-+ op1 = convert_to_mode (mode, size, 1);
-+ pred = insn_data[(int) code].operand[1].predicate;
-+ if (pred != 0 && ! (*pred) (op1, mode))
-+ op1 = copy_to_mode_reg (mode, op1);
-+
-+ pat = GEN_FCN ((int) code) (object, op1, opalign);
-+ if (pat)
-+ {
-+ emit_insn (pat);
-+ return true;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+
-+ return false;
-+}
-+
-+/* A subroutine of clear_storage. Expand a call to memset or bzero.
-+ Return the return value of memset, 0 otherwise. */
-+
-+static rtx
-+clear_storage_via_libcall (object, size)
-+ rtx object, size;
-+{
-+ tree call_expr, arg_list, fn, object_tree, size_tree;
-+ enum machine_mode size_mode;
-+ rtx retval;
-+
-+ /* OBJECT or SIZE may have been passed through protect_from_queue.
-+
-+ It is unsafe to save the value generated by protect_from_queue
-+ and reuse it later. Consider what happens if emit_queue is
-+ called before the return value from protect_from_queue is used.
-+
-+ Expansion of the CALL_EXPR below will call emit_queue before
-+ we are finished emitting RTL for argument setup. So if we are
-+ not careful we could get the wrong value for an argument.
-+
-+ To avoid this problem we go ahead and emit code to copy OBJECT
-+ and SIZE into new pseudos. We can then place those new pseudos
-+ into an RTL_EXPR and use them later, even after a call to
-+ emit_queue.
-+
-+ Note this is not strictly needed for library calls since they
-+ do not call emit_queue before loading their arguments. However,
-+ we may need to have library calls call emit_queue in the future
-+ since failing to do so could cause problems for targets which
-+ define SMALL_REGISTER_CLASSES and pass arguments in registers. */
-+
-+ object = copy_to_mode_reg (Pmode, XEXP (object, 0));
-+
-+ if (TARGET_MEM_FUNCTIONS)
-+ size_mode = TYPE_MODE (sizetype);
-+ else
-+ size_mode = TYPE_MODE (unsigned_type_node);
-+ size = convert_to_mode (size_mode, size, 1);
-+ size = copy_to_mode_reg (size_mode, size);
-+
-+ /* It is incorrect to use the libcall calling conventions to call
-+ memset in this context. This could be a user call to memset and
-+ the user may wish to examine the return value from memset. For
-+ targets where libcalls and normal calls have different conventions
-+ for returning pointers, we could end up generating incorrect code.
-+
-+ For convenience, we generate the call to bzero this way as well. */
-+
-+ object_tree = make_tree (ptr_type_node, object);
-+ if (TARGET_MEM_FUNCTIONS)
-+ size_tree = make_tree (sizetype, size);
-+ else
-+ size_tree = make_tree (unsigned_type_node, size);
-+
-+ fn = clear_storage_libcall_fn (true);
-+ arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
-+ if (TARGET_MEM_FUNCTIONS)
-+ arg_list = tree_cons (NULL_TREE, integer_zero_node, arg_list);
-+ arg_list = tree_cons (NULL_TREE, object_tree, arg_list);
-+
-+ /* Now we have to build up the CALL_EXPR itself. */
-+ call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
-+ call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
-+ call_expr, arg_list, NULL_TREE);
-+ TREE_SIDE_EFFECTS (call_expr) = 1;
-+
-+ retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
-+
-+ /* If we are initializing a readonly value, show the above call
-+ clobbered it. Otherwise, a load from it may erroneously be
-+ hoisted from a loop. */
-+ if (RTX_UNCHANGING_P (object))
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, object));
-+
-+ return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
-+}
-+
-+/* A subroutine of clear_storage_via_libcall. Create the tree node
-+ for the function we use for block clears. The first time FOR_CALL
-+ is true, we call assemble_external. */
-+
-+static GTY(()) tree block_clear_fn;
-+
-+static tree
-+clear_storage_libcall_fn (for_call)
-+ int for_call;
-+{
-+ static bool emitted_extern;
-+ tree fn = block_clear_fn, args;
-+
-+ if (!fn)
-+ {
-+ if (TARGET_MEM_FUNCTIONS)
-+ {
-+ fn = get_identifier ("memset");
-+ args = build_function_type_list (ptr_type_node, ptr_type_node,
-+ integer_type_node, sizetype,
-+ NULL_TREE);
-+ }
-+ else
-+ {
-+ fn = get_identifier ("bzero");
-+ args = build_function_type_list (void_type_node, ptr_type_node,
-+ unsigned_type_node, NULL_TREE);
-+ }
-+
-+ fn = build_decl (FUNCTION_DECL, fn, args);
-+ DECL_EXTERNAL (fn) = 1;
-+ TREE_PUBLIC (fn) = 1;
-+ DECL_ARTIFICIAL (fn) = 1;
-+ TREE_NOTHROW (fn) = 1;
-+
-+ block_clear_fn = fn;
-+ }
-+
-+ if (for_call && !emitted_extern)
-+ {
-+ emitted_extern = true;
-+ make_decl_rtl (fn, NULL);
-+ assemble_external (fn);
-+ }
-+
-+ return fn;
-+}
-+\f
-+/* Generate code to copy Y into X.
-+ Both Y and X must have the same mode, except that
-+ Y can be a constant with VOIDmode.
-+ This mode cannot be BLKmode; use emit_block_move for that.
-+
-+ Return the last instruction emitted. */
-+
-+rtx
-+emit_move_insn (x, y)
-+ rtx x, y;
-+{
-+ enum machine_mode mode = GET_MODE (x);
-+ rtx y_cst = NULL_RTX;
-+ rtx last_insn;
-+
-+ x = protect_from_queue (x, 1);
-+ y = protect_from_queue (y, 0);
-+
-+ if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode))
-+ abort ();
-+
-+ /* Never force constant_p_rtx to memory. */
-+ if (GET_CODE (y) == CONSTANT_P_RTX)
-+ ;
-+ else if (CONSTANT_P (y))
-+ {
-+ if (optimize
-+ && SCALAR_FLOAT_MODE_P (GET_MODE (x))
-+ && (last_insn = compress_float_constant (x, y)))
-+ return last_insn;
-+
-+ if (!LEGITIMATE_CONSTANT_P (y))
-+ {
-+ y_cst = y;
-+ y = force_const_mem (mode, y);
-+
-+ /* If the target's cannot_force_const_mem prevented the spill,
-+ assume that the target's move expanders will also take care
-+ of the non-legitimate constant. */
-+ if (!y)
-+ y = y_cst;
-+ }
-+ }
-+
-+ /* If X or Y are memory references, verify that their addresses are valid
-+ for the machine. */
-+ if (GET_CODE (x) == MEM
-+ && ((! memory_address_p (GET_MODE (x), XEXP (x, 0))
-+ && ! push_operand (x, GET_MODE (x)))
-+ || (flag_force_addr
-+ && CONSTANT_ADDRESS_P (XEXP (x, 0)))))
-+ x = validize_mem (x);
-+
-+ if (GET_CODE (y) == MEM
-+ && (! memory_address_p (GET_MODE (y), XEXP (y, 0))
-+ || (flag_force_addr
-+ && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
-+ y = validize_mem (y);
-+
-+ if (mode == BLKmode)
-+ abort ();
-+
-+ last_insn = emit_move_insn_1 (x, y);
-+
-+ if (y_cst && GET_CODE (x) == REG)
-+ set_unique_reg_note (last_insn, REG_EQUAL, y_cst);
-+
-+ return last_insn;
-+}
-+
-+/* Low level part of emit_move_insn.
-+ Called just like emit_move_insn, but assumes X and Y
-+ are basically valid. */
-+
-+rtx
-+emit_move_insn_1 (x, y)
-+ rtx x, y;
-+{
-+ enum machine_mode mode = GET_MODE (x);
-+ enum machine_mode submode;
-+ enum mode_class class = GET_MODE_CLASS (mode);
-+
-+ if ((unsigned int) mode >= (unsigned int) MAX_MACHINE_MODE)
-+ abort ();
-+
-+ if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ return
-+ emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
-+
-+ /* Expand complex moves by moving real part and imag part, if possible. */
-+ else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
-+ && BLKmode != (submode = GET_MODE_INNER (mode))
-+ && (mov_optab->handlers[(int) submode].insn_code
-+ != CODE_FOR_nothing))
-+ {
-+ /* Don't split destination if it is a stack push. */
-+ int stack = push_operand (x, GET_MODE (x));
-+
-+#ifdef PUSH_ROUNDING
-+ /* In case we output to the stack, but the size is smaller machine can
-+ push exactly, we need to use move instructions. */
-+ if (stack
-+ && (PUSH_ROUNDING (GET_MODE_SIZE (submode))
-+ != GET_MODE_SIZE (submode)))
-+ {
-+ rtx temp;
-+ HOST_WIDE_INT offset1, offset2;
-+
-+ /* Do not use anti_adjust_stack, since we don't want to update
-+ stack_pointer_delta. */
-+ temp = expand_binop (Pmode,
-+#ifdef STACK_GROWS_DOWNWARD
-+ sub_optab,
-+#else
-+ add_optab,
-+#endif
-+ stack_pointer_rtx,
-+ GEN_INT
-+ (PUSH_ROUNDING
-+ (GET_MODE_SIZE (GET_MODE (x)))),
-+ stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
-+
-+ if (temp != stack_pointer_rtx)
-+ emit_move_insn (stack_pointer_rtx, temp);
-+
-+#ifdef STACK_GROWS_DOWNWARD
-+ offset1 = 0;
-+ offset2 = GET_MODE_SIZE (submode);
-+#else
-+ offset1 = -PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)));
-+ offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))
-+ + GET_MODE_SIZE (submode));
-+#endif
-+
-+ emit_move_insn (change_address (x, submode,
-+ gen_rtx_PLUS (Pmode,
-+ stack_pointer_rtx,
-+ GEN_INT (offset1))),
-+ gen_realpart (submode, y));
-+ emit_move_insn (change_address (x, submode,
-+ gen_rtx_PLUS (Pmode,
-+ stack_pointer_rtx,
-+ GEN_INT (offset2))),
-+ gen_imagpart (submode, y));
-+ }
-+ else
-+#endif
-+ /* If this is a stack, push the highpart first, so it
-+ will be in the argument order.
-+
-+ In that case, change_address is used only to convert
-+ the mode, not to change the address. */
-+ if (stack)
-+ {
-+ /* Note that the real part always precedes the imag part in memory
-+ regardless of machine's endianness. */
-+#ifdef STACK_GROWS_DOWNWARD
-+ emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
-+ (gen_rtx_MEM (submode, XEXP (x, 0)),
-+ gen_imagpart (submode, y)));
-+ emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
-+ (gen_rtx_MEM (submode, XEXP (x, 0)),
-+ gen_realpart (submode, y)));
-+#else
-+ emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
-+ (gen_rtx_MEM (submode, XEXP (x, 0)),
-+ gen_realpart (submode, y)));
-+ emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
-+ (gen_rtx_MEM (submode, XEXP (x, 0)),
-+ gen_imagpart (submode, y)));
-+#endif
-+ }
-+ else
-+ {
-+ rtx realpart_x, realpart_y;
-+ rtx imagpart_x, imagpart_y;
-+
-+ /* If this is a complex value with each part being smaller than a
-+ word, the usual calling sequence will likely pack the pieces into
-+ a single register. Unfortunately, SUBREG of hard registers only
-+ deals in terms of words, so we have a problem converting input
-+ arguments to the CONCAT of two registers that is used elsewhere
-+ for complex values. If this is before reload, we can copy it into
-+ memory and reload. FIXME, we should see about using extract and
-+ insert on integer registers, but complex short and complex char
-+ variables should be rarely used. */
-+ if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
-+ && (reload_in_progress | reload_completed) == 0)
-+ {
-+ int packed_dest_p
-+ = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
-+ int packed_src_p
-+ = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
-+
-+ if (packed_dest_p || packed_src_p)
-+ {
-+ enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
-+ ? MODE_FLOAT : MODE_INT);
-+
-+ enum machine_mode reg_mode
-+ = mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
-+
-+ if (reg_mode != BLKmode)
-+ {
-+ rtx mem = assign_stack_temp (reg_mode,
-+ GET_MODE_SIZE (mode), 0);
-+ rtx cmem = adjust_address (mem, mode, 0);
-+
-+ cfun->cannot_inline
-+ = N_("function using short complex types cannot be inline");
-+
-+ if (packed_dest_p)
-+ {
-+ rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
-+
-+ emit_move_insn_1 (cmem, y);
-+ return emit_move_insn_1 (sreg, mem);
-+ }
-+ else
-+ {
-+ rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
-+
-+ emit_move_insn_1 (mem, sreg);
-+ return emit_move_insn_1 (x, cmem);
-+ }
-+ }
-+ }
-+ }
-+
-+ realpart_x = gen_realpart (submode, x);
-+ realpart_y = gen_realpart (submode, y);
-+ imagpart_x = gen_imagpart (submode, x);
-+ imagpart_y = gen_imagpart (submode, y);
-+
-+ /* Show the output dies here. This is necessary for SUBREGs
-+ of pseudos since we cannot track their lifetimes correctly;
-+ hard regs shouldn't appear here except as return values.
-+ We never want to emit such a clobber after reload. */
-+ if (x != y
-+ && ! (reload_in_progress || reload_completed)
-+ && (GET_CODE (realpart_x) == SUBREG
-+ || GET_CODE (imagpart_x) == SUBREG))
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
-+
-+ emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
-+ (realpart_x, realpart_y));
-+ emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
-+ (imagpart_x, imagpart_y));
-+ }
-+
-+ return get_last_insn ();
-+ }
-+
-+ /* This will handle any multi-word or full-word mode that lacks a move_insn
-+ pattern. However, you will get better code if you define such patterns,
-+ even if they must turn into multiple assembler instructions. */
-+ else if (GET_MODE_SIZE (mode) >= UNITS_PER_WORD)
-+ {
-+ rtx last_insn = 0;
-+ rtx seq, inner;
-+ int need_clobber;
-+ int i;
-+
-+#ifdef PUSH_ROUNDING
-+
-+ /* If X is a push on the stack, do the push now and replace
-+ X with a reference to the stack pointer. */
-+ if (push_operand (x, GET_MODE (x)))
-+ {
-+ rtx temp;
-+ enum rtx_code code;
-+
-+ /* Do not use anti_adjust_stack, since we don't want to update
-+ stack_pointer_delta. */
-+ temp = expand_binop (Pmode,
-+#ifdef STACK_GROWS_DOWNWARD
-+ sub_optab,
-+#else
-+ add_optab,
-+#endif
-+ stack_pointer_rtx,
-+ GEN_INT
-+ (PUSH_ROUNDING
-+ (GET_MODE_SIZE (GET_MODE (x)))),
-+ stack_pointer_rtx, 0, OPTAB_LIB_WIDEN);
-+
-+ if (temp != stack_pointer_rtx)
-+ emit_move_insn (stack_pointer_rtx, temp);
-+
-+ code = GET_CODE (XEXP (x, 0));
-+
-+ /* Just hope that small offsets off SP are OK. */
-+ if (code == POST_INC)
-+ temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-+ GEN_INT (-((HOST_WIDE_INT)
-+ GET_MODE_SIZE (GET_MODE (x)))));
-+ else if (code == POST_DEC)
-+ temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-+ GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
-+ else
-+ temp = stack_pointer_rtx;
-+
-+ x = change_address (x, VOIDmode, temp);
-+ }
-+#endif
-+
-+ /* If we are in reload, see if either operand is a MEM whose address
-+ is scheduled for replacement. */
-+ if (reload_in_progress && GET_CODE (x) == MEM
-+ && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
-+ x = replace_equiv_address_nv (x, inner);
-+ if (reload_in_progress && GET_CODE (y) == MEM
-+ && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
-+ y = replace_equiv_address_nv (y, inner);
-+
-+ start_sequence ();
-+
-+ need_clobber = 0;
-+ for (i = 0;
-+ i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
-+ i++)
-+ {
-+ rtx xpart = operand_subword (x, i, 1, mode);
-+ rtx ypart = operand_subword (y, i, 1, mode);
-+
-+ /* If we can't get a part of Y, put Y into memory if it is a
-+ constant. Otherwise, force it into a register. If we still
-+ can't get a part of Y, abort. */
-+ if (ypart == 0 && CONSTANT_P (y))
-+ {
-+ y = force_const_mem (mode, y);
-+ ypart = operand_subword (y, i, 1, mode);
-+ }
-+ else if (ypart == 0)
-+ ypart = operand_subword_force (y, i, mode);
-+
-+ if (xpart == 0 || ypart == 0)
-+ abort ();
-+
-+ need_clobber |= (GET_CODE (xpart) == SUBREG);
-+
-+ last_insn = emit_move_insn (xpart, ypart);
-+ }
-+
-+ seq = get_insns ();
-+ end_sequence ();
-+
-+ /* Show the output dies here. This is necessary for SUBREGs
-+ of pseudos since we cannot track their lifetimes correctly;
-+ hard regs shouldn't appear here except as return values.
-+ We never want to emit such a clobber after reload. */
-+ if (x != y
-+ && ! (reload_in_progress || reload_completed)
-+ && need_clobber != 0)
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
-+
-+ emit_insn (seq);
-+
-+ return last_insn;
-+ }
-+ else
-+ abort ();
-+}
-+
-+/* If Y is representable exactly in a narrower mode, and the target can
-+ perform the extension directly from constant or memory, then emit the
-+ move as an extension. */
-+
-+static rtx
-+compress_float_constant (x, y)
-+ rtx x, y;
-+{
-+ enum machine_mode dstmode = GET_MODE (x);
-+ enum machine_mode orig_srcmode = GET_MODE (y);
-+ enum machine_mode srcmode;
-+ REAL_VALUE_TYPE r;
-+
-+ REAL_VALUE_FROM_CONST_DOUBLE (r, y);
-+
-+ for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
-+ srcmode != orig_srcmode;
-+ srcmode = GET_MODE_WIDER_MODE (srcmode))
-+ {
-+ enum insn_code ic;
-+ rtx trunc_y, last_insn;
-+
-+ /* Skip if the target can't extend this way. */
-+ ic = can_extend_p (dstmode, srcmode, 0);
-+ if (ic == CODE_FOR_nothing)
-+ continue;
-+
-+ /* Skip if the narrowed value isn't exact. */
-+ if (! exact_real_truncate (srcmode, &r))
-+ continue;
-+
-+ trunc_y = CONST_DOUBLE_FROM_REAL_VALUE (r, srcmode);
-+
-+ if (LEGITIMATE_CONSTANT_P (trunc_y))
-+ {
-+ /* Skip if the target needs extra instructions to perform
-+ the extension. */
-+ if (! (*insn_data[ic].operand[1].predicate) (trunc_y, srcmode))
-+ continue;
-+ }
-+ else if (float_extend_from_mem[dstmode][srcmode])
-+ trunc_y = validize_mem (force_const_mem (srcmode, trunc_y));
-+ else
-+ continue;
-+
-+ emit_unop_insn (ic, x, trunc_y, UNKNOWN);
-+ last_insn = get_last_insn ();
-+
-+ if (GET_CODE (x) == REG)
-+ REG_NOTES (last_insn)
-+ = gen_rtx_EXPR_LIST (REG_EQUAL, y, REG_NOTES (last_insn));
-+
-+ return last_insn;
-+ }
-+
-+ return NULL_RTX;
-+}
-+\f
-+/* Pushing data onto the stack. */
-+
-+/* Push a block of length SIZE (perhaps variable)
-+ and return an rtx to address the beginning of the block.
-+ Note that it is not possible for the value returned to be a QUEUED.
-+ The value may be virtual_outgoing_args_rtx.
-+
-+ EXTRA is the number of bytes of padding to push in addition to SIZE.
-+ BELOW nonzero means this padding comes at low addresses;
-+ otherwise, the padding comes at high addresses. */
-+
-+rtx
-+push_block (size, extra, below)
-+ rtx size;
-+ int extra, below;
-+{
-+ rtx temp;
-+
-+ size = convert_modes (Pmode, ptr_mode, size, 1);
-+ if (CONSTANT_P (size))
-+ anti_adjust_stack (plus_constant (size, extra));
-+ else if (GET_CODE (size) == REG && extra == 0)
-+ anti_adjust_stack (size);
-+ else
-+ {
-+ temp = copy_to_mode_reg (Pmode, size);
-+ if (extra != 0)
-+ temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
-+ temp, 0, OPTAB_LIB_WIDEN);
-+ anti_adjust_stack (temp);
-+ }
-+
-+#ifndef STACK_GROWS_DOWNWARD
-+ if (0)
-+#else
-+ if (1)
-+#endif
-+ {
-+ temp = virtual_outgoing_args_rtx;
-+ if (extra != 0 && below)
-+ temp = plus_constant (temp, extra);
-+ }
-+ else
-+ {
-+ if (GET_CODE (size) == CONST_INT)
-+ temp = plus_constant (virtual_outgoing_args_rtx,
-+ -INTVAL (size) - (below ? 0 : extra));
-+ else if (extra != 0 && !below)
-+ temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
-+ negate_rtx (Pmode, plus_constant (size, extra)));
-+ else
-+ temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
-+ negate_rtx (Pmode, size));
-+ }
-+
-+ return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
-+}
-+
-+#ifdef PUSH_ROUNDING
-+
-+/* Emit single push insn. */
-+
-+static void
-+emit_single_push_insn (mode, x, type)
-+ rtx x;
-+ enum machine_mode mode;
-+ tree type;
-+{
-+ rtx dest_addr;
-+ unsigned rounded_size = PUSH_ROUNDING (GET_MODE_SIZE (mode));
-+ rtx dest;
-+ enum insn_code icode;
-+ insn_operand_predicate_fn pred;
-+
-+ stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
-+ /* If there is push pattern, use it. Otherwise try old way of throwing
-+ MEM representing push operation to move expander. */
-+ icode = push_optab->handlers[(int) mode].insn_code;
-+ if (icode != CODE_FOR_nothing)
-+ {
-+ if (((pred = insn_data[(int) icode].operand[0].predicate)
-+ && !((*pred) (x, mode))))
-+ x = force_reg (mode, x);
-+ emit_insn (GEN_FCN (icode) (x));
-+ return;
-+ }
-+ if (GET_MODE_SIZE (mode) == rounded_size)
-+ dest_addr = gen_rtx_fmt_e (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
-+ else
-+ {
-+#ifdef STACK_GROWS_DOWNWARD
-+ dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-+ GEN_INT (-(HOST_WIDE_INT) rounded_size));
-+#else
-+ dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-+ GEN_INT (rounded_size));
-+#endif
-+ dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
-+ }
-+
-+ dest = gen_rtx_MEM (mode, dest_addr);
-+
-+ if (type != 0)
-+ {
-+ set_mem_attributes (dest, type, 1);
-+
-+ if (flag_optimize_sibling_calls)
-+ /* Function incoming arguments may overlap with sibling call
-+ outgoing arguments and we cannot allow reordering of reads
-+ from function arguments with stores to outgoing arguments
-+ of sibling calls. */
-+ set_mem_alias_set (dest, 0);
-+ }
-+ emit_move_insn (dest, x);
-+}
-+#endif
-+
-+/* Generate code to push X onto the stack, assuming it has mode MODE and
-+ type TYPE.
-+ MODE is redundant except when X is a CONST_INT (since they don't
-+ carry mode info).
-+ SIZE is an rtx for the size of data to be copied (in bytes),
-+ needed only if X is BLKmode.
-+
-+ ALIGN (in bits) is maximum alignment we can assume.
-+
-+ If PARTIAL and REG are both nonzero, then copy that many of the first
-+ words of X into registers starting with REG, and push the rest of X.
-+ The amount of space pushed is decreased by PARTIAL words,
-+ rounded *down* to a multiple of PARM_BOUNDARY.
-+ REG must be a hard register in this case.
-+ If REG is zero but PARTIAL is not, take any all others actions for an
-+ argument partially in registers, but do not actually load any
-+ registers.
-+
-+ EXTRA is the amount in bytes of extra space to leave next to this arg.
-+ This is ignored if an argument block has already been allocated.
-+
-+ On a machine that lacks real push insns, ARGS_ADDR is the address of
-+ the bottom of the argument block for this call. We use indexing off there
-+ to store the arg. On machines with push insns, ARGS_ADDR is 0 when a
-+ argument block has not been preallocated.
-+
-+ ARGS_SO_FAR is the size of args previously pushed for this call.
-+
-+ REG_PARM_STACK_SPACE is nonzero if functions require stack space
-+ for arguments passed in registers. If nonzero, it will be the number
-+ of bytes required. */
-+
-+void
-+emit_push_insn (x, mode, type, size, align, partial, reg, extra,
-+ args_addr, args_so_far, reg_parm_stack_space,
-+ alignment_pad)
-+ rtx x;
-+ enum machine_mode mode;
-+ tree type;
-+ rtx size;
-+ unsigned int align;
-+ int partial;
-+ rtx reg;
-+ int extra;
-+ rtx args_addr;
-+ rtx args_so_far;
-+ int reg_parm_stack_space;
-+ rtx alignment_pad;
-+{
-+ rtx xinner;
-+ enum direction stack_direction
-+#ifdef STACK_GROWS_DOWNWARD
-+ = downward;
-+#else
-+ = upward;
-+#endif
-+
-+ /* Decide where to pad the argument: `downward' for below,
-+ `upward' for above, or `none' for don't pad it.
-+ Default is below for small data on big-endian machines; else above. */
-+ enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
-+
-+ /* Invert direction if stack is post-decrement.
-+ FIXME: why? */
-+ if (STACK_PUSH_CODE == POST_DEC)
-+ if (where_pad != none)
-+ where_pad = (where_pad == downward ? upward : downward);
-+
-+ xinner = x = protect_from_queue (x, 0);
-+
-+ if (mode == BLKmode)
-+ {
-+ /* Copy a block into the stack, entirely or partially. */
-+
-+ rtx temp;
-+ int used = partial * UNITS_PER_WORD;
-+ int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
-+ int skip;
-+
-+ if (size == 0)
-+ abort ();
-+
-+ used -= offset;
-+
-+ /* USED is now the # of bytes we need not copy to the stack
-+ because registers will take care of them. */
-+
-+ if (partial != 0)
-+ xinner = adjust_address (xinner, BLKmode, used);
-+
-+ /* If the partial register-part of the arg counts in its stack size,
-+ skip the part of stack space corresponding to the registers.
-+ Otherwise, start copying to the beginning of the stack space,
-+ by setting SKIP to 0. */
-+ skip = (reg_parm_stack_space == 0) ? 0 : used;
-+
-+#ifdef PUSH_ROUNDING
-+ /* Do it with several push insns if that doesn't take lots of insns
-+ and if there is no difficulty with push insns that skip bytes
-+ on the stack for alignment purposes. */
-+ if (args_addr == 0
-+ && PUSH_ARGS
-+ && GET_CODE (size) == CONST_INT
-+ && skip == 0
-+ && (MOVE_BY_PIECES_P ((unsigned) INTVAL (size) - used, align))
-+ /* Here we avoid the case of a structure whose weak alignment
-+ forces many pushes of a small amount of data,
-+ and such small pushes do rounding that causes trouble. */
-+ && ((! SLOW_UNALIGNED_ACCESS (word_mode, align))
-+ || align >= BIGGEST_ALIGNMENT
-+ || (PUSH_ROUNDING (align / BITS_PER_UNIT)
-+ == (align / BITS_PER_UNIT)))
-+ && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
-+ {
-+ /* Push padding now if padding above and stack grows down,
-+ or if padding below and stack grows up.
-+ But if space already allocated, this has already been done. */
-+ if (extra && args_addr == 0
-+ && where_pad != none && where_pad != stack_direction)
-+ anti_adjust_stack (GEN_INT (extra));
-+
-+ move_by_pieces (NULL, xinner, INTVAL (size) - used, align);
-+ }
-+ else
-+#endif /* PUSH_ROUNDING */
-+ {
-+ rtx target;
-+
-+ /* Otherwise make space on the stack and copy the data
-+ to the address of that space. */
-+
-+ /* Deduct words put into registers from the size we must copy. */
-+ if (partial != 0)
-+ {
-+ if (GET_CODE (size) == CONST_INT)
-+ size = GEN_INT (INTVAL (size) - used);
-+ else
-+ size = expand_binop (GET_MODE (size), sub_optab, size,
-+ GEN_INT (used), NULL_RTX, 0,
-+ OPTAB_LIB_WIDEN);
-+ }
-+
-+ /* Get the address of the stack space.
-+ In this case, we do not deal with EXTRA separately.
-+ A single stack adjust will do. */
-+ if (! args_addr)
-+ {
-+ temp = push_block (size, extra, where_pad == downward);
-+ extra = 0;
-+ }
-+ else if (GET_CODE (args_so_far) == CONST_INT)
-+ temp = memory_address (BLKmode,
-+ plus_constant (args_addr,
-+ skip + INTVAL (args_so_far)));
-+ else
-+ temp = memory_address (BLKmode,
-+ plus_constant (gen_rtx_PLUS (Pmode,
-+ args_addr,
-+ args_so_far),
-+ skip));
-+
-+ if (!ACCUMULATE_OUTGOING_ARGS)
-+ {
-+ /* If the source is referenced relative to the stack pointer,
-+ copy it to another register to stabilize it. We do not need
-+ to do this if we know that we won't be changing sp. */
-+
-+ if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
-+ || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
-+ temp = copy_to_reg (temp);
-+ }
-+
-+ target = gen_rtx_MEM (BLKmode, temp);
-+
-+ if (type != 0)
-+ {
-+ set_mem_attributes (target, type, 1);
-+ /* Function incoming arguments may overlap with sibling call
-+ outgoing arguments and we cannot allow reordering of reads
-+ from function arguments with stores to outgoing arguments
-+ of sibling calls. */
-+ set_mem_alias_set (target, 0);
-+ }
-+
-+ /* ALIGN may well be better aligned than TYPE, e.g. due to
-+ PARM_BOUNDARY. Assume the caller isn't lying. */
-+ set_mem_align (target, align);
-+
-+ emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
-+ }
-+ }
-+ else if (partial > 0)
-+ {
-+ /* Scalar partly in registers. */
-+
-+ int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
-+ int i;
-+ int not_stack;
-+ /* # words of start of argument
-+ that we must make space for but need not store. */
-+ int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
-+ int args_offset = INTVAL (args_so_far);
-+ int skip;
-+
-+ /* Push padding now if padding above and stack grows down,
-+ or if padding below and stack grows up.
-+ But if space already allocated, this has already been done. */
-+ if (extra && args_addr == 0
-+ && where_pad != none && where_pad != stack_direction)
-+ anti_adjust_stack (GEN_INT (extra));
-+
-+ /* If we make space by pushing it, we might as well push
-+ the real data. Otherwise, we can leave OFFSET nonzero
-+ and leave the space uninitialized. */
-+ if (args_addr == 0)
-+ offset = 0;
-+
-+ /* Now NOT_STACK gets the number of words that we don't need to
-+ allocate on the stack. */
-+ not_stack = partial - offset;
-+
-+ /* If the partial register-part of the arg counts in its stack size,
-+ skip the part of stack space corresponding to the registers.
-+ Otherwise, start copying to the beginning of the stack space,
-+ by setting SKIP to 0. */
-+ skip = (reg_parm_stack_space == 0) ? 0 : not_stack;
-+
-+ if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
-+ x = validize_mem (force_const_mem (mode, x));
-+
-+ /* If X is a hard register in a non-integer mode, copy it into a pseudo;
-+ SUBREGs of such registers are not allowed. */
-+ if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER
-+ && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT))
-+ x = copy_to_reg (x);
-+
-+ /* Loop over all the words allocated on the stack for this arg. */
-+ /* We can do it by words, because any scalar bigger than a word
-+ has a size a multiple of a word. */
-+#ifndef PUSH_ARGS_REVERSED
-+ for (i = not_stack; i < size; i++)
-+#else
-+ for (i = size - 1; i >= not_stack; i--)
-+#endif
-+ if (i >= not_stack + offset)
-+ emit_push_insn (operand_subword_force (x, i, mode),
-+ word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX,
-+ 0, args_addr,
-+ GEN_INT (args_offset + ((i - not_stack + skip)
-+ * UNITS_PER_WORD)),
-+ reg_parm_stack_space, alignment_pad);
-+ }
-+ else
-+ {
-+ rtx addr;
-+ rtx target = NULL_RTX;
-+ rtx dest;
-+
-+ /* Push padding now if padding above and stack grows down,
-+ or if padding below and stack grows up.
-+ But if space already allocated, this has already been done. */
-+ if (extra && args_addr == 0
-+ && where_pad != none && where_pad != stack_direction)
-+ anti_adjust_stack (GEN_INT (extra));
-+
-+#ifdef PUSH_ROUNDING
-+ if (args_addr == 0 && PUSH_ARGS)
-+ emit_single_push_insn (mode, x, type);
-+ else
-+#endif
-+ {
-+ if (GET_CODE (args_so_far) == CONST_INT)
-+ addr
-+ = memory_address (mode,
-+ plus_constant (args_addr,
-+ INTVAL (args_so_far)));
-+ else
-+ addr = memory_address (mode, gen_rtx_PLUS (Pmode, args_addr,
-+ args_so_far));
-+ target = addr;
-+ dest = gen_rtx_MEM (mode, addr);
-+ if (type != 0)
-+ {
-+ set_mem_attributes (dest, type, 1);
-+ /* Function incoming arguments may overlap with sibling call
-+ outgoing arguments and we cannot allow reordering of reads
-+ from function arguments with stores to outgoing arguments
-+ of sibling calls. */
-+ set_mem_alias_set (dest, 0);
-+ }
-+
-+ emit_move_insn (dest, x);
-+ }
-+ }
-+
-+ /* If part should go in registers, copy that part
-+ into the appropriate registers. Do this now, at the end,
-+ since mem-to-mem copies above may do function calls. */
-+ if (partial > 0 && reg != 0)
-+ {
-+ /* Handle calls that pass values in multiple non-contiguous locations.
-+ The Irix 6 ABI has examples of this. */
-+ if (GET_CODE (reg) == PARALLEL)
-+ emit_group_load (reg, x, -1); /* ??? size? */
-+ else
-+ move_block_to_reg (REGNO (reg), x, partial, mode);
-+ }
-+
-+ if (extra && args_addr == 0 && where_pad == stack_direction)
-+ anti_adjust_stack (GEN_INT (extra));
-+
-+ if (alignment_pad && args_addr == 0)
-+ anti_adjust_stack (alignment_pad);
-+}
-+\f
-+/* Return X if X can be used as a subtarget in a sequence of arithmetic
-+ operations. */
-+
-+static rtx
-+get_subtarget (x)
-+ rtx x;
-+{
-+ return ((x == 0
-+ /* Only registers can be subtargets. */
-+ || GET_CODE (x) != REG
-+ /* If the register is readonly, it can't be set more than once. */
-+ || RTX_UNCHANGING_P (x)
-+ /* Don't use hard regs to avoid extending their life. */
-+ || REGNO (x) < FIRST_PSEUDO_REGISTER
-+ /* Avoid subtargets inside loops,
-+ since they hide some invariant expressions. */
-+ || preserve_subexpressions_p ())
-+ ? 0 : x);
-+}
-+
-+/* Expand an assignment that stores the value of FROM into TO.
-+ If WANT_VALUE is nonzero, return an rtx for the value of TO.
-+ (This may contain a QUEUED rtx;
-+ if the value is constant, this rtx is a constant.)
-+ Otherwise, the returned value is NULL_RTX.
-+
-+ SUGGEST_REG is no longer actually used.
-+ It used to mean, copy the value through a register
-+ and return that register, if that is possible.
-+ We now use WANT_VALUE to decide whether to do this. */
-+
-+rtx
-+expand_assignment (to, from, want_value, suggest_reg)
-+ tree to, from;
-+ int want_value;
-+ int suggest_reg ATTRIBUTE_UNUSED;
-+{
-+ rtx to_rtx = 0;
-+ rtx result;
-+
-+ /* Don't crash if the lhs of the assignment was erroneous. */
-+
-+ if (TREE_CODE (to) == ERROR_MARK)
-+ {
-+ result = expand_expr (from, NULL_RTX, VOIDmode, 0);
-+ return want_value ? result : NULL_RTX;
-+ }
-+
-+ /* Assignment of a structure component needs special treatment
-+ if the structure component's rtx is not simply a MEM.
-+ Assignment of an array element at a constant index, and assignment of
-+ an array element in an unaligned packed structure field, has the same
-+ problem. */
-+
-+ if (TREE_CODE (to) == COMPONENT_REF || TREE_CODE (to) == BIT_FIELD_REF
-+ || TREE_CODE (to) == ARRAY_REF || TREE_CODE (to) == ARRAY_RANGE_REF
-+ || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
-+ {
-+ enum machine_mode mode1;
-+ HOST_WIDE_INT bitsize, bitpos;
-+ rtx orig_to_rtx;
-+ tree offset;
-+ int unsignedp;
-+ int volatilep = 0;
-+ tree tem;
-+
-+ push_temp_slots ();
-+ tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
-+ &unsignedp, &volatilep);
-+
-+ /* If we are going to use store_bit_field and extract_bit_field,
-+ make sure to_rtx will be safe for multiple use. */
-+
-+ if (mode1 == VOIDmode && want_value)
-+ tem = stabilize_reference (tem);
-+
-+ orig_to_rtx = to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
-+
-+ if (offset != 0)
-+ {
-+ rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
-+
-+ if (GET_CODE (to_rtx) != MEM)
-+ abort ();
-+
-+#ifdef POINTERS_EXTEND_UNSIGNED
-+ if (GET_MODE (offset_rtx) != Pmode)
-+ offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
-+#else
-+ if (GET_MODE (offset_rtx) != ptr_mode)
-+ offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
-+#endif
-+
-+ /* A constant address in TO_RTX can have VOIDmode, we must not try
-+ to call force_reg for that case. Avoid that case. */
-+ if (GET_CODE (to_rtx) == MEM
-+ && GET_MODE (to_rtx) == BLKmode
-+ && GET_MODE (XEXP (to_rtx, 0)) != VOIDmode
-+ && bitsize > 0
-+ && (bitpos % bitsize) == 0
-+ && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
-+ && MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
-+ {
-+ to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
-+ bitpos = 0;
-+ }
-+
-+ to_rtx = offset_address (to_rtx, offset_rtx,
-+ highest_pow2_factor_for_type (TREE_TYPE (to),
-+ offset));
-+ }
-+
-+ if (GET_CODE (to_rtx) == MEM)
-+ {
-+ /* If the field is at offset zero, we could have been given the
-+ DECL_RTX of the parent struct. Don't munge it. */
-+ to_rtx = shallow_copy_rtx (to_rtx);
-+
-+ set_mem_attributes_minus_bitpos (to_rtx, to, 0, bitpos);
-+ }
-+
-+ /* Deal with volatile and readonly fields. The former is only done
-+ for MEM. Also set MEM_KEEP_ALIAS_SET_P if needed. */
-+ if (volatilep && GET_CODE (to_rtx) == MEM)
-+ {
-+ if (to_rtx == orig_to_rtx)
-+ to_rtx = copy_rtx (to_rtx);
-+ MEM_VOLATILE_P (to_rtx) = 1;
-+ }
-+
-+ if (TREE_CODE (to) == COMPONENT_REF
-+ && TREE_READONLY (TREE_OPERAND (to, 1)))
-+ {
-+ if (to_rtx == orig_to_rtx)
-+ to_rtx = copy_rtx (to_rtx);
-+ RTX_UNCHANGING_P (to_rtx) = 1;
-+ }
-+
-+ if (GET_CODE (to_rtx) == MEM && ! can_address_p (to))
-+ {
-+ if (to_rtx == orig_to_rtx)
-+ to_rtx = copy_rtx (to_rtx);
-+ MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
-+ }
-+
-+ result = store_field (to_rtx, bitsize, bitpos, mode1, from,
-+ (want_value
-+ /* Spurious cast for HPUX compiler. */
-+ ? ((enum machine_mode)
-+ TYPE_MODE (TREE_TYPE (to)))
-+ : VOIDmode),
-+ unsignedp, TREE_TYPE (tem), get_alias_set (to));
-+
-+ preserve_temp_slots (result);
-+ free_temp_slots ();
-+ pop_temp_slots ();
-+
-+ /* If the value is meaningful, convert RESULT to the proper mode.
-+ Otherwise, return nothing. */
-+ return (want_value ? convert_modes (TYPE_MODE (TREE_TYPE (to)),
-+ TYPE_MODE (TREE_TYPE (from)),
-+ result,
-+ TREE_UNSIGNED (TREE_TYPE (to)))
-+ : NULL_RTX);
-+ }
-+
-+ /* If the rhs is a function call and its value is not an aggregate,
-+ call the function before we start to compute the lhs.
-+ This is needed for correct code for cases such as
-+ val = setjmp (buf) on machines where reference to val
-+ requires loading up part of an address in a separate insn.
-+
-+ Don't do this if TO is a VAR_DECL or PARM_DECL whose DECL_RTL is REG
-+ since it might be a promoted variable where the zero- or sign- extension
-+ needs to be done. Handling this in the normal way is safe because no
-+ computation is done before the call. */
-+ if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from)
-+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
-+ && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
-+ && GET_CODE (DECL_RTL (to)) == REG))
-+ {
-+ rtx value;
-+
-+ push_temp_slots ();
-+ value = expand_expr (from, NULL_RTX, VOIDmode, 0);
-+ if (to_rtx == 0)
-+ to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
-+
-+ /* Handle calls that return values in multiple non-contiguous locations.
-+ The Irix 6 ABI has examples of this. */
-+ if (GET_CODE (to_rtx) == PARALLEL)
-+ emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)));
-+ else if (GET_MODE (to_rtx) == BLKmode)
-+ emit_block_move (to_rtx, value, expr_size (from), BLOCK_OP_NORMAL);
-+ else
-+ {
-+#ifdef POINTERS_EXTEND_UNSIGNED
-+ if (POINTER_TYPE_P (TREE_TYPE (to))
-+ && GET_MODE (to_rtx) != GET_MODE (value))
-+ value = convert_memory_address (GET_MODE (to_rtx), value);
-+#endif
-+ emit_move_insn (to_rtx, value);
-+ }
-+ preserve_temp_slots (to_rtx);
-+ free_temp_slots ();
-+ pop_temp_slots ();
-+ return want_value ? to_rtx : NULL_RTX;
-+ }
-+
-+ /* Ordinary treatment. Expand TO to get a REG or MEM rtx.
-+ Don't re-expand if it was expanded already (in COMPONENT_REF case). */
-+
-+ if (to_rtx == 0)
-+ to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
-+
-+ /* Don't move directly into a return register. */
-+ if (TREE_CODE (to) == RESULT_DECL
-+ && (GET_CODE (to_rtx) == REG || GET_CODE (to_rtx) == PARALLEL))
-+ {
-+ rtx temp;
-+
-+ push_temp_slots ();
-+ temp = expand_expr (from, 0, GET_MODE (to_rtx), 0);
-+
-+ if (GET_CODE (to_rtx) == PARALLEL)
-+ emit_group_load (to_rtx, temp, int_size_in_bytes (TREE_TYPE (from)));
-+ else
-+ emit_move_insn (to_rtx, temp);
-+
-+ preserve_temp_slots (to_rtx);
-+ free_temp_slots ();
-+ pop_temp_slots ();
-+ return want_value ? to_rtx : NULL_RTX;
-+ }
-+
-+ /* In case we are returning the contents of an object which overlaps
-+ the place the value is being stored, use a safe function when copying
-+ a value through a pointer into a structure value return block. */
-+ if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
-+ && current_function_returns_struct
-+ && !current_function_returns_pcc_struct)
-+ {
-+ rtx from_rtx, size;
-+
-+ push_temp_slots ();
-+ size = expr_size (from);
-+ from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
-+
-+ if (TARGET_MEM_FUNCTIONS)
-+ emit_library_call (memmove_libfunc, LCT_NORMAL,
-+ VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
-+ XEXP (from_rtx, 0), Pmode,
-+ convert_to_mode (TYPE_MODE (sizetype),
-+ size, TREE_UNSIGNED (sizetype)),
-+ TYPE_MODE (sizetype));
-+ else
-+ emit_library_call (bcopy_libfunc, LCT_NORMAL,
-+ VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
-+ XEXP (to_rtx, 0), Pmode,
-+ convert_to_mode (TYPE_MODE (integer_type_node),
-+ size,
-+ TREE_UNSIGNED (integer_type_node)),
-+ TYPE_MODE (integer_type_node));
-+
-+ preserve_temp_slots (to_rtx);
-+ free_temp_slots ();
-+ pop_temp_slots ();
-+ return want_value ? to_rtx : NULL_RTX;
-+ }
-+
-+ /* Compute FROM and store the value in the rtx we got. */
-+
-+ push_temp_slots ();
-+ result = store_expr (from, to_rtx, want_value);
-+ preserve_temp_slots (result);
-+ free_temp_slots ();
-+ pop_temp_slots ();
-+ return want_value ? result : NULL_RTX;
-+}
-+
-+/* Generate code for computing expression EXP,
-+ and storing the value into TARGET.
-+ TARGET may contain a QUEUED rtx.
-+
-+ If WANT_VALUE & 1 is nonzero, return a copy of the value
-+ not in TARGET, so that we can be sure to use the proper
-+ value in a containing expression even if TARGET has something
-+ else stored in it. If possible, we copy the value through a pseudo
-+ and return that pseudo. Or, if the value is constant, we try to
-+ return the constant. In some cases, we return a pseudo
-+ copied *from* TARGET.
-+
-+ If the mode is BLKmode then we may return TARGET itself.
-+ It turns out that in BLKmode it doesn't cause a problem.
-+ because C has no operators that could combine two different
-+ assignments into the same BLKmode object with different values
-+ with no sequence point. Will other languages need this to
-+ be more thorough?
-+
-+ If WANT_VALUE & 1 is 0, we return NULL, to make sure
-+ to catch quickly any cases where the caller uses the value
-+ and fails to set WANT_VALUE.
-+
-+ If WANT_VALUE & 2 is set, this is a store into a call param on the
-+ stack, and block moves may need to be treated specially. */
-+
-+rtx
-+store_expr (exp, target, want_value)
-+ tree exp;
-+ rtx target;
-+ int want_value;
-+{
-+ rtx temp;
-+ int dont_return_target = 0;
-+ int dont_store_target = 0;
-+
-+ if (VOID_TYPE_P (TREE_TYPE (exp)))
-+ {
-+ /* C++ can generate ?: expressions with a throw expression in one
-+ branch and an rvalue in the other. Here, we resolve attempts to
-+ store the throw expression's nonexistant result. */
-+ if (want_value)
-+ abort ();
-+ expand_expr (exp, const0_rtx, VOIDmode, 0);
-+ return NULL_RTX;
-+ }
-+ if (TREE_CODE (exp) == COMPOUND_EXPR)
-+ {
-+ /* Perform first part of compound expression, then assign from second
-+ part. */
-+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-+ want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
-+ emit_queue ();
-+ return store_expr (TREE_OPERAND (exp, 1), target, want_value);
-+ }
-+ else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
-+ {
-+ /* For conditional expression, get safe form of the target. Then
-+ test the condition, doing the appropriate assignment on either
-+ side. This avoids the creation of unnecessary temporaries.
-+ For non-BLKmode, it is more efficient not to do this. */
-+
-+ rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
-+
-+ emit_queue ();
-+ target = protect_from_queue (target, 1);
-+
-+ do_pending_stack_adjust ();
-+ NO_DEFER_POP;
-+ jumpifnot (TREE_OPERAND (exp, 0), lab1);
-+ start_cleanup_deferral ();
-+ store_expr (TREE_OPERAND (exp, 1), target, want_value & 2);
-+ end_cleanup_deferral ();
-+ emit_queue ();
-+ emit_jump_insn (gen_jump (lab2));
-+ emit_barrier ();
-+ emit_label (lab1);
-+ start_cleanup_deferral ();
-+ store_expr (TREE_OPERAND (exp, 2), target, want_value & 2);
-+ end_cleanup_deferral ();
-+ emit_queue ();
-+ emit_label (lab2);
-+ OK_DEFER_POP;
-+
-+ return want_value & 1 ? target : NULL_RTX;
-+ }
-+ else if (queued_subexp_p (target))
-+ /* If target contains a postincrement, let's not risk
-+ using it as the place to generate the rhs. */
-+ {
-+ if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode)
-+ {
-+ /* Expand EXP into a new pseudo. */
-+ temp = gen_reg_rtx (GET_MODE (target));
-+ temp = expand_expr (exp, temp, GET_MODE (target),
-+ (want_value & 2
-+ ? EXPAND_STACK_PARM : EXPAND_NORMAL));
-+ }
-+ else
-+ temp = expand_expr (exp, NULL_RTX, GET_MODE (target),
-+ (want_value & 2
-+ ? EXPAND_STACK_PARM : EXPAND_NORMAL));
-+
-+ /* If target is volatile, ANSI requires accessing the value
-+ *from* the target, if it is accessed. So make that happen.
-+ In no case return the target itself. */
-+ if (! MEM_VOLATILE_P (target) && (want_value & 1) != 0)
-+ dont_return_target = 1;
-+ }
-+ else if ((want_value & 1) != 0
-+ && GET_CODE (target) == MEM
-+ && ! MEM_VOLATILE_P (target)
-+ && GET_MODE (target) != BLKmode)
-+ /* If target is in memory and caller wants value in a register instead,
-+ arrange that. Pass TARGET as target for expand_expr so that,
-+ if EXP is another assignment, WANT_VALUE will be nonzero for it.
-+ We know expand_expr will not use the target in that case.
-+ Don't do this if TARGET is volatile because we are supposed
-+ to write it and then read it. */
-+ {
-+ temp = expand_expr (exp, target, GET_MODE (target),
-+ want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
-+ if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
-+ {
-+ /* If TEMP is already in the desired TARGET, only copy it from
-+ memory and don't store it there again. */
-+ if (temp == target
-+ || (rtx_equal_p (temp, target)
-+ && ! side_effects_p (temp) && ! side_effects_p (target)))
-+ dont_store_target = 1;
-+ temp = copy_to_reg (temp);
-+ }
-+ dont_return_target = 1;
-+ }
-+ else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
-+ /* If this is a scalar in a register that is stored in a wider mode
-+ than the declared mode, compute the result into its declared mode
-+ and then convert to the wider mode. Our value is the computed
-+ expression. */
-+ {
-+ rtx inner_target = 0;
-+
-+ /* If we don't want a value, we can do the conversion inside EXP,
-+ which will often result in some optimizations. Do the conversion
-+ in two steps: first change the signedness, if needed, then
-+ the extend. But don't do this if the type of EXP is a subtype
-+ of something else since then the conversion might involve
-+ more than just converting modes. */
-+ if ((want_value & 1) == 0
-+ && INTEGRAL_TYPE_P (TREE_TYPE (exp))
-+ && TREE_TYPE (TREE_TYPE (exp)) == 0)
-+ {
-+ if (TREE_UNSIGNED (TREE_TYPE (exp))
-+ != SUBREG_PROMOTED_UNSIGNED_P (target))
-+ exp = convert
-+ ((*lang_hooks.types.signed_or_unsigned_type)
-+ (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)), exp);
-+
-+ exp = convert ((*lang_hooks.types.type_for_mode)
-+ (GET_MODE (SUBREG_REG (target)),
-+ SUBREG_PROMOTED_UNSIGNED_P (target)),
-+ exp);
-+
-+ inner_target = SUBREG_REG (target);
-+ }
-+
-+ temp = expand_expr (exp, inner_target, VOIDmode,
-+ want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
-+
-+ /* If TEMP is a volatile MEM and we want a result value, make
-+ the access now so it gets done only once. Likewise if
-+ it contains TARGET. */
-+ if (GET_CODE (temp) == MEM && (want_value & 1) != 0
-+ && (MEM_VOLATILE_P (temp)
-+ || reg_mentioned_p (SUBREG_REG (target), XEXP (temp, 0))))
-+ temp = copy_to_reg (temp);
-+
-+ /* If TEMP is a VOIDmode constant, use convert_modes to make
-+ sure that we properly convert it. */
-+ if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode)
-+ {
-+ temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
-+ temp, SUBREG_PROMOTED_UNSIGNED_P (target));
-+ temp = convert_modes (GET_MODE (SUBREG_REG (target)),
-+ GET_MODE (target), temp,
-+ SUBREG_PROMOTED_UNSIGNED_P (target));
-+ }
-+
-+ convert_move (SUBREG_REG (target), temp,
-+ SUBREG_PROMOTED_UNSIGNED_P (target));
-+
-+ /* If we promoted a constant, change the mode back down to match
-+ target. Otherwise, the caller might get confused by a result whose
-+ mode is larger than expected. */
-+
-+ if ((want_value & 1) != 0 && GET_MODE (temp) != GET_MODE (target))
-+ {
-+ if (GET_MODE (temp) != VOIDmode)
-+ {
-+ temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
-+ SUBREG_PROMOTED_VAR_P (temp) = 1;
-+ SUBREG_PROMOTED_UNSIGNED_SET (temp,
-+ SUBREG_PROMOTED_UNSIGNED_P (target));
-+ }
-+ else
-+ temp = convert_modes (GET_MODE (target),
-+ GET_MODE (SUBREG_REG (target)),
-+ temp, SUBREG_PROMOTED_UNSIGNED_P (target));
-+ }
-+
-+ return want_value & 1 ? temp : NULL_RTX;
-+ }
-+ else
-+ {
-+ temp = expand_expr (exp, target, GET_MODE (target),
-+ want_value & 2 ? EXPAND_STACK_PARM : EXPAND_NORMAL);
-+ /* Return TARGET if it's a specified hardware register.
-+ If TARGET is a volatile mem ref, either return TARGET
-+ or return a reg copied *from* TARGET; ANSI requires this.
-+
-+ Otherwise, if TEMP is not TARGET, return TEMP
-+ if it is constant (for efficiency),
-+ or if we really want the correct value. */
-+ if (!(target && GET_CODE (target) == REG
-+ && REGNO (target) < FIRST_PSEUDO_REGISTER)
-+ && !(GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
-+ && ! rtx_equal_p (temp, target)
-+ && (CONSTANT_P (temp) || (want_value & 1) != 0))
-+ dont_return_target = 1;
-+ }
-+
-+ /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not
-+ the same as that of TARGET, adjust the constant. This is needed, for
-+ example, in case it is a CONST_DOUBLE and we want only a word-sized
-+ value. */
-+ if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode
-+ && TREE_CODE (exp) != ERROR_MARK
-+ && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
-+ temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
-+ temp, TREE_UNSIGNED (TREE_TYPE (exp)));
-+
-+ /* If value was not generated in the target, store it there.
-+ Convert the value to TARGET's type first if necessary.
-+ If TEMP and TARGET compare equal according to rtx_equal_p, but
-+ one or both of them are volatile memory refs, we have to distinguish
-+ two cases:
-+ - expand_expr has used TARGET. In this case, we must not generate
-+ another copy. This can be detected by TARGET being equal according
-+ to == .
-+ - expand_expr has not used TARGET - that means that the source just
-+ happens to have the same RTX form. Since temp will have been created
-+ by expand_expr, it will compare unequal according to == .
-+ We must generate a copy in this case, to reach the correct number
-+ of volatile memory references. */
-+
-+ if ((! rtx_equal_p (temp, target)
-+ || (temp != target && (side_effects_p (temp)
-+ || side_effects_p (target))))
-+ && TREE_CODE (exp) != ERROR_MARK
-+ && ! dont_store_target
-+ /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET,
-+ but TARGET is not valid memory reference, TEMP will differ
-+ from TARGET although it is really the same location. */
-+ && (TREE_CODE_CLASS (TREE_CODE (exp)) != 'd'
-+ || target != DECL_RTL_IF_SET (exp))
-+ /* If there's nothing to copy, don't bother. Don't call expr_size
-+ unless necessary, because some front-ends (C++) expr_size-hook
-+ aborts on objects that are not supposed to be bit-copied or
-+ bit-initialized. */
-+ && expr_size (exp) != const0_rtx)
-+ {
-+ target = protect_from_queue (target, 1);
-+ if (GET_MODE (temp) != GET_MODE (target)
-+ && GET_MODE (temp) != VOIDmode)
-+ {
-+ int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
-+ if (dont_return_target)
-+ {
-+ /* In this case, we will return TEMP,
-+ so make sure it has the proper mode.
-+ But don't forget to store the value into TARGET. */
-+ temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
-+ emit_move_insn (target, temp);
-+ }
-+ else
-+ convert_move (target, temp, unsignedp);
-+ }
-+
-+ else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST)
-+ {
-+ /* Handle copying a string constant into an array. The string
-+ constant may be shorter than the array. So copy just the string's
-+ actual length, and clear the rest. First get the size of the data
-+ type of the string, which is actually the size of the target. */
-+ rtx size = expr_size (exp);
-+
-+ if (GET_CODE (size) == CONST_INT
-+ && INTVAL (size) < TREE_STRING_LENGTH (exp))
-+ emit_block_move (target, temp, size,
-+ (want_value & 2
-+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
-+ else
-+ {
-+ /* Compute the size of the data to copy from the string. */
-+ tree copy_size
-+ = size_binop (MIN_EXPR,
-+ make_tree (sizetype, size),
-+ size_int (TREE_STRING_LENGTH (exp)));
-+ rtx copy_size_rtx
-+ = expand_expr (copy_size, NULL_RTX, VOIDmode,
-+ (want_value & 2
-+ ? EXPAND_STACK_PARM : EXPAND_NORMAL));
-+ rtx label = 0;
-+
-+ /* Copy that much. */
-+ copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx,
-+ TREE_UNSIGNED (sizetype));
-+ emit_block_move (target, temp, copy_size_rtx,
-+ (want_value & 2
-+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
-+
-+ /* Figure out how much is left in TARGET that we have to clear.
-+ Do all calculations in ptr_mode. */
-+ if (GET_CODE (copy_size_rtx) == CONST_INT)
-+ {
-+ size = plus_constant (size, -INTVAL (copy_size_rtx));
-+ target = adjust_address (target, BLKmode,
-+ INTVAL (copy_size_rtx));
-+ }
-+ else
-+ {
-+ size = expand_binop (TYPE_MODE (sizetype), sub_optab, size,
-+ copy_size_rtx, NULL_RTX, 0,
-+ OPTAB_LIB_WIDEN);
-+
-+#ifdef POINTERS_EXTEND_UNSIGNED
-+ if (GET_MODE (copy_size_rtx) != Pmode)
-+ copy_size_rtx = convert_to_mode (Pmode, copy_size_rtx,
-+ TREE_UNSIGNED (sizetype));
-+#endif
-+
-+ target = offset_address (target, copy_size_rtx,
-+ highest_pow2_factor (copy_size));
-+ label = gen_label_rtx ();
-+ emit_cmp_and_jump_insns (size, const0_rtx, LT, NULL_RTX,
-+ GET_MODE (size), 0, label);
-+ }
-+
-+ if (size != const0_rtx)
-+ clear_storage (target, size);
-+
-+ if (label)
-+ emit_label (label);
-+ }
-+ }
-+ /* Handle calls that return values in multiple non-contiguous locations.
-+ The Irix 6 ABI has examples of this. */
-+ else if (GET_CODE (target) == PARALLEL)
-+ emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)));
-+ else if (GET_MODE (temp) == BLKmode)
-+ emit_block_move (target, temp, expr_size (exp),
-+ (want_value & 2
-+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
-+ else
-+ emit_move_insn (target, temp);
-+ }
-+
-+ /* If we don't want a value, return NULL_RTX. */
-+ if ((want_value & 1) == 0)
-+ return NULL_RTX;
-+
-+ /* If we are supposed to return TEMP, do so as long as it isn't a MEM.
-+ ??? The latter test doesn't seem to make sense. */
-+ else if (dont_return_target && GET_CODE (temp) != MEM)
-+ return temp;
-+
-+ /* Return TARGET itself if it is a hard register. */
-+ else if ((want_value & 1) != 0
-+ && GET_MODE (target) != BLKmode
-+ && ! (GET_CODE (target) == REG
-+ && REGNO (target) < FIRST_PSEUDO_REGISTER))
-+ return copy_to_reg (target);
-+
-+ else
-+ return target;
-+}
-+\f
-+/* Return 1 if EXP just contains zeros. */
-+
-+static int
-+is_zeros_p (exp)
-+ tree exp;
-+{
-+ tree elt;
-+
-+ switch (TREE_CODE (exp))
-+ {
-+ case CONVERT_EXPR:
-+ case NOP_EXPR:
-+ case NON_LVALUE_EXPR:
-+ case VIEW_CONVERT_EXPR:
-+ return is_zeros_p (TREE_OPERAND (exp, 0));
-+
-+ case INTEGER_CST:
-+ return integer_zerop (exp);
-+
-+ case COMPLEX_CST:
-+ return
-+ is_zeros_p (TREE_REALPART (exp)) && is_zeros_p (TREE_IMAGPART (exp));
-+
-+ case REAL_CST:
-+ return REAL_VALUES_IDENTICAL (TREE_REAL_CST (exp), dconst0);
-+
-+ case VECTOR_CST:
-+ for (elt = TREE_VECTOR_CST_ELTS (exp); elt;
-+ elt = TREE_CHAIN (elt))
-+ if (!is_zeros_p (TREE_VALUE (elt)))
-+ return 0;
-+
-+ return 1;
-+
-+ case CONSTRUCTOR:
-+ if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
-+ return CONSTRUCTOR_ELTS (exp) == NULL_TREE;
-+ for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
-+ if (! is_zeros_p (TREE_VALUE (elt)))
-+ return 0;
-+
-+ return 1;
-+
-+ default:
-+ return 0;
-+ }
-+}
-+
-+/* Return 1 if EXP contains mostly (3/4) zeros. */
-+
-+static int
-+mostly_zeros_p (exp)
-+ tree exp;
-+{
-+ if (TREE_CODE (exp) == CONSTRUCTOR)
-+ {
-+ int elts = 0, zeros = 0;
-+ tree elt = CONSTRUCTOR_ELTS (exp);
-+ if (TREE_TYPE (exp) && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
-+ {
-+ /* If there are no ranges of true bits, it is all zero. */
-+ return elt == NULL_TREE;
-+ }
-+ for (; elt; elt = TREE_CHAIN (elt))
-+ {
-+ /* We do not handle the case where the index is a RANGE_EXPR,
-+ so the statistic will be somewhat inaccurate.
-+ We do make a more accurate count in store_constructor itself,
-+ so since this function is only used for nested array elements,
-+ this should be close enough. */
-+ if (mostly_zeros_p (TREE_VALUE (elt)))
-+ zeros++;
-+ elts++;
-+ }
-+
-+ return 4 * zeros >= 3 * elts;
-+ }
-+
-+ return is_zeros_p (exp);
-+}
-+\f
-+/* Helper function for store_constructor.
-+ TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field.
-+ TYPE is the type of the CONSTRUCTOR, not the element type.
-+ CLEARED is as for store_constructor.
-+ ALIAS_SET is the alias set to use for any stores.
-+
-+ This provides a recursive shortcut back to store_constructor when it isn't
-+ necessary to go through store_field. This is so that we can pass through
-+ the cleared field to let store_constructor know that we may not have to
-+ clear a substructure if the outer structure has already been cleared. */
-+
-+static void
-+store_constructor_field (target, bitsize, bitpos, mode, exp, type, cleared,
-+ alias_set)
-+ rtx target;
-+ unsigned HOST_WIDE_INT bitsize;
-+ HOST_WIDE_INT bitpos;
-+ enum machine_mode mode;
-+ tree exp, type;
-+ int cleared;
-+ int alias_set;
-+{
-+ if (TREE_CODE (exp) == CONSTRUCTOR
-+ && bitpos % BITS_PER_UNIT == 0
-+ /* If we have a nonzero bitpos for a register target, then we just
-+ let store_field do the bitfield handling. This is unlikely to
-+ generate unnecessary clear instructions anyways. */
-+ && (bitpos == 0 || GET_CODE (target) == MEM))
-+ {
-+ if (GET_CODE (target) == MEM)
-+ target
-+ = adjust_address (target,
-+ GET_MODE (target) == BLKmode
-+ || 0 != (bitpos
-+ % GET_MODE_ALIGNMENT (GET_MODE (target)))
-+ ? BLKmode : VOIDmode, bitpos / BITS_PER_UNIT);
-+
-+
-+ /* Update the alias set, if required. */
-+ if (GET_CODE (target) == MEM && ! MEM_KEEP_ALIAS_SET_P (target)
-+ && MEM_ALIAS_SET (target) != 0)
-+ {
-+ target = copy_rtx (target);
-+ set_mem_alias_set (target, alias_set);
-+ }
-+
-+ store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
-+ }
-+ else
-+ store_field (target, bitsize, bitpos, mode, exp, VOIDmode, 0, type,
-+ alias_set);
-+}
-+
-+/* Store the value of constructor EXP into the rtx TARGET.
-+ TARGET is either a REG or a MEM; we know it cannot conflict, since
-+ safe_from_p has been called.
-+ CLEARED is true if TARGET is known to have been zero'd.
-+ SIZE is the number of bytes of TARGET we are allowed to modify: this
-+ may not be the same as the size of EXP if we are assigning to a field
-+ which has been packed to exclude padding bits. */
-+
-+static void
-+store_constructor (exp, target, cleared, size)
-+ tree exp;
-+ rtx target;
-+ int cleared;
-+ HOST_WIDE_INT size;
-+{
-+ tree type = TREE_TYPE (exp);
-+#ifdef WORD_REGISTER_OPERATIONS
-+ HOST_WIDE_INT exp_size = int_size_in_bytes (type);
-+#endif
-+
-+ if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
-+ || TREE_CODE (type) == QUAL_UNION_TYPE)
-+ {
-+ tree elt;
-+
-+ /* If size is zero or the target is already cleared, do nothing. */
-+ if (size == 0 || cleared)
-+ cleared = 1;
-+ /* We either clear the aggregate or indicate the value is dead. */
-+ else if ((TREE_CODE (type) == UNION_TYPE
-+ || TREE_CODE (type) == QUAL_UNION_TYPE)
-+ && ! CONSTRUCTOR_ELTS (exp))
-+ /* If the constructor is empty, clear the union. */
-+ {
-+ clear_storage (target, expr_size (exp));
-+ cleared = 1;
-+ }
-+
-+ /* If we are building a static constructor into a register,
-+ set the initial value as zero so we can fold the value into
-+ a constant. But if more than one register is involved,
-+ this probably loses. */
-+ else if (GET_CODE (target) == REG && TREE_STATIC (exp)
-+ && GET_MODE_SIZE (GET_MODE (target)) <= UNITS_PER_WORD)
-+ {
-+ emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
-+ cleared = 1;
-+ }
-+
-+ /* If the constructor has fewer fields than the structure
-+ or if we are initializing the structure to mostly zeros,
-+ clear the whole structure first. Don't do this if TARGET is a
-+ register whose mode size isn't equal to SIZE since clear_storage
-+ can't handle this case. */
-+ else if (((list_length (CONSTRUCTOR_ELTS (exp)) != fields_length (type))
-+ || mostly_zeros_p (exp))
-+ && (GET_CODE (target) != REG
-+ || ((HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target))
-+ == size)))
-+ {
-+ clear_storage (target, GEN_INT (size));
-+ cleared = 1;
-+ }
-+
-+ if (! cleared)
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
-+
-+ /* Store each element of the constructor into
-+ the corresponding field of TARGET. */
-+
-+ for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
-+ {
-+ tree field = TREE_PURPOSE (elt);
-+ tree value = TREE_VALUE (elt);
-+ enum machine_mode mode;
-+ HOST_WIDE_INT bitsize;
-+ HOST_WIDE_INT bitpos = 0;
-+ int unsignedp;
-+ tree offset;
-+ rtx to_rtx = target;
-+
-+ /* Just ignore missing fields.
-+ We cleared the whole structure, above,
-+ if any fields are missing. */
-+ if (field == 0)
-+ continue;
-+
-+ if (cleared && is_zeros_p (value))
-+ continue;
-+
-+ if (host_integerp (DECL_SIZE (field), 1))
-+ bitsize = tree_low_cst (DECL_SIZE (field), 1);
-+ else
-+ bitsize = -1;
-+
-+ unsignedp = TREE_UNSIGNED (field);
-+ mode = DECL_MODE (field);
-+ if (DECL_BIT_FIELD (field))
-+ mode = VOIDmode;
-+
-+ offset = DECL_FIELD_OFFSET (field);
-+ if (host_integerp (offset, 0)
-+ && host_integerp (bit_position (field), 0))
-+ {
-+ bitpos = int_bit_position (field);
-+ offset = 0;
-+ }
-+ else
-+ bitpos = tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
-+
-+ if (offset)
-+ {
-+ rtx offset_rtx;
-+
-+ if (contains_placeholder_p (offset))
-+ offset = build (WITH_RECORD_EXPR, sizetype,
-+ offset, make_tree (TREE_TYPE (exp), target));
-+
-+ offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
-+ if (GET_CODE (to_rtx) != MEM)
-+ abort ();
-+
-+#ifdef POINTERS_EXTEND_UNSIGNED
-+ if (GET_MODE (offset_rtx) != Pmode)
-+ offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
-+#else
-+ if (GET_MODE (offset_rtx) != ptr_mode)
-+ offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
-+#endif
-+
-+ to_rtx = offset_address (to_rtx, offset_rtx,
-+ highest_pow2_factor (offset));
-+ }
-+
-+ if (TREE_READONLY (field))
-+ {
-+ if (GET_CODE (to_rtx) == MEM)
-+ to_rtx = copy_rtx (to_rtx);
-+
-+ RTX_UNCHANGING_P (to_rtx) = 1;
-+ }
-+
-+#ifdef WORD_REGISTER_OPERATIONS
-+ /* If this initializes a field that is smaller than a word, at the
-+ start of a word, try to widen it to a full word.
-+ This special case allows us to output C++ member function
-+ initializations in a form that the optimizers can understand. */
-+ if (GET_CODE (target) == REG
-+ && bitsize < BITS_PER_WORD
-+ && bitpos % BITS_PER_WORD == 0
-+ && GET_MODE_CLASS (mode) == MODE_INT
-+ && TREE_CODE (value) == INTEGER_CST
-+ && exp_size >= 0
-+ && bitpos + BITS_PER_WORD <= exp_size * BITS_PER_UNIT)
-+ {
-+ tree type = TREE_TYPE (value);
-+
-+ if (TYPE_PRECISION (type) < BITS_PER_WORD)
-+ {
-+ type = (*lang_hooks.types.type_for_size)
-+ (BITS_PER_WORD, TREE_UNSIGNED (type));
-+ value = convert (type, value);
-+ }
-+
-+ if (BYTES_BIG_ENDIAN)
-+ value
-+ = fold (build (LSHIFT_EXPR, type, value,
-+ build_int_2 (BITS_PER_WORD - bitsize, 0)));
-+ bitsize = BITS_PER_WORD;
-+ mode = word_mode;
-+ }
-+#endif
-+
-+ if (GET_CODE (to_rtx) == MEM && !MEM_KEEP_ALIAS_SET_P (to_rtx)
-+ && DECL_NONADDRESSABLE_P (field))
-+ {
-+ to_rtx = copy_rtx (to_rtx);
-+ MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
-+ }
-+
-+ store_constructor_field (to_rtx, bitsize, bitpos, mode,
-+ value, type, cleared,
-+ get_alias_set (TREE_TYPE (field)));
-+ }
-+ }
-+ else if (TREE_CODE (type) == ARRAY_TYPE
-+ || TREE_CODE (type) == VECTOR_TYPE)
-+ {
-+ tree elt;
-+ int i;
-+ int need_to_clear;
-+ tree domain = TYPE_DOMAIN (type);
-+ tree elttype = TREE_TYPE (type);
-+ int const_bounds_p;
-+ HOST_WIDE_INT minelt = 0;
-+ HOST_WIDE_INT maxelt = 0;
-+
-+ /* Vectors are like arrays, but the domain is stored via an array
-+ type indirectly. */
-+ if (TREE_CODE (type) == VECTOR_TYPE)
-+ {
-+ /* Note that although TYPE_DEBUG_REPRESENTATION_TYPE uses
-+ the same field as TYPE_DOMAIN, we are not guaranteed that
-+ it always will. */
-+ domain = TYPE_DEBUG_REPRESENTATION_TYPE (type);
-+ domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain)));
-+ }
-+
-+ const_bounds_p = (TYPE_MIN_VALUE (domain)
-+ && TYPE_MAX_VALUE (domain)
-+ && host_integerp (TYPE_MIN_VALUE (domain), 0)
-+ && host_integerp (TYPE_MAX_VALUE (domain), 0));
-+
-+ /* If we have constant bounds for the range of the type, get them. */
-+ if (const_bounds_p)
-+ {
-+ minelt = tree_low_cst (TYPE_MIN_VALUE (domain), 0);
-+ maxelt = tree_low_cst (TYPE_MAX_VALUE (domain), 0);
-+ }
-+
-+ /* If the constructor has fewer elements than the array,
-+ clear the whole array first. Similarly if this is
-+ static constructor of a non-BLKmode object. */
-+ if (cleared || (GET_CODE (target) == REG && TREE_STATIC (exp)))
-+ need_to_clear = 1;
-+ else
-+ {
-+ HOST_WIDE_INT count = 0, zero_count = 0;
-+ need_to_clear = ! const_bounds_p;
-+
-+ /* This loop is a more accurate version of the loop in
-+ mostly_zeros_p (it handles RANGE_EXPR in an index).
-+ It is also needed to check for missing elements. */
-+ for (elt = CONSTRUCTOR_ELTS (exp);
-+ elt != NULL_TREE && ! need_to_clear;
-+ elt = TREE_CHAIN (elt))
-+ {
-+ tree index = TREE_PURPOSE (elt);
-+ HOST_WIDE_INT this_node_count;
-+
-+ if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
-+ {
-+ tree lo_index = TREE_OPERAND (index, 0);
-+ tree hi_index = TREE_OPERAND (index, 1);
-+
-+ if (! host_integerp (lo_index, 1)
-+ || ! host_integerp (hi_index, 1))
-+ {
-+ need_to_clear = 1;
-+ break;
-+ }
-+
-+ this_node_count = (tree_low_cst (hi_index, 1)
-+ - tree_low_cst (lo_index, 1) + 1);
-+ }
-+ else
-+ this_node_count = 1;
-+
-+ count += this_node_count;
-+ if (mostly_zeros_p (TREE_VALUE (elt)))
-+ zero_count += this_node_count;
-+ }
-+
-+ /* Clear the entire array first if there are any missing elements,
-+ or if the incidence of zero elements is >= 75%. */
-+ if (! need_to_clear
-+ && (count < maxelt - minelt + 1 || 4 * zero_count >= 3 * count))
-+ need_to_clear = 1;
-+ }
-+
-+ if (need_to_clear && size > 0)
-+ {
-+ if (! cleared)
-+ {
-+ if (REG_P (target))
-+ emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
-+ else
-+ clear_storage (target, GEN_INT (size));
-+ }
-+ cleared = 1;
-+ }
-+ else if (REG_P (target))
-+ /* Inform later passes that the old value is dead. */
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
-+
-+ /* Store each element of the constructor into
-+ the corresponding element of TARGET, determined
-+ by counting the elements. */
-+ for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
-+ elt;
-+ elt = TREE_CHAIN (elt), i++)
-+ {
-+ enum machine_mode mode;
-+ HOST_WIDE_INT bitsize;
-+ HOST_WIDE_INT bitpos;
-+ int unsignedp;
-+ tree value = TREE_VALUE (elt);
-+ tree index = TREE_PURPOSE (elt);
-+ rtx xtarget = target;
-+
-+ if (cleared && is_zeros_p (value))
-+ continue;
-+
-+ unsignedp = TREE_UNSIGNED (elttype);
-+ mode = TYPE_MODE (elttype);
-+ if (mode == BLKmode)
-+ bitsize = (host_integerp (TYPE_SIZE (elttype), 1)
-+ ? tree_low_cst (TYPE_SIZE (elttype), 1)
-+ : -1);
-+ else
-+ bitsize = GET_MODE_BITSIZE (mode);
-+
-+ if (index != NULL_TREE && TREE_CODE (index) == RANGE_EXPR)
-+ {
-+ tree lo_index = TREE_OPERAND (index, 0);
-+ tree hi_index = TREE_OPERAND (index, 1);
-+ rtx index_r, pos_rtx, hi_r, loop_top, loop_end;
-+ struct nesting *loop;
-+ HOST_WIDE_INT lo, hi, count;
-+ tree position;
-+
-+ /* If the range is constant and "small", unroll the loop. */
-+ if (const_bounds_p
-+ && host_integerp (lo_index, 0)
-+ && host_integerp (hi_index, 0)
-+ && (lo = tree_low_cst (lo_index, 0),
-+ hi = tree_low_cst (hi_index, 0),
-+ count = hi - lo + 1,
-+ (GET_CODE (target) != MEM
-+ || count <= 2
-+ || (host_integerp (TYPE_SIZE (elttype), 1)
-+ && (tree_low_cst (TYPE_SIZE (elttype), 1) * count
-+ <= 40 * 8)))))
-+ {
-+ lo -= minelt; hi -= minelt;
-+ for (; lo <= hi; lo++)
-+ {
-+ bitpos = lo * tree_low_cst (TYPE_SIZE (elttype), 0);
-+
-+ if (GET_CODE (target) == MEM
-+ && !MEM_KEEP_ALIAS_SET_P (target)
-+ && TREE_CODE (type) == ARRAY_TYPE
-+ && TYPE_NONALIASED_COMPONENT (type))
-+ {
-+ target = copy_rtx (target);
-+ MEM_KEEP_ALIAS_SET_P (target) = 1;
-+ }
-+
-+ store_constructor_field
-+ (target, bitsize, bitpos, mode, value, type, cleared,
-+ get_alias_set (elttype));
-+ }
-+ }
-+ else
-+ {
-+ hi_r = expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
-+ loop_top = gen_label_rtx ();
-+ loop_end = gen_label_rtx ();
-+
-+ unsignedp = TREE_UNSIGNED (domain);
-+
-+ index = build_decl (VAR_DECL, NULL_TREE, domain);
-+
-+ index_r
-+ = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
-+ &unsignedp, 0));
-+ SET_DECL_RTL (index, index_r);
-+ if (TREE_CODE (value) == SAVE_EXPR
-+ && SAVE_EXPR_RTL (value) == 0)
-+ {
-+ /* Make sure value gets expanded once before the
-+ loop. */
-+ expand_expr (value, const0_rtx, VOIDmode, 0);
-+ emit_queue ();
-+ }
-+ store_expr (lo_index, index_r, 0);
-+ loop = expand_start_loop (0);
-+
-+ /* Assign value to element index. */
-+ position
-+ = convert (ssizetype,
-+ fold (build (MINUS_EXPR, TREE_TYPE (index),
-+ index, TYPE_MIN_VALUE (domain))));
-+ position = size_binop (MULT_EXPR, position,
-+ convert (ssizetype,
-+ TYPE_SIZE_UNIT (elttype)));
-+
-+ pos_rtx = expand_expr (position, 0, VOIDmode, 0);
-+ xtarget = offset_address (target, pos_rtx,
-+ highest_pow2_factor (position));
-+ xtarget = adjust_address (xtarget, mode, 0);
-+ if (TREE_CODE (value) == CONSTRUCTOR)
-+ store_constructor (value, xtarget, cleared,
-+ bitsize / BITS_PER_UNIT);
-+ else
-+ store_expr (value, xtarget, 0);
-+
-+ expand_exit_loop_if_false (loop,
-+ build (LT_EXPR, integer_type_node,
-+ index, hi_index));
-+
-+ expand_increment (build (PREINCREMENT_EXPR,
-+ TREE_TYPE (index),
-+ index, integer_one_node), 0, 0);
-+ expand_end_loop ();
-+ emit_label (loop_end);
-+ }
-+ }
-+ else if ((index != 0 && ! host_integerp (index, 0))
-+ || ! host_integerp (TYPE_SIZE (elttype), 1))
-+ {
-+ tree position;
-+
-+ if (index == 0)
-+ index = ssize_int (1);
-+
-+ if (minelt)
-+ index = convert (ssizetype,
-+ fold (build (MINUS_EXPR, index,
-+ TYPE_MIN_VALUE (domain))));
-+
-+ position = size_binop (MULT_EXPR, index,
-+ convert (ssizetype,
-+ TYPE_SIZE_UNIT (elttype)));
-+ xtarget = offset_address (target,
-+ expand_expr (position, 0, VOIDmode, 0),
-+ highest_pow2_factor (position));
-+ xtarget = adjust_address (xtarget, mode, 0);
-+ store_expr (value, xtarget, 0);
-+ }
-+ else
-+ {
-+ if (index != 0)
-+ bitpos = ((tree_low_cst (index, 0) - minelt)
-+ * tree_low_cst (TYPE_SIZE (elttype), 1));
-+ else
-+ bitpos = (i * tree_low_cst (TYPE_SIZE (elttype), 1));
-+
-+ if (GET_CODE (target) == MEM && !MEM_KEEP_ALIAS_SET_P (target)
-+ && TREE_CODE (type) == ARRAY_TYPE
-+ && TYPE_NONALIASED_COMPONENT (type))
-+ {
-+ target = copy_rtx (target);
-+ MEM_KEEP_ALIAS_SET_P (target) = 1;
-+ }
-+
-+ store_constructor_field (target, bitsize, bitpos, mode, value,
-+ type, cleared, get_alias_set (elttype));
-+
-+ }
-+ }
-+ }
-+
-+ /* Set constructor assignments. */
-+ else if (TREE_CODE (type) == SET_TYPE)
-+ {
-+ tree elt = CONSTRUCTOR_ELTS (exp);
-+ unsigned HOST_WIDE_INT nbytes = int_size_in_bytes (type), nbits;
-+ tree domain = TYPE_DOMAIN (type);
-+ tree domain_min, domain_max, bitlength;
-+
-+ /* The default implementation strategy is to extract the constant
-+ parts of the constructor, use that to initialize the target,
-+ and then "or" in whatever non-constant ranges we need in addition.
-+
-+ If a large set is all zero or all ones, it is
-+ probably better to set it using memset (if available) or bzero.
-+ Also, if a large set has just a single range, it may also be
-+ better to first clear all the first clear the set (using
-+ bzero/memset), and set the bits we want. */
-+
-+ /* Check for all zeros. */
-+ if (elt == NULL_TREE && size > 0)
-+ {
-+ if (!cleared)
-+ clear_storage (target, GEN_INT (size));
-+ return;
-+ }
-+
-+ domain_min = convert (sizetype, TYPE_MIN_VALUE (domain));
-+ domain_max = convert (sizetype, TYPE_MAX_VALUE (domain));
-+ bitlength = size_binop (PLUS_EXPR,
-+ size_diffop (domain_max, domain_min),
-+ ssize_int (1));
-+
-+ nbits = tree_low_cst (bitlength, 1);
-+
-+ /* For "small" sets, or "medium-sized" (up to 32 bytes) sets that
-+ are "complicated" (more than one range), initialize (the
-+ constant parts) by copying from a constant. */
-+ if (GET_MODE (target) != BLKmode || nbits <= 2 * BITS_PER_WORD
-+ || (nbytes <= 32 && TREE_CHAIN (elt) != NULL_TREE))
-+ {
-+ unsigned int set_word_size = TYPE_ALIGN (TREE_TYPE (exp));
-+ enum machine_mode mode = mode_for_size (set_word_size, MODE_INT, 1);
-+ char *bit_buffer = (char *) alloca (nbits);
-+ HOST_WIDE_INT word = 0;
-+ unsigned int bit_pos = 0;
-+ unsigned int ibit = 0;
-+ unsigned int offset = 0; /* In bytes from beginning of set. */
-+
-+ elt = get_set_constructor_bits (exp, bit_buffer, nbits);
-+ for (;;)
-+ {
-+ if (bit_buffer[ibit])
-+ {
-+ if (BYTES_BIG_ENDIAN)
-+ word |= (1 << (set_word_size - 1 - bit_pos));
-+ else
-+ word |= 1 << bit_pos;
-+ }
-+
-+ bit_pos++; ibit++;
-+ if (bit_pos >= set_word_size || ibit == nbits)
-+ {
-+ if (word != 0 || ! cleared)
-+ {
-+ rtx datum = GEN_INT (word);
-+ rtx to_rtx;
-+
-+ /* The assumption here is that it is safe to use
-+ XEXP if the set is multi-word, but not if
-+ it's single-word. */
-+ if (GET_CODE (target) == MEM)
-+ to_rtx = adjust_address (target, mode, offset);
-+ else if (offset == 0)
-+ to_rtx = target;
-+ else
-+ abort ();
-+ emit_move_insn (to_rtx, datum);
-+ }
-+
-+ if (ibit == nbits)
-+ break;
-+ word = 0;
-+ bit_pos = 0;
-+ offset += set_word_size / BITS_PER_UNIT;
-+ }
-+ }
-+ }
-+ else if (!cleared)
-+ /* Don't bother clearing storage if the set is all ones. */
-+ if (TREE_CHAIN (elt) != NULL_TREE
-+ || (TREE_PURPOSE (elt) == NULL_TREE
-+ ? nbits != 1
-+ : ( ! host_integerp (TREE_VALUE (elt), 0)
-+ || ! host_integerp (TREE_PURPOSE (elt), 0)
-+ || (tree_low_cst (TREE_VALUE (elt), 0)
-+ - tree_low_cst (TREE_PURPOSE (elt), 0) + 1
-+ != (HOST_WIDE_INT) nbits))))
-+ clear_storage (target, expr_size (exp));
-+
-+ for (; elt != NULL_TREE; elt = TREE_CHAIN (elt))
-+ {
-+ /* Start of range of element or NULL. */
-+ tree startbit = TREE_PURPOSE (elt);
-+ /* End of range of element, or element value. */
-+ tree endbit = TREE_VALUE (elt);
-+ HOST_WIDE_INT startb, endb;
-+ rtx bitlength_rtx, startbit_rtx, endbit_rtx, targetx;
-+
-+ bitlength_rtx = expand_expr (bitlength,
-+ NULL_RTX, MEM, EXPAND_CONST_ADDRESS);
-+
-+ /* Handle non-range tuple element like [ expr ]. */
-+ if (startbit == NULL_TREE)
-+ {
-+ startbit = save_expr (endbit);
-+ endbit = startbit;
-+ }
-+
-+ startbit = convert (sizetype, startbit);
-+ endbit = convert (sizetype, endbit);
-+ if (! integer_zerop (domain_min))
-+ {
-+ startbit = size_binop (MINUS_EXPR, startbit, domain_min);
-+ endbit = size_binop (MINUS_EXPR, endbit, domain_min);
-+ }
-+ startbit_rtx = expand_expr (startbit, NULL_RTX, MEM,
-+ EXPAND_CONST_ADDRESS);
-+ endbit_rtx = expand_expr (endbit, NULL_RTX, MEM,
-+ EXPAND_CONST_ADDRESS);
-+
-+ if (REG_P (target))
-+ {
-+ targetx
-+ = assign_temp
-+ ((build_qualified_type ((*lang_hooks.types.type_for_mode)
-+ (GET_MODE (target), 0),
-+ TYPE_QUAL_CONST)),
-+ 0, 1, 1);
-+ emit_move_insn (targetx, target);
-+ }
-+
-+ else if (GET_CODE (target) == MEM)
-+ targetx = target;
-+ else
-+ abort ();
-+
-+ /* Optimization: If startbit and endbit are constants divisible
-+ by BITS_PER_UNIT, call memset instead. */
-+ if (TARGET_MEM_FUNCTIONS
-+ && TREE_CODE (startbit) == INTEGER_CST
-+ && TREE_CODE (endbit) == INTEGER_CST
-+ && (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
-+ && (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
-+ {
-+ emit_library_call (memset_libfunc, LCT_NORMAL,
-+ VOIDmode, 3,
-+ plus_constant (XEXP (targetx, 0),
-+ startb / BITS_PER_UNIT),
-+ Pmode,
-+ constm1_rtx, TYPE_MODE (integer_type_node),
-+ GEN_INT ((endb - startb) / BITS_PER_UNIT),
-+ TYPE_MODE (sizetype));
-+ }
-+ else
-+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__setbits"),
-+ LCT_NORMAL, VOIDmode, 4, XEXP (targetx, 0),
-+ Pmode, bitlength_rtx, TYPE_MODE (sizetype),
-+ startbit_rtx, TYPE_MODE (sizetype),
-+ endbit_rtx, TYPE_MODE (sizetype));
-+
-+ if (REG_P (target))
-+ emit_move_insn (target, targetx);
-+ }
-+ }
-+
-+ else
-+ abort ();
-+}
-+
-+/* Store the value of EXP (an expression tree)
-+ into a subfield of TARGET which has mode MODE and occupies
-+ BITSIZE bits, starting BITPOS bits from the start of TARGET.
-+ If MODE is VOIDmode, it means that we are storing into a bit-field.
-+
-+ If VALUE_MODE is VOIDmode, return nothing in particular.
-+ UNSIGNEDP is not used in this case.
-+
-+ Otherwise, return an rtx for the value stored. This rtx
-+ has mode VALUE_MODE if that is convenient to do.
-+ In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
-+
-+ TYPE is the type of the underlying object,
-+
-+ ALIAS_SET is the alias set for the destination. This value will
-+ (in general) be different from that for TARGET, since TARGET is a
-+ reference to the containing structure. */
-+
-+static rtx
-+store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
-+ alias_set)
-+ rtx target;
-+ HOST_WIDE_INT bitsize;
-+ HOST_WIDE_INT bitpos;
-+ enum machine_mode mode;
-+ tree exp;
-+ enum machine_mode value_mode;
-+ int unsignedp;
-+ tree type;
-+ int alias_set;
-+{
-+ HOST_WIDE_INT width_mask = 0;
-+
-+ if (TREE_CODE (exp) == ERROR_MARK)
-+ return const0_rtx;
-+
-+ /* If we have nothing to store, do nothing unless the expression has
-+ side-effects. */
-+ if (bitsize == 0)
-+ return expand_expr (exp, const0_rtx, VOIDmode, 0);
-+ else if (bitsize >=0 && bitsize < HOST_BITS_PER_WIDE_INT)
-+ width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1;
-+
-+ /* If we are storing into an unaligned field of an aligned union that is
-+ in a register, we may have the mode of TARGET being an integer mode but
-+ MODE == BLKmode. In that case, get an aligned object whose size and
-+ alignment are the same as TARGET and store TARGET into it (we can avoid
-+ the store if the field being stored is the entire width of TARGET). Then
-+ call ourselves recursively to store the field into a BLKmode version of
-+ that object. Finally, load from the object into TARGET. This is not
-+ very efficient in general, but should only be slightly more expensive
-+ than the otherwise-required unaligned accesses. Perhaps this can be
-+ cleaned up later. */
-+
-+ if (mode == BLKmode
-+ && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG))
-+ {
-+ rtx object
-+ = assign_temp
-+ (build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUAL_CONST),
-+ 0, 1, 1);
-+ rtx blk_object = adjust_address (object, BLKmode, 0);
-+
-+ if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
-+ emit_move_insn (object, target);
-+
-+ store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0, type,
-+ alias_set);
-+
-+ emit_move_insn (target, object);
-+
-+ /* We want to return the BLKmode version of the data. */
-+ return blk_object;
-+ }
-+
-+ if (GET_CODE (target) == CONCAT)
-+ {
-+ /* We're storing into a struct containing a single __complex. */
-+
-+ if (bitpos != 0)
-+ abort ();
-+ return store_expr (exp, target, 0);
-+ }
-+
-+ /* If the structure is in a register or if the component
-+ is a bit field, we cannot use addressing to access it.
-+ Use bit-field techniques or SUBREG to store in it. */
-+
-+ if (mode == VOIDmode
-+ || (mode != BLKmode && ! direct_store[(int) mode]
-+ && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
-+ && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
-+ || GET_CODE (target) == REG
-+ || GET_CODE (target) == SUBREG
-+ /* If the field isn't aligned enough to store as an ordinary memref,
-+ store it as a bit field. */
-+ || (mode != BLKmode && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (target))
-+ && (MEM_ALIGN (target) < GET_MODE_ALIGNMENT (mode)
-+ || bitpos % GET_MODE_ALIGNMENT (mode)))
-+ /* If the RHS and field are a constant size and the size of the
-+ RHS isn't the same size as the bitfield, we must use bitfield
-+ operations. */
-+ || (bitsize >= 0
-+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
-+ && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0))
-+ {
-+ rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
-+
-+ /* If BITSIZE is narrower than the size of the type of EXP
-+ we will be narrowing TEMP. Normally, what's wanted are the
-+ low-order bits. However, if EXP's type is a record and this is
-+ big-endian machine, we want the upper BITSIZE bits. */
-+ if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
-+ && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp))
-+ && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
-+ temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
-+ size_int (GET_MODE_BITSIZE (GET_MODE (temp))
-+ - bitsize),
-+ temp, 1);
-+
-+ /* Unless MODE is VOIDmode or BLKmode, convert TEMP to
-+ MODE. */
-+ if (mode != VOIDmode && mode != BLKmode
-+ && mode != TYPE_MODE (TREE_TYPE (exp)))
-+ temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
-+
-+ /* If the modes of TARGET and TEMP are both BLKmode, both
-+ must be in memory and BITPOS must be aligned on a byte
-+ boundary. If so, we simply do a block copy. */
-+ if (GET_MODE (target) == BLKmode && GET_MODE (temp) == BLKmode)
-+ {
-+ if (GET_CODE (target) != MEM || GET_CODE (temp) != MEM
-+ || bitpos % BITS_PER_UNIT != 0)
-+ abort ();
-+
-+ target = adjust_address (target, VOIDmode, bitpos / BITS_PER_UNIT);
-+ emit_block_move (target, temp,
-+ GEN_INT ((bitsize + BITS_PER_UNIT - 1)
-+ / BITS_PER_UNIT),
-+ BLOCK_OP_NORMAL);
-+
-+ return value_mode == VOIDmode ? const0_rtx : target;
-+ }
-+
-+ /* Store the value in the bitfield. */
-+ store_bit_field (target, bitsize, bitpos, mode, temp,
-+ int_size_in_bytes (type));
-+
-+ if (value_mode != VOIDmode)
-+ {
-+ /* The caller wants an rtx for the value.
-+ If possible, avoid refetching from the bitfield itself. */
-+ if (width_mask != 0
-+ && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)))
-+ {
-+ tree count;
-+ enum machine_mode tmode;
-+
-+ tmode = GET_MODE (temp);
-+ if (tmode == VOIDmode)
-+ tmode = value_mode;
-+
-+ if (unsignedp)
-+ return expand_and (tmode, temp,
-+ gen_int_mode (width_mask, tmode),
-+ NULL_RTX);
-+
-+ count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
-+ temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
-+ return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
-+ }
-+
-+ return extract_bit_field (target, bitsize, bitpos, unsignedp,
-+ NULL_RTX, value_mode, VOIDmode,
-+ int_size_in_bytes (type));
-+ }
-+ return const0_rtx;
-+ }
-+ else
-+ {
-+ rtx addr = XEXP (target, 0);
-+ rtx to_rtx = target;
-+
-+ /* If a value is wanted, it must be the lhs;
-+ so make the address stable for multiple use. */
-+
-+ if (value_mode != VOIDmode && GET_CODE (addr) != REG
-+ && ! CONSTANT_ADDRESS_P (addr)
-+ /* A frame-pointer reference is already stable. */
-+ && ! (GET_CODE (addr) == PLUS
-+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
-+ && (XEXP (addr, 0) == virtual_incoming_args_rtx
-+ || XEXP (addr, 0) == virtual_stack_vars_rtx)))
-+ to_rtx = replace_equiv_address (to_rtx, copy_to_reg (addr));
-+
-+ /* Now build a reference to just the desired component. */
-+
-+ to_rtx = adjust_address (target, mode, bitpos / BITS_PER_UNIT);
-+
-+ if (to_rtx == target)
-+ to_rtx = copy_rtx (to_rtx);
-+
-+ MEM_SET_IN_STRUCT_P (to_rtx, 1);
-+ if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
-+ set_mem_alias_set (to_rtx, alias_set);
-+
-+ return store_expr (exp, to_rtx, value_mode != VOIDmode);
-+ }
-+}
-+\f
-+/* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF,
-+ an ARRAY_REF, or an ARRAY_RANGE_REF, look for nested operations of these
-+ codes and find the ultimate containing object, which we return.
-+
-+ We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
-+ bit position, and *PUNSIGNEDP to the signedness of the field.
-+ If the position of the field is variable, we store a tree
-+ giving the variable offset (in units) in *POFFSET.
-+ This offset is in addition to the bit position.
-+ If the position is not variable, we store 0 in *POFFSET.
-+
-+ If any of the extraction expressions is volatile,
-+ we store 1 in *PVOLATILEP. Otherwise we don't change that.
-+
-+ If the field is a bit-field, *PMODE is set to VOIDmode. Otherwise, it
-+ is a mode that can be used to access the field. In that case, *PBITSIZE
-+ is redundant.
-+
-+ If the field describes a variable-sized object, *PMODE is set to
-+ VOIDmode and *PBITSIZE is set to -1. An access cannot be made in
-+ this case, but the address of the object can be found. */
-+
-+tree
-+get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
-+ punsignedp, pvolatilep)
-+ tree exp;
-+ HOST_WIDE_INT *pbitsize;
-+ HOST_WIDE_INT *pbitpos;
-+ tree *poffset;
-+ enum machine_mode *pmode;
-+ int *punsignedp;
-+ int *pvolatilep;
-+{
-+ tree size_tree = 0;
-+ enum machine_mode mode = VOIDmode;
-+ tree offset = size_zero_node;
-+ tree bit_offset = bitsize_zero_node;
-+ tree placeholder_ptr = 0;
-+ tree tem;
-+
-+ /* First get the mode, signedness, and size. We do this from just the
-+ outermost expression. */
-+ if (TREE_CODE (exp) == COMPONENT_REF)
-+ {
-+ size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
-+ if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
-+ mode = DECL_MODE (TREE_OPERAND (exp, 1));
-+
-+ *punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1));
-+ }
-+ else if (TREE_CODE (exp) == BIT_FIELD_REF)
-+ {
-+ size_tree = TREE_OPERAND (exp, 1);
-+ *punsignedp = TREE_UNSIGNED (exp);
-+ }
-+ else
-+ {
-+ mode = TYPE_MODE (TREE_TYPE (exp));
-+ *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
-+
-+ if (mode == BLKmode)
-+ size_tree = TYPE_SIZE (TREE_TYPE (exp));
-+ else
-+ *pbitsize = GET_MODE_BITSIZE (mode);
-+ }
-+
-+ if (size_tree != 0)
-+ {
-+ if (! host_integerp (size_tree, 1))
-+ mode = BLKmode, *pbitsize = -1;
-+ else
-+ *pbitsize = tree_low_cst (size_tree, 1);
-+ }
-+
-+ /* Compute cumulative bit-offset for nested component-refs and array-refs,
-+ and find the ultimate containing object. */
-+ while (1)
-+ {
-+ if (TREE_CODE (exp) == BIT_FIELD_REF)
-+ bit_offset = size_binop (PLUS_EXPR, bit_offset, TREE_OPERAND (exp, 2));
-+ else if (TREE_CODE (exp) == COMPONENT_REF)
-+ {
-+ tree field = TREE_OPERAND (exp, 1);
-+ tree this_offset = DECL_FIELD_OFFSET (field);
-+
-+ /* If this field hasn't been filled in yet, don't go
-+ past it. This should only happen when folding expressions
-+ made during type construction. */
-+ if (this_offset == 0)
-+ break;
-+ else if (! TREE_CONSTANT (this_offset)
-+ && contains_placeholder_p (this_offset))
-+ this_offset = build (WITH_RECORD_EXPR, sizetype, this_offset, exp);
-+
-+ offset = size_binop (PLUS_EXPR, offset, this_offset);
-+ bit_offset = size_binop (PLUS_EXPR, bit_offset,
-+ DECL_FIELD_BIT_OFFSET (field));
-+
-+ /* ??? Right now we don't do anything with DECL_OFFSET_ALIGN. */
-+ }
-+
-+ else if (TREE_CODE (exp) == ARRAY_REF
-+ || TREE_CODE (exp) == ARRAY_RANGE_REF)
-+ {
-+ tree index = TREE_OPERAND (exp, 1);
-+ tree array = TREE_OPERAND (exp, 0);
-+ tree domain = TYPE_DOMAIN (TREE_TYPE (array));
-+ tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
-+ tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
-+
-+ /* We assume all arrays have sizes that are a multiple of a byte.
-+ First subtract the lower bound, if any, in the type of the
-+ index, then convert to sizetype and multiply by the size of the
-+ array element. */
-+ if (low_bound != 0 && ! integer_zerop (low_bound))
-+ index = fold (build (MINUS_EXPR, TREE_TYPE (index),
-+ index, low_bound));
-+
-+ /* If the index has a self-referential type, pass it to a
-+ WITH_RECORD_EXPR; if the component size is, pass our
-+ component to one. */
-+ if (! TREE_CONSTANT (index)
-+ && contains_placeholder_p (index))
-+ index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp);
-+ if (! TREE_CONSTANT (unit_size)
-+ && contains_placeholder_p (unit_size))
-+ unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size, array);
-+
-+ offset = size_binop (PLUS_EXPR, offset,
-+ size_binop (MULT_EXPR,
-+ convert (sizetype, index),
-+ unit_size));
-+ }
-+
-+ else if (TREE_CODE (exp) == PLACEHOLDER_EXPR)
-+ {
-+ tree new = find_placeholder (exp, &placeholder_ptr);
-+
-+ /* If we couldn't find the replacement, return the PLACEHOLDER_EXPR.
-+ We might have been called from tree optimization where we
-+ haven't set up an object yet. */
-+ if (new == 0)
-+ break;
-+ else
-+ exp = new;
-+
-+ continue;
-+ }
-+ else if (TREE_CODE (exp) != NON_LVALUE_EXPR
-+ && TREE_CODE (exp) != VIEW_CONVERT_EXPR
-+ && ! ((TREE_CODE (exp) == NOP_EXPR
-+ || TREE_CODE (exp) == CONVERT_EXPR)
-+ && (TYPE_MODE (TREE_TYPE (exp))
-+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))))
-+ break;
-+
-+ /* If any reference in the chain is volatile, the effect is volatile. */
-+ if (TREE_THIS_VOLATILE (exp))
-+ *pvolatilep = 1;
-+
-+ exp = TREE_OPERAND (exp, 0);
-+ }
-+
-+ /* If OFFSET is constant, see if we can return the whole thing as a
-+ constant bit position. Otherwise, split it up. */
-+ if (host_integerp (offset, 0)
-+ && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, offset),
-+ bitsize_unit_node))
-+ && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
-+ && host_integerp (tem, 0))
-+ *pbitpos = tree_low_cst (tem, 0), *poffset = 0;
-+ else
-+ *pbitpos = tree_low_cst (bit_offset, 0), *poffset = offset;
-+
-+ *pmode = mode;
-+ return exp;
-+}
-+
-+/* Return 1 if T is an expression that get_inner_reference handles. */
-+
-+int
-+handled_component_p (t)
-+ tree t;
-+{
-+ switch (TREE_CODE (t))
-+ {
-+ case BIT_FIELD_REF:
-+ case COMPONENT_REF:
-+ case ARRAY_REF:
-+ case ARRAY_RANGE_REF:
-+ case NON_LVALUE_EXPR:
-+ case VIEW_CONVERT_EXPR:
-+ return 1;
-+
-+ case NOP_EXPR:
-+ case CONVERT_EXPR:
-+ return (TYPE_MODE (TREE_TYPE (t))
-+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))));
-+
-+ default:
-+ return 0;
-+ }
-+}
-+\f
-+/* Given an rtx VALUE that may contain additions and multiplications, return
-+ an equivalent value that just refers to a register, memory, or constant.
-+ This is done by generating instructions to perform the arithmetic and
-+ returning a pseudo-register containing the value.
-+
-+ The returned value may be a REG, SUBREG, MEM or constant. */
-+
-+rtx
-+force_operand (value, target)
-+ rtx value, target;
-+{
-+ rtx op1, op2;
-+ /* Use subtarget as the target for operand 0 of a binary operation. */
-+ rtx subtarget = get_subtarget (target);
-+ enum rtx_code code = GET_CODE (value);
-+
-+ /* Check for a PIC address load. */
-+ if ((code == PLUS || code == MINUS)
-+ && XEXP (value, 0) == pic_offset_table_rtx
-+ && (GET_CODE (XEXP (value, 1)) == SYMBOL_REF
-+ || GET_CODE (XEXP (value, 1)) == LABEL_REF
-+ || GET_CODE (XEXP (value, 1)) == CONST))
-+ {
-+ if (!subtarget)
-+ subtarget = gen_reg_rtx (GET_MODE (value));
-+ emit_move_insn (subtarget, value);
-+ return subtarget;
-+ }
-+
-+ if (code == ZERO_EXTEND || code == SIGN_EXTEND)
-+ {
-+ if (!target)
-+ target = gen_reg_rtx (GET_MODE (value));
-+ convert_move (target, force_operand (XEXP (value, 0), NULL),
-+ code == ZERO_EXTEND);
-+ return target;
-+ }
-+
-+ if (GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == 'c')
-+ {
-+ op2 = XEXP (value, 1);
-+ if (!CONSTANT_P (op2) && !(GET_CODE (op2) == REG && op2 != subtarget))
-+ subtarget = 0;
-+ if (code == MINUS && GET_CODE (op2) == CONST_INT)
-+ {
-+ code = PLUS;
-+ op2 = negate_rtx (GET_MODE (value), op2);
-+ }
-+
-+ /* Check for an addition with OP2 a constant integer and our first
-+ operand a PLUS of a virtual register and something else. In that
-+ case, we want to emit the sum of the virtual register and the
-+ constant first and then add the other value. This allows virtual
-+ register instantiation to simply modify the constant rather than
-+ creating another one around this addition. */
-+ if (code == PLUS && GET_CODE (op2) == CONST_INT
-+ && GET_CODE (XEXP (value, 0)) == PLUS
-+ && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
-+ && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
-+ && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
-+ {
-+ rtx temp = expand_simple_binop (GET_MODE (value), code,
-+ XEXP (XEXP (value, 0), 0), op2,
-+ subtarget, 0, OPTAB_LIB_WIDEN);
-+ return expand_simple_binop (GET_MODE (value), code, temp,
-+ force_operand (XEXP (XEXP (value,
-+ 0), 1), 0),
-+ target, 0, OPTAB_LIB_WIDEN);
-+ }
-+
-+ op1 = force_operand (XEXP (value, 0), subtarget);
-+ op2 = force_operand (op2, NULL_RTX);
-+ switch (code)
-+ {
-+ case MULT:
-+ return expand_mult (GET_MODE (value), op1, op2, target, 1);
-+ case DIV:
-+ if (!INTEGRAL_MODE_P (GET_MODE (value)))
-+ return expand_simple_binop (GET_MODE (value), code, op1, op2,
-+ target, 1, OPTAB_LIB_WIDEN);
-+ else
-+ return expand_divmod (0,
-+ FLOAT_MODE_P (GET_MODE (value))
-+ ? RDIV_EXPR : TRUNC_DIV_EXPR,
-+ GET_MODE (value), op1, op2, target, 0);
-+ break;
-+ case MOD:
-+ return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
-+ target, 0);
-+ break;
-+ case UDIV:
-+ return expand_divmod (0, TRUNC_DIV_EXPR, GET_MODE (value), op1, op2,
-+ target, 1);
-+ break;
-+ case UMOD:
-+ return expand_divmod (1, TRUNC_MOD_EXPR, GET_MODE (value), op1, op2,
-+ target, 1);
-+ break;
-+ case ASHIFTRT:
-+ return expand_simple_binop (GET_MODE (value), code, op1, op2,
-+ target, 0, OPTAB_LIB_WIDEN);
-+ break;
-+ default:
-+ return expand_simple_binop (GET_MODE (value), code, op1, op2,
-+ target, 1, OPTAB_LIB_WIDEN);
-+ }
-+ }
-+ if (GET_RTX_CLASS (code) == '1')
-+ {
-+ op1 = force_operand (XEXP (value, 0), NULL_RTX);
-+ return expand_simple_unop (GET_MODE (value), code, op1, target, 0);
-+ }
-+
-+#ifdef INSN_SCHEDULING
-+ /* On machines that have insn scheduling, we want all memory reference to be
-+ explicit, so we need to deal with such paradoxical SUBREGs. */
-+ if (GET_CODE (value) == SUBREG && GET_CODE (SUBREG_REG (value)) == MEM
-+ && (GET_MODE_SIZE (GET_MODE (value))
-+ > GET_MODE_SIZE (GET_MODE (SUBREG_REG (value)))))
-+ value
-+ = simplify_gen_subreg (GET_MODE (value),
-+ force_reg (GET_MODE (SUBREG_REG (value)),
-+ force_operand (SUBREG_REG (value),
-+ NULL_RTX)),
-+ GET_MODE (SUBREG_REG (value)),
-+ SUBREG_BYTE (value));
-+#endif
-+
-+ return value;
-+}
-+\f
-+/* Subroutine of expand_expr: return nonzero iff there is no way that
-+ EXP can reference X, which is being modified. TOP_P is nonzero if this
-+ call is going to be used to determine whether we need a temporary
-+ for EXP, as opposed to a recursive call to this function.
-+
-+ It is always safe for this routine to return zero since it merely
-+ searches for optimization opportunities. */
-+
-+int
-+safe_from_p (x, exp, top_p)
-+ rtx x;
-+ tree exp;
-+ int top_p;
-+{
-+ rtx exp_rtl = 0;
-+ int i, nops;
-+ static tree save_expr_list;
-+
-+ if (x == 0
-+ /* If EXP has varying size, we MUST use a target since we currently
-+ have no way of allocating temporaries of variable size
-+ (except for arrays that have TYPE_ARRAY_MAX_SIZE set).
-+ So we assume here that something at a higher level has prevented a
-+ clash. This is somewhat bogus, but the best we can do. Only
-+ do this when X is BLKmode and when we are at the top level. */
-+ || (top_p && TREE_TYPE (exp) != 0 && COMPLETE_TYPE_P (TREE_TYPE (exp))
-+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
-+ && (TREE_CODE (TREE_TYPE (exp)) != ARRAY_TYPE
-+ || TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)) == NULL_TREE
-+ || TREE_CODE (TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)))
-+ != INTEGER_CST)
-+ && GET_MODE (x) == BLKmode)
-+ /* If X is in the outgoing argument area, it is always safe. */
-+ || (GET_CODE (x) == MEM
-+ && (XEXP (x, 0) == virtual_outgoing_args_rtx
-+ || (GET_CODE (XEXP (x, 0)) == PLUS
-+ && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx))))
-+ return 1;
-+
-+ /* If this is a subreg of a hard register, declare it unsafe, otherwise,
-+ find the underlying pseudo. */
-+ if (GET_CODE (x) == SUBREG)
-+ {
-+ x = SUBREG_REG (x);
-+ if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
-+ return 0;
-+ }
-+
-+ /* A SAVE_EXPR might appear many times in the expression passed to the
-+ top-level safe_from_p call, and if it has a complex subexpression,
-+ examining it multiple times could result in a combinatorial explosion.
-+ E.g. on an Alpha running at least 200MHz, a Fortran test case compiled
-+ with optimization took about 28 minutes to compile -- even though it was
-+ only a few lines long. So we mark each SAVE_EXPR we see with TREE_PRIVATE
-+ and turn that off when we are done. We keep a list of the SAVE_EXPRs
-+ we have processed. Note that the only test of top_p was above. */
-+
-+ if (top_p)
-+ {
-+ int rtn;
-+ tree t;
-+
-+ save_expr_list = 0;
-+
-+ rtn = safe_from_p (x, exp, 0);
-+
-+ for (t = save_expr_list; t != 0; t = TREE_CHAIN (t))
-+ TREE_PRIVATE (TREE_PURPOSE (t)) = 0;
-+
-+ return rtn;
-+ }
-+
-+ /* Now look at our tree code and possibly recurse. */
-+ switch (TREE_CODE_CLASS (TREE_CODE (exp)))
-+ {
-+ case 'd':
-+ exp_rtl = DECL_RTL_IF_SET (exp);
-+ break;
-+
-+ case 'c':
-+ return 1;
-+
-+ case 'x':
-+ if (TREE_CODE (exp) == TREE_LIST)
-+ {
-+ while (1)
-+ {
-+ if (TREE_VALUE (exp) && !safe_from_p (x, TREE_VALUE (exp), 0))
-+ return 0;
-+ exp = TREE_CHAIN (exp);
-+ if (!exp)
-+ return 1;
-+ if (TREE_CODE (exp) != TREE_LIST)
-+ return safe_from_p (x, exp, 0);
-+ }
-+ }
-+ else if (TREE_CODE (exp) == ERROR_MARK)
-+ return 1; /* An already-visited SAVE_EXPR? */
-+ else
-+ return 0;
-+
-+ case '2':
-+ case '<':
-+ if (!safe_from_p (x, TREE_OPERAND (exp, 1), 0))
-+ return 0;
-+ /* FALLTHRU */
-+
-+ case '1':
-+ return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
-+
-+ case 'e':
-+ case 'r':
-+ /* Now do code-specific tests. EXP_RTL is set to any rtx we find in
-+ the expression. If it is set, we conflict iff we are that rtx or
-+ both are in memory. Otherwise, we check all operands of the
-+ expression recursively. */
-+
-+ switch (TREE_CODE (exp))
-+ {
-+ case ADDR_EXPR:
-+ /* If the operand is static or we are static, we can't conflict.
-+ Likewise if we don't conflict with the operand at all. */
-+ if (staticp (TREE_OPERAND (exp, 0))
-+ || TREE_STATIC (exp)
-+ || safe_from_p (x, TREE_OPERAND (exp, 0), 0))
-+ return 1;
-+
-+ /* Otherwise, the only way this can conflict is if we are taking
-+ the address of a DECL a that address if part of X, which is
-+ very rare. */
-+ exp = TREE_OPERAND (exp, 0);
-+ if (DECL_P (exp))
-+ {
-+ if (!DECL_RTL_SET_P (exp)
-+ || GET_CODE (DECL_RTL (exp)) != MEM)
-+ return 0;
-+ else
-+ exp_rtl = XEXP (DECL_RTL (exp), 0);
-+ }
-+ break;
-+
-+ case INDIRECT_REF:
-+ if (GET_CODE (x) == MEM
-+ && alias_sets_conflict_p (MEM_ALIAS_SET (x),
-+ get_alias_set (exp)))
-+ return 0;
-+ break;
-+
-+ case CALL_EXPR:
-+ /* Assume that the call will clobber all hard registers and
-+ all of memory. */
-+ if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
-+ || GET_CODE (x) == MEM)
-+ return 0;
-+ break;
-+
-+ case RTL_EXPR:
-+ /* If a sequence exists, we would have to scan every instruction
-+ in the sequence to see if it was safe. This is probably not
-+ worthwhile. */
-+ if (RTL_EXPR_SEQUENCE (exp))
-+ return 0;
-+
-+ exp_rtl = RTL_EXPR_RTL (exp);
-+ break;
-+
-+ case WITH_CLEANUP_EXPR:
-+ exp_rtl = WITH_CLEANUP_EXPR_RTL (exp);
-+ break;
-+
-+ case CLEANUP_POINT_EXPR:
-+ return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
-+
-+ case SAVE_EXPR:
-+ exp_rtl = SAVE_EXPR_RTL (exp);
-+ if (exp_rtl)
-+ break;
-+
-+ /* If we've already scanned this, don't do it again. Otherwise,
-+ show we've scanned it and record for clearing the flag if we're
-+ going on. */
-+ if (TREE_PRIVATE (exp))
-+ return 1;
-+
-+ TREE_PRIVATE (exp) = 1;
-+ if (! safe_from_p (x, TREE_OPERAND (exp, 0), 0))
-+ {
-+ TREE_PRIVATE (exp) = 0;
-+ return 0;
-+ }
-+
-+ save_expr_list = tree_cons (exp, NULL_TREE, save_expr_list);
-+ return 1;
-+
-+ case BIND_EXPR:
-+ /* The only operand we look at is operand 1. The rest aren't
-+ part of the expression. */
-+ return safe_from_p (x, TREE_OPERAND (exp, 1), 0);
-+
-+ case METHOD_CALL_EXPR:
-+ /* This takes an rtx argument, but shouldn't appear here. */
-+ abort ();
-+
-+ default:
-+ break;
-+ }
-+
-+ /* If we have an rtx, we do not need to scan our operands. */
-+ if (exp_rtl)
-+ break;
-+
-+ nops = first_rtl_op (TREE_CODE (exp));
-+ for (i = 0; i < nops; i++)
-+ if (TREE_OPERAND (exp, i) != 0
-+ && ! safe_from_p (x, TREE_OPERAND (exp, i), 0))
-+ return 0;
-+
-+ /* If this is a language-specific tree code, it may require
-+ special handling. */
-+ if ((unsigned int) TREE_CODE (exp)
-+ >= (unsigned int) LAST_AND_UNUSED_TREE_CODE
-+ && !(*lang_hooks.safe_from_p) (x, exp))
-+ return 0;
-+ }
-+
-+ /* If we have an rtl, find any enclosed object. Then see if we conflict
-+ with it. */
-+ if (exp_rtl)
-+ {
-+ if (GET_CODE (exp_rtl) == SUBREG)
-+ {
-+ exp_rtl = SUBREG_REG (exp_rtl);
-+ if (GET_CODE (exp_rtl) == REG
-+ && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER)
-+ return 0;
-+ }
-+
-+ /* If the rtl is X, then it is not safe. Otherwise, it is unless both
-+ are memory and they conflict. */
-+ return ! (rtx_equal_p (x, exp_rtl)
-+ || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
-+ && true_dependence (exp_rtl, VOIDmode, x,
-+ rtx_addr_varies_p)));
-+ }
-+
-+ /* If we reach here, it is safe. */
-+ return 1;
-+}
-+
-+/* Subroutine of expand_expr: return rtx if EXP is a
-+ variable or parameter; else return 0. */
-+
-+static rtx
-+var_rtx (exp)
-+ tree exp;
-+{
-+ STRIP_NOPS (exp);
-+ switch (TREE_CODE (exp))
-+ {
-+ case PARM_DECL:
-+ case VAR_DECL:
-+ return DECL_RTL (exp);
-+ default:
-+ return 0;
-+ }
-+}
-+
-+#ifdef MAX_INTEGER_COMPUTATION_MODE
-+
-+void
-+check_max_integer_computation_mode (exp)
-+ tree exp;
-+{
-+ enum tree_code code;
-+ enum machine_mode mode;
-+
-+ /* Strip any NOPs that don't change the mode. */
-+ STRIP_NOPS (exp);
-+ code = TREE_CODE (exp);
-+
-+ /* We must allow conversions of constants to MAX_INTEGER_COMPUTATION_MODE. */
-+ if (code == NOP_EXPR
-+ && TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
-+ return;
-+
-+ /* First check the type of the overall operation. We need only look at
-+ unary, binary and relational operations. */
-+ if (TREE_CODE_CLASS (code) == '1'
-+ || TREE_CODE_CLASS (code) == '2'
-+ || TREE_CODE_CLASS (code) == '<')
-+ {
-+ mode = TYPE_MODE (TREE_TYPE (exp));
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && mode > MAX_INTEGER_COMPUTATION_MODE)
-+ internal_error ("unsupported wide integer operation");
-+ }
-+
-+ /* Check operand of a unary op. */
-+ if (TREE_CODE_CLASS (code) == '1')
-+ {
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && mode > MAX_INTEGER_COMPUTATION_MODE)
-+ internal_error ("unsupported wide integer operation");
-+ }
-+
-+ /* Check operands of a binary/comparison op. */
-+ if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
-+ {
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && mode > MAX_INTEGER_COMPUTATION_MODE)
-+ internal_error ("unsupported wide integer operation");
-+
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)));
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && mode > MAX_INTEGER_COMPUTATION_MODE)
-+ internal_error ("unsupported wide integer operation");
-+ }
-+}
-+#endif
-+\f
-+/* Return the highest power of two that EXP is known to be a multiple of.
-+ This is used in updating alignment of MEMs in array references. */
-+
-+static HOST_WIDE_INT
-+highest_pow2_factor (exp)
-+ tree exp;
-+{
-+ HOST_WIDE_INT c0, c1;
-+
-+ switch (TREE_CODE (exp))
-+ {
-+ case INTEGER_CST:
-+ /* We can find the lowest bit that's a one. If the low
-+ HOST_BITS_PER_WIDE_INT bits are zero, return BIGGEST_ALIGNMENT.
-+ We need to handle this case since we can find it in a COND_EXPR,
-+ a MIN_EXPR, or a MAX_EXPR. If the constant overlows, we have an
-+ erroneous program, so return BIGGEST_ALIGNMENT to avoid any
-+ later ICE. */
-+ if (TREE_CONSTANT_OVERFLOW (exp))
-+ return BIGGEST_ALIGNMENT;
-+ else
-+ {
-+ /* Note: tree_low_cst is intentionally not used here,
-+ we don't care about the upper bits. */
-+ c0 = TREE_INT_CST_LOW (exp);
-+ c0 &= -c0;
-+ return c0 ? c0 : BIGGEST_ALIGNMENT;
-+ }
-+ break;
-+
-+ case PLUS_EXPR: case MINUS_EXPR: case MIN_EXPR: case MAX_EXPR:
-+ c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
-+ c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
-+ return MIN (c0, c1);
-+
-+ case MULT_EXPR:
-+ c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
-+ c1 = highest_pow2_factor (TREE_OPERAND (exp, 1));
-+ return c0 * c1;
-+
-+ case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: case FLOOR_DIV_EXPR:
-+ case CEIL_DIV_EXPR:
-+ if (integer_pow2p (TREE_OPERAND (exp, 1))
-+ && host_integerp (TREE_OPERAND (exp, 1), 1))
-+ {
-+ c0 = highest_pow2_factor (TREE_OPERAND (exp, 0));
-+ c1 = tree_low_cst (TREE_OPERAND (exp, 1), 1);
-+ return MAX (1, c0 / c1);
-+ }
-+ break;
-+
-+ case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR:
-+ case SAVE_EXPR: case WITH_RECORD_EXPR:
-+ return highest_pow2_factor (TREE_OPERAND (exp, 0));
-+
-+ case COMPOUND_EXPR:
-+ return highest_pow2_factor (TREE_OPERAND (exp, 1));
-+
-+ case COND_EXPR:
-+ c0 = highest_pow2_factor (TREE_OPERAND (exp, 1));
-+ c1 = highest_pow2_factor (TREE_OPERAND (exp, 2));
-+ return MIN (c0, c1);
-+
-+ default:
-+ break;
-+ }
-+
-+ return 1;
-+}
-+
-+/* Similar, except that it is known that the expression must be a multiple
-+ of the alignment of TYPE. */
-+
-+static HOST_WIDE_INT
-+highest_pow2_factor_for_type (type, exp)
-+ tree type;
-+ tree exp;
-+{
-+ HOST_WIDE_INT type_align, factor;
-+
-+ factor = highest_pow2_factor (exp);
-+ type_align = TYPE_ALIGN (type) / BITS_PER_UNIT;
-+ return MAX (factor, type_align);
-+}
-+\f
-+/* Return an object on the placeholder list that matches EXP, a
-+ PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
-+ PLACEHOLDER_EXPR or a pointer type to it. For further information, see
-+ tree.def. If no such object is found, return 0. If PLIST is nonzero, it
-+ is a location which initially points to a starting location in the
-+ placeholder list (zero means start of the list) and where a pointer into
-+ the placeholder list at which the object is found is placed. */
-+
-+tree
-+find_placeholder (exp, plist)
-+ tree exp;
-+ tree *plist;
-+{
-+ tree type = TREE_TYPE (exp);
-+ tree placeholder_expr;
-+
-+ for (placeholder_expr
-+ = plist && *plist ? TREE_CHAIN (*plist) : placeholder_list;
-+ placeholder_expr != 0;
-+ placeholder_expr = TREE_CHAIN (placeholder_expr))
-+ {
-+ tree need_type = TYPE_MAIN_VARIANT (type);
-+ tree elt;
-+
-+ /* Find the outermost reference that is of the type we want. If none,
-+ see if any object has a type that is a pointer to the type we
-+ want. */
-+ for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
-+ elt = ((TREE_CODE (elt) == COMPOUND_EXPR
-+ || TREE_CODE (elt) == COND_EXPR)
-+ ? TREE_OPERAND (elt, 1)
-+ : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-+ || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-+ || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-+ || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
-+ ? TREE_OPERAND (elt, 0) : 0))
-+ if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
-+ {
-+ if (plist)
-+ *plist = placeholder_expr;
-+ return elt;
-+ }
-+
-+ for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
-+ elt
-+ = ((TREE_CODE (elt) == COMPOUND_EXPR
-+ || TREE_CODE (elt) == COND_EXPR)
-+ ? TREE_OPERAND (elt, 1)
-+ : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
-+ || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
-+ || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
-+ || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
-+ ? TREE_OPERAND (elt, 0) : 0))
-+ if (POINTER_TYPE_P (TREE_TYPE (elt))
-+ && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
-+ == need_type))
-+ {
-+ if (plist)
-+ *plist = placeholder_expr;
-+ return build1 (INDIRECT_REF, need_type, elt);
-+ }
-+ }
-+
-+ return 0;
-+}
-+\f
-+/* expand_expr: generate code for computing expression EXP.
-+ An rtx for the computed value is returned. The value is never null.
-+ In the case of a void EXP, const0_rtx is returned.
-+
-+ The value may be stored in TARGET if TARGET is nonzero.
-+ TARGET is just a suggestion; callers must assume that
-+ the rtx returned may not be the same as TARGET.
-+
-+ If TARGET is CONST0_RTX, it means that the value will be ignored.
-+
-+ If TMODE is not VOIDmode, it suggests generating the
-+ result in mode TMODE. But this is done only when convenient.
-+ Otherwise, TMODE is ignored and the value generated in its natural mode.
-+ TMODE is just a suggestion; callers must assume that
-+ the rtx returned may not have mode TMODE.
-+
-+ Note that TARGET may have neither TMODE nor MODE. In that case, it
-+ probably will not be used.
-+
-+ If MODIFIER is EXPAND_SUM then when EXP is an addition
-+ we can return an rtx of the form (MULT (REG ...) (CONST_INT ...))
-+ or a nest of (PLUS ...) and (MINUS ...) where the terms are
-+ products as above, or REG or MEM, or constant.
-+ Ordinarily in such cases we would output mul or add instructions
-+ and then return a pseudo reg containing the sum.
-+
-+ EXPAND_INITIALIZER is much like EXPAND_SUM except that
-+ it also marks a label as absolutely required (it can't be dead).
-+ It also makes a ZERO_EXTEND or SIGN_EXTEND instead of emitting extend insns.
-+ This is used for outputting expressions used in initializers.
-+
-+ EXPAND_CONST_ADDRESS says that it is okay to return a MEM
-+ with a constant address even if that address is not normally legitimate.
-+ EXPAND_INITIALIZER and EXPAND_SUM also have this effect.
-+
-+ EXPAND_STACK_PARM is used when expanding to a TARGET on the stack for
-+ a call parameter. Such targets require special care as we haven't yet
-+ marked TARGET so that it's safe from being trashed by libcalls. We
-+ don't want to use TARGET for anything but the final result;
-+ Intermediate values must go elsewhere. Additionally, calls to
-+ emit_block_move will be flagged with BLOCK_OP_CALL_PARM. */
-+
-+rtx
-+expand_expr (exp, target, tmode, modifier)
-+ tree exp;
-+ rtx target;
-+ enum machine_mode tmode;
-+ enum expand_modifier modifier;
-+{
-+ rtx op0, op1, temp;
-+ tree type = TREE_TYPE (exp);
-+ int unsignedp = TREE_UNSIGNED (type);
-+ enum machine_mode mode;
-+ enum tree_code code = TREE_CODE (exp);
-+ optab this_optab;
-+ rtx subtarget, original_target;
-+ int ignore;
-+ tree context;
-+
-+ /* Handle ERROR_MARK before anybody tries to access its type. */
-+ if (TREE_CODE (exp) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
-+ {
-+ op0 = CONST0_RTX (tmode);
-+ if (op0 != 0)
-+ return op0;
-+ return const0_rtx;
-+ }
-+
-+ mode = TYPE_MODE (type);
-+ /* Use subtarget as the target for operand 0 of a binary operation. */
-+ subtarget = get_subtarget (target);
-+ original_target = target;
-+ ignore = (target == const0_rtx
-+ || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
-+ || code == CONVERT_EXPR || code == REFERENCE_EXPR
-+ || code == COND_EXPR || code == VIEW_CONVERT_EXPR)
-+ && TREE_CODE (type) == VOID_TYPE));
-+
-+ /* If we are going to ignore this result, we need only do something
-+ if there is a side-effect somewhere in the expression. If there
-+ is, short-circuit the most common cases here. Note that we must
-+ not call expand_expr with anything but const0_rtx in case this
-+ is an initial expansion of a size that contains a PLACEHOLDER_EXPR. */
-+
-+ if (ignore)
-+ {
-+ if (! TREE_SIDE_EFFECTS (exp))
-+ return const0_rtx;
-+
-+ /* Ensure we reference a volatile object even if value is ignored, but
-+ don't do this if all we are doing is taking its address. */
-+ if (TREE_THIS_VOLATILE (exp)
-+ && TREE_CODE (exp) != FUNCTION_DECL
-+ && mode != VOIDmode && mode != BLKmode
-+ && modifier != EXPAND_CONST_ADDRESS)
-+ {
-+ temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier);
-+ if (GET_CODE (temp) == MEM)
-+ temp = copy_to_reg (temp);
-+ return const0_rtx;
-+ }
-+
-+ if (TREE_CODE_CLASS (code) == '1' || code == COMPONENT_REF
-+ || code == INDIRECT_REF || code == BUFFER_REF)
-+ return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-+ modifier);
-+
-+ else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<'
-+ || code == ARRAY_REF || code == ARRAY_RANGE_REF)
-+ {
-+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
-+ expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
-+ return const0_rtx;
-+ }
-+ else if ((code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
-+ && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
-+ /* If the second operand has no side effects, just evaluate
-+ the first. */
-+ return expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-+ modifier);
-+ else if (code == BIT_FIELD_REF)
-+ {
-+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
-+ expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, modifier);
-+ expand_expr (TREE_OPERAND (exp, 2), const0_rtx, VOIDmode, modifier);
-+ return const0_rtx;
-+ }
-+
-+ target = 0;
-+ }
-+
-+#ifdef MAX_INTEGER_COMPUTATION_MODE
-+ /* Only check stuff here if the mode we want is different from the mode
-+ of the expression; if it's the same, check_max_integer_computiation_mode
-+ will handle it. Do we really need to check this stuff at all? */
-+
-+ if (target
-+ && GET_MODE (target) != mode
-+ && TREE_CODE (exp) != INTEGER_CST
-+ && TREE_CODE (exp) != PARM_DECL
-+ && TREE_CODE (exp) != ARRAY_REF
-+ && TREE_CODE (exp) != ARRAY_RANGE_REF
-+ && TREE_CODE (exp) != COMPONENT_REF
-+ && TREE_CODE (exp) != BIT_FIELD_REF
-+ && TREE_CODE (exp) != INDIRECT_REF
-+ && TREE_CODE (exp) != CALL_EXPR
-+ && TREE_CODE (exp) != VAR_DECL
-+ && TREE_CODE (exp) != RTL_EXPR)
-+ {
-+ enum machine_mode mode = GET_MODE (target);
-+
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && mode > MAX_INTEGER_COMPUTATION_MODE)
-+ internal_error ("unsupported wide integer operation");
-+ }
-+
-+ if (tmode != mode
-+ && TREE_CODE (exp) != INTEGER_CST
-+ && TREE_CODE (exp) != PARM_DECL
-+ && TREE_CODE (exp) != ARRAY_REF
-+ && TREE_CODE (exp) != ARRAY_RANGE_REF
-+ && TREE_CODE (exp) != COMPONENT_REF
-+ && TREE_CODE (exp) != BIT_FIELD_REF
-+ && TREE_CODE (exp) != INDIRECT_REF
-+ && TREE_CODE (exp) != VAR_DECL
-+ && TREE_CODE (exp) != CALL_EXPR
-+ && TREE_CODE (exp) != RTL_EXPR
-+ && GET_MODE_CLASS (tmode) == MODE_INT
-+ && tmode > MAX_INTEGER_COMPUTATION_MODE)
-+ internal_error ("unsupported wide integer operation");
-+
-+ check_max_integer_computation_mode (exp);
-+#endif
-+
-+ /* If will do cse, generate all results into pseudo registers
-+ since 1) that allows cse to find more things
-+ and 2) otherwise cse could produce an insn the machine
-+ cannot support. And exception is a CONSTRUCTOR into a multi-word
-+ MEM: that's much more likely to be most efficient into the MEM. */
-+
-+ if (! cse_not_expected && mode != BLKmode && target
-+ && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
-+ && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD))
-+ target = 0;
-+
-+ switch (code)
-+ {
-+ case LABEL_DECL:
-+ {
-+ tree function = decl_function_context (exp);
-+ /* Handle using a label in a containing function. */
-+ if (function != current_function_decl
-+ && function != inline_function_decl && function != 0)
-+ {
-+ struct function *p = find_function_data (function);
-+ p->expr->x_forced_labels
-+ = gen_rtx_EXPR_LIST (VOIDmode, label_rtx (exp),
-+ p->expr->x_forced_labels);
-+ }
-+ else
-+ {
-+ if (modifier == EXPAND_INITIALIZER)
-+ forced_labels = gen_rtx_EXPR_LIST (VOIDmode,
-+ label_rtx (exp),
-+ forced_labels);
-+ }
-+
-+ temp = gen_rtx_MEM (FUNCTION_MODE,
-+ gen_rtx_LABEL_REF (Pmode, label_rtx (exp)));
-+ if (function != current_function_decl
-+ && function != inline_function_decl && function != 0)
-+ LABEL_REF_NONLOCAL_P (XEXP (temp, 0)) = 1;
-+ return temp;
-+ }
-+
-+ case PARM_DECL:
-+ if (!DECL_RTL_SET_P (exp))
-+ {
-+ error_with_decl (exp, "prior parameter's size depends on `%s'");
-+ return CONST0_RTX (mode);
-+ }
-+
-+ /* ... fall through ... */
-+
-+ case VAR_DECL:
-+ /* If a static var's type was incomplete when the decl was written,
-+ but the type is complete now, lay out the decl now. */
-+ if (DECL_SIZE (exp) == 0
-+ && COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (TREE_TYPE (exp))
-+ && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
-+ layout_decl (exp, 0);
-+
-+ /* ... fall through ... */
-+
-+ case FUNCTION_DECL:
-+ case RESULT_DECL:
-+ if (DECL_RTL (exp) == 0)
-+ abort ();
-+
-+ /* Ensure variable marked as used even if it doesn't go through
-+ a parser. If it hasn't be used yet, write out an external
-+ definition. */
-+ if (! TREE_USED (exp))
-+ {
-+ assemble_external (exp);
-+ TREE_USED (exp) = 1;
-+ }
-+
-+ /* Show we haven't gotten RTL for this yet. */
-+ temp = 0;
-+
-+ /* Handle variables inherited from containing functions. */
-+ context = decl_function_context (exp);
-+
-+ /* We treat inline_function_decl as an alias for the current function
-+ because that is the inline function whose vars, types, etc.
-+ are being merged into the current function.
-+ See expand_inline_function. */
-+
-+ if (context != 0 && context != current_function_decl
-+ && context != inline_function_decl
-+ /* If var is static, we don't need a static chain to access it. */
-+ && ! (GET_CODE (DECL_RTL (exp)) == MEM
-+ && CONSTANT_P (XEXP (DECL_RTL (exp), 0))))
-+ {
-+ rtx addr;
-+
-+ /* Mark as non-local and addressable. */
-+ DECL_NONLOCAL (exp) = 1;
-+ if (DECL_NO_STATIC_CHAIN (current_function_decl))
-+ abort ();
-+ (*lang_hooks.mark_addressable) (exp);
-+ if (GET_CODE (DECL_RTL (exp)) != MEM)
-+ abort ();
-+ addr = XEXP (DECL_RTL (exp), 0);
-+ if (GET_CODE (addr) == MEM)
-+ addr
-+ = replace_equiv_address (addr,
-+ fix_lexical_addr (XEXP (addr, 0), exp));
-+ else
-+ addr = fix_lexical_addr (addr, exp);
-+
-+ temp = replace_equiv_address (DECL_RTL (exp), addr);
-+ }
-+
-+ /* This is the case of an array whose size is to be determined
-+ from its initializer, while the initializer is still being parsed.
-+ See expand_decl. */
-+
-+ else if (GET_CODE (DECL_RTL (exp)) == MEM
-+ && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG)
-+ temp = validize_mem (DECL_RTL (exp));
-+
-+ /* If DECL_RTL is memory, we are in the normal case and either
-+ the address is not valid or it is not a register and -fforce-addr
-+ is specified, get the address into a register. */
-+
-+ else if (GET_CODE (DECL_RTL (exp)) == MEM
-+ && modifier != EXPAND_CONST_ADDRESS
-+ && modifier != EXPAND_SUM
-+ && modifier != EXPAND_INITIALIZER
-+ && (! memory_address_p (DECL_MODE (exp),
-+ XEXP (DECL_RTL (exp), 0))
-+ || (flag_force_addr
-+ && GET_CODE (XEXP (DECL_RTL (exp), 0)) != REG)))
-+ temp = replace_equiv_address (DECL_RTL (exp),
-+ copy_rtx (XEXP (DECL_RTL (exp), 0)));
-+
-+ /* If we got something, return it. But first, set the alignment
-+ if the address is a register. */
-+ if (temp != 0)
-+ {
-+ if (GET_CODE (temp) == MEM && GET_CODE (XEXP (temp, 0)) == REG)
-+ mark_reg_pointer (XEXP (temp, 0), DECL_ALIGN (exp));
-+
-+ return temp;
-+ }
-+
-+ /* If the mode of DECL_RTL does not match that of the decl, it
-+ must be a promoted value. We return a SUBREG of the wanted mode,
-+ but mark it so that we know that it was already extended. */
-+
-+ if (GET_CODE (DECL_RTL (exp)) == REG
-+ && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp))
-+ {
-+ /* Get the signedness used for this variable. Ensure we get the
-+ same mode we got when the variable was declared. */
-+ if (GET_MODE (DECL_RTL (exp))
-+ != promote_mode (type, DECL_MODE (exp), &unsignedp,
-+ (TREE_CODE (exp) == RESULT_DECL ? 1 : 0)))
-+ abort ();
-+
-+ temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
-+ SUBREG_PROMOTED_VAR_P (temp) = 1;
-+ SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
-+ return temp;
-+ }
-+
-+ return DECL_RTL (exp);
-+
-+ case INTEGER_CST:
-+ temp = immed_double_const (TREE_INT_CST_LOW (exp),
-+ TREE_INT_CST_HIGH (exp), mode);
-+
-+ /* ??? If overflow is set, fold will have done an incomplete job,
-+ which can result in (plus xx (const_int 0)), which can get
-+ simplified by validate_replace_rtx during virtual register
-+ instantiation, which can result in unrecognizable insns.
-+ Avoid this by forcing all overflows into registers. */
-+ if (TREE_CONSTANT_OVERFLOW (exp)
-+ && modifier != EXPAND_INITIALIZER)
-+ temp = force_reg (mode, temp);
-+
-+ return temp;
-+
-+ case VECTOR_CST:
-+ return const_vector_from_tree (exp);
-+
-+ case CONST_DECL:
-+ return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
-+
-+ case REAL_CST:
-+ /* If optimized, generate immediate CONST_DOUBLE
-+ which will be turned into memory by reload if necessary.
-+
-+ We used to force a register so that loop.c could see it. But
-+ this does not allow gen_* patterns to perform optimizations with
-+ the constants. It also produces two insns in cases like "x = 1.0;".
-+ On most machines, floating-point constants are not permitted in
-+ many insns, so we'd end up copying it to a register in any case.
-+
-+ Now, we do the copying in expand_binop, if appropriate. */
-+ return CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (exp),
-+ TYPE_MODE (TREE_TYPE (exp)));
-+
-+ case COMPLEX_CST:
-+ case STRING_CST:
-+ if (! TREE_CST_RTL (exp))
-+ output_constant_def (exp, 1);
-+
-+ /* TREE_CST_RTL probably contains a constant address.
-+ On RISC machines where a constant address isn't valid,
-+ make some insns to get that address into a register. */
-+ if (GET_CODE (TREE_CST_RTL (exp)) == MEM
-+ && modifier != EXPAND_CONST_ADDRESS
-+ && modifier != EXPAND_INITIALIZER
-+ && modifier != EXPAND_SUM
-+ && (! memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0))
-+ || (flag_force_addr
-+ && GET_CODE (XEXP (TREE_CST_RTL (exp), 0)) != REG)))
-+ return replace_equiv_address (TREE_CST_RTL (exp),
-+ copy_rtx (XEXP (TREE_CST_RTL (exp), 0)));
-+ return TREE_CST_RTL (exp);
-+
-+ case EXPR_WITH_FILE_LOCATION:
-+ {
-+ rtx to_return;
-+ const char *saved_input_filename = input_filename;
-+ int saved_lineno = lineno;
-+ input_filename = EXPR_WFL_FILENAME (exp);
-+ lineno = EXPR_WFL_LINENO (exp);
-+ if (EXPR_WFL_EMIT_LINE_NOTE (exp))
-+ emit_line_note (input_filename, lineno);
-+ /* Possibly avoid switching back and forth here. */
-+ to_return = expand_expr (EXPR_WFL_NODE (exp), target, tmode, modifier);
-+ input_filename = saved_input_filename;
-+ lineno = saved_lineno;
-+ return to_return;
-+ }
-+
-+ case SAVE_EXPR:
-+ context = decl_function_context (exp);
-+
-+ /* If this SAVE_EXPR was at global context, assume we are an
-+ initialization function and move it into our context. */
-+ if (context == 0)
-+ SAVE_EXPR_CONTEXT (exp) = current_function_decl;
-+
-+ /* We treat inline_function_decl as an alias for the current function
-+ because that is the inline function whose vars, types, etc.
-+ are being merged into the current function.
-+ See expand_inline_function. */
-+ if (context == current_function_decl || context == inline_function_decl)
-+ context = 0;
-+
-+ /* If this is non-local, handle it. */
-+ if (context)
-+ {
-+ /* The following call just exists to abort if the context is
-+ not of a containing function. */
-+ find_function_data (context);
-+
-+ temp = SAVE_EXPR_RTL (exp);
-+ if (temp && GET_CODE (temp) == REG)
-+ {
-+ put_var_into_stack (exp, /*rescan=*/true);
-+ temp = SAVE_EXPR_RTL (exp);
-+ }
-+ if (temp == 0 || GET_CODE (temp) != MEM)
-+ abort ();
-+ return
-+ replace_equiv_address (temp,
-+ fix_lexical_addr (XEXP (temp, 0), exp));
-+ }
-+ if (SAVE_EXPR_RTL (exp) == 0)
-+ {
-+ if (mode == VOIDmode)
-+ temp = const0_rtx;
-+ else
-+ temp = assign_temp (build_qualified_type (type,
-+ (TYPE_QUALS (type)
-+ | TYPE_QUAL_CONST)),
-+ 3, 0, 0);
-+
-+ SAVE_EXPR_RTL (exp) = temp;
-+ if (!optimize && GET_CODE (temp) == REG)
-+ save_expr_regs = gen_rtx_EXPR_LIST (VOIDmode, temp,
-+ save_expr_regs);
-+
-+ /* If the mode of TEMP does not match that of the expression, it
-+ must be a promoted value. We pass store_expr a SUBREG of the
-+ wanted mode but mark it so that we know that it was already
-+ extended. */
-+
-+ if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
-+ {
-+ temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
-+ promote_mode (type, mode, &unsignedp, 0);
-+ SUBREG_PROMOTED_VAR_P (temp) = 1;
-+ SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
-+ }
-+
-+ if (temp == const0_rtx)
-+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
-+ else
-+ store_expr (TREE_OPERAND (exp, 0), temp,
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+
-+ TREE_USED (exp) = 1;
-+ }
-+
-+ /* If the mode of SAVE_EXPR_RTL does not match that of the expression, it
-+ must be a promoted value. We return a SUBREG of the wanted mode,
-+ but mark it so that we know that it was already extended. */
-+
-+ if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG
-+ && GET_MODE (SAVE_EXPR_RTL (exp)) != mode)
-+ {
-+ /* Compute the signedness and make the proper SUBREG. */
-+ promote_mode (type, mode, &unsignedp, 0);
-+ temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
-+ SUBREG_PROMOTED_VAR_P (temp) = 1;
-+ SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
-+ return temp;
-+ }
-+
-+ return SAVE_EXPR_RTL (exp);
-+
-+ case UNSAVE_EXPR:
-+ {
-+ rtx temp;
-+ temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
-+ TREE_OPERAND (exp, 0)
-+ = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
-+ return temp;
-+ }
-+
-+ case PLACEHOLDER_EXPR:
-+ {
-+ tree old_list = placeholder_list;
-+ tree placeholder_expr = 0;
-+
-+ exp = find_placeholder (exp, &placeholder_expr);
-+ if (exp == 0)
-+ abort ();
-+
-+ placeholder_list = TREE_CHAIN (placeholder_expr);
-+ temp = expand_expr (exp, original_target, tmode, modifier);
-+ placeholder_list = old_list;
-+ return temp;
-+ }
-+
-+ case WITH_RECORD_EXPR:
-+ /* Put the object on the placeholder list, expand our first operand,
-+ and pop the list. */
-+ placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
-+ placeholder_list);
-+ target = expand_expr (TREE_OPERAND (exp, 0), original_target, tmode,
-+ modifier);
-+ placeholder_list = TREE_CHAIN (placeholder_list);
-+ return target;
-+
-+ case GOTO_EXPR:
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == LABEL_DECL)
-+ expand_goto (TREE_OPERAND (exp, 0));
-+ else
-+ expand_computed_goto (TREE_OPERAND (exp, 0));
-+ return const0_rtx;
-+
-+ case EXIT_EXPR:
-+ expand_exit_loop_if_false (NULL,
-+ invert_truthvalue (TREE_OPERAND (exp, 0)));
-+ return const0_rtx;
-+
-+ case LABELED_BLOCK_EXPR:
-+ if (LABELED_BLOCK_BODY (exp))
-+ expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0, 1);
-+ /* Should perhaps use expand_label, but this is simpler and safer. */
-+ do_pending_stack_adjust ();
-+ emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
-+ return const0_rtx;
-+
-+ case EXIT_BLOCK_EXPR:
-+ if (EXIT_BLOCK_RETURN (exp))
-+ sorry ("returned value in block_exit_expr");
-+ expand_goto (LABELED_BLOCK_LABEL (EXIT_BLOCK_LABELED_BLOCK (exp)));
-+ return const0_rtx;
-+
-+ case LOOP_EXPR:
-+ push_temp_slots ();
-+ expand_start_loop (1);
-+ expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1);
-+ expand_end_loop ();
-+ pop_temp_slots ();
-+
-+ return const0_rtx;
-+
-+ case BIND_EXPR:
-+ {
-+ tree vars = TREE_OPERAND (exp, 0);
-+ int vars_need_expansion = 0;
-+
-+ /* Need to open a binding contour here because
-+ if there are any cleanups they must be contained here. */
-+ expand_start_bindings (2);
-+
-+ /* Mark the corresponding BLOCK for output in its proper place. */
-+ if (TREE_OPERAND (exp, 2) != 0
-+ && ! TREE_USED (TREE_OPERAND (exp, 2)))
-+ (*lang_hooks.decls.insert_block) (TREE_OPERAND (exp, 2));
-+
-+ /* If VARS have not yet been expanded, expand them now. */
-+ while (vars)
-+ {
-+ if (!DECL_RTL_SET_P (vars))
-+ {
-+ vars_need_expansion = 1;
-+ expand_decl (vars);
-+ }
-+ expand_decl_init (vars);
-+ vars = TREE_CHAIN (vars);
-+ }
-+
-+ temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier);
-+
-+ expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
-+
-+ return temp;
-+ }
-+
-+ case RTL_EXPR:
-+ if (RTL_EXPR_SEQUENCE (exp))
-+ {
-+ if (RTL_EXPR_SEQUENCE (exp) == const0_rtx)
-+ abort ();
-+ emit_insn (RTL_EXPR_SEQUENCE (exp));
-+ RTL_EXPR_SEQUENCE (exp) = const0_rtx;
-+ }
-+ preserve_rtl_expr_result (RTL_EXPR_RTL (exp));
-+ free_temps_for_rtl_expr (exp);
-+ return RTL_EXPR_RTL (exp);
-+
-+ case CONSTRUCTOR:
-+ /* If we don't need the result, just ensure we evaluate any
-+ subexpressions. */
-+ if (ignore)
-+ {
-+ tree elt;
-+
-+ for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
-+ expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
-+
-+ return const0_rtx;
-+ }
-+
-+ /* All elts simple constants => refer to a constant in memory. But
-+ if this is a non-BLKmode mode, let it store a field at a time
-+ since that should make a CONST_INT or CONST_DOUBLE when we
-+ fold. Likewise, if we have a target we can use, it is best to
-+ store directly into the target unless the type is large enough
-+ that memcpy will be used. If we are making an initializer and
-+ all operands are constant, put it in memory as well.
-+
-+ FIXME: Avoid trying to fill vector constructors piece-meal.
-+ Output them with output_constant_def below unless we're sure
-+ they're zeros. This should go away when vector initializers
-+ are treated like VECTOR_CST instead of arrays.
-+ */
-+ else if ((TREE_STATIC (exp)
-+ && ((mode == BLKmode
-+ && ! (target != 0 && safe_from_p (target, exp, 1)))
-+ || TREE_ADDRESSABLE (exp)
-+ || (host_integerp (TYPE_SIZE_UNIT (type), 1)
-+ && (! MOVE_BY_PIECES_P
-+ (tree_low_cst (TYPE_SIZE_UNIT (type), 1),
-+ TYPE_ALIGN (type)))
-+ && ((TREE_CODE (type) == VECTOR_TYPE
-+ && !is_zeros_p (exp))
-+ || ! mostly_zeros_p (exp)))))
-+ || (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
-+ {
-+ rtx constructor = output_constant_def (exp, 1);
-+
-+ if (modifier != EXPAND_CONST_ADDRESS
-+ && modifier != EXPAND_INITIALIZER
-+ && modifier != EXPAND_SUM)
-+ constructor = validize_mem (constructor);
-+
-+ return constructor;
-+ }
-+ else
-+ {
-+ /* Handle calls that pass values in multiple non-contiguous
-+ locations. The Irix 6 ABI has examples of this. */
-+ if (target == 0 || ! safe_from_p (target, exp, 1)
-+ || GET_CODE (target) == PARALLEL
-+ || modifier == EXPAND_STACK_PARM)
-+ target
-+ = assign_temp (build_qualified_type (type,
-+ (TYPE_QUALS (type)
-+ | (TREE_READONLY (exp)
-+ * TYPE_QUAL_CONST))),
-+ 0, TREE_ADDRESSABLE (exp), 1);
-+
-+ store_constructor (exp, target, 0, int_expr_size (exp));
-+ return target;
-+ }
-+
-+ case INDIRECT_REF:
-+ {
-+ tree exp1 = TREE_OPERAND (exp, 0);
-+ tree index;
-+ tree string = string_constant (exp1, &index);
-+
-+ /* Try to optimize reads from const strings. */
-+ if (string
-+ && TREE_CODE (string) == STRING_CST
-+ && TREE_CODE (index) == INTEGER_CST
-+ && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
-+ && GET_MODE_CLASS (mode) == MODE_INT
-+ && GET_MODE_SIZE (mode) == 1
-+ && modifier != EXPAND_WRITE)
-+ return gen_int_mode (TREE_STRING_POINTER (string)
-+ [TREE_INT_CST_LOW (index)], mode);
-+
-+ op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
-+ op0 = memory_address (mode, op0);
-+ temp = gen_rtx_MEM (mode, op0);
-+ set_mem_attributes (temp, exp, 0);
-+
-+ /* If we are writing to this object and its type is a record with
-+ readonly fields, we must mark it as readonly so it will
-+ conflict with readonly references to those fields. */
-+ if (modifier == EXPAND_WRITE && readonly_fields_p (type))
-+ RTX_UNCHANGING_P (temp) = 1;
-+
-+ return temp;
-+ }
-+
-+ case ARRAY_REF:
-+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE)
-+ abort ();
-+
-+ {
-+ tree array = TREE_OPERAND (exp, 0);
-+ tree domain = TYPE_DOMAIN (TREE_TYPE (array));
-+ tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
-+ tree index = convert (sizetype, TREE_OPERAND (exp, 1));
-+ HOST_WIDE_INT i;
-+
-+ /* Optimize the special-case of a zero lower bound.
-+
-+ We convert the low_bound to sizetype to avoid some problems
-+ with constant folding. (E.g. suppose the lower bound is 1,
-+ and its mode is QI. Without the conversion, (ARRAY
-+ +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
-+ +INDEX), which becomes (ARRAY+255+INDEX). Oops!) */
-+
-+ if (! integer_zerop (low_bound))
-+ index = size_diffop (index, convert (sizetype, low_bound));
-+
-+ /* Fold an expression like: "foo"[2].
-+ This is not done in fold so it won't happen inside &.
-+ Don't fold if this is for wide characters since it's too
-+ difficult to do correctly and this is a very rare case. */
-+
-+ if (modifier != EXPAND_CONST_ADDRESS
-+ && modifier != EXPAND_INITIALIZER
-+ && modifier != EXPAND_MEMORY
-+ && TREE_CODE (array) == STRING_CST
-+ && TREE_CODE (index) == INTEGER_CST
-+ && compare_tree_int (index, TREE_STRING_LENGTH (array)) < 0
-+ && GET_MODE_CLASS (mode) == MODE_INT
-+ && GET_MODE_SIZE (mode) == 1)
-+ return gen_int_mode (TREE_STRING_POINTER (array)
-+ [TREE_INT_CST_LOW (index)], mode);
-+
-+ /* If this is a constant index into a constant array,
-+ just get the value from the array. Handle both the cases when
-+ we have an explicit constructor and when our operand is a variable
-+ that was declared const. */
-+
-+ if (modifier != EXPAND_CONST_ADDRESS
-+ && modifier != EXPAND_INITIALIZER
-+ && modifier != EXPAND_MEMORY
-+ && TREE_CODE (array) == CONSTRUCTOR
-+ && ! TREE_SIDE_EFFECTS (array)
-+ && TREE_CODE (index) == INTEGER_CST
-+ && 0 > compare_tree_int (index,
-+ list_length (CONSTRUCTOR_ELTS
-+ (TREE_OPERAND (exp, 0)))))
-+ {
-+ tree elem;
-+
-+ for (elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)),
-+ i = TREE_INT_CST_LOW (index);
-+ elem != 0 && i != 0; i--, elem = TREE_CHAIN (elem))
-+ ;
-+
-+ if (elem)
-+ return expand_expr (fold (TREE_VALUE (elem)), target, tmode,
-+ modifier);
-+ }
-+
-+ else if (optimize >= 1
-+ && modifier != EXPAND_CONST_ADDRESS
-+ && modifier != EXPAND_INITIALIZER
-+ && modifier != EXPAND_MEMORY
-+ && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
-+ && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
-+ && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK)
-+ {
-+ if (TREE_CODE (index) == INTEGER_CST)
-+ {
-+ tree init = DECL_INITIAL (array);
-+
-+ if (TREE_CODE (init) == CONSTRUCTOR)
-+ {
-+ tree elem;
-+
-+ for (elem = CONSTRUCTOR_ELTS (init);
-+ (elem
-+ && !tree_int_cst_equal (TREE_PURPOSE (elem), index));
-+ elem = TREE_CHAIN (elem))
-+ ;
-+
-+ if (elem && !TREE_SIDE_EFFECTS (TREE_VALUE (elem)))
-+ return expand_expr (fold (TREE_VALUE (elem)), target,
-+ tmode, modifier);
-+ }
-+ else if (TREE_CODE (init) == STRING_CST
-+ && 0 > compare_tree_int (index,
-+ TREE_STRING_LENGTH (init)))
-+ {
-+ tree type = TREE_TYPE (TREE_TYPE (init));
-+ enum machine_mode mode = TYPE_MODE (type);
-+
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && GET_MODE_SIZE (mode) == 1)
-+ return gen_int_mode (TREE_STRING_POINTER (init)
-+ [TREE_INT_CST_LOW (index)], mode);
-+ }
-+ }
-+ }
-+ }
-+ /* Fall through. */
-+
-+ case COMPONENT_REF:
-+ case BIT_FIELD_REF:
-+ case ARRAY_RANGE_REF:
-+ /* If the operand is a CONSTRUCTOR, we can just extract the
-+ appropriate field if it is present. Don't do this if we have
-+ already written the data since we want to refer to that copy
-+ and varasm.c assumes that's what we'll do. */
-+ if (code == COMPONENT_REF
-+ && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
-+ && TREE_CST_RTL (TREE_OPERAND (exp, 0)) == 0)
-+ {
-+ tree elt;
-+
-+ for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
-+ elt = TREE_CHAIN (elt))
-+ if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1)
-+ /* We can normally use the value of the field in the
-+ CONSTRUCTOR. However, if this is a bitfield in
-+ an integral mode that we can fit in a HOST_WIDE_INT,
-+ we must mask only the number of bits in the bitfield,
-+ since this is done implicitly by the constructor. If
-+ the bitfield does not meet either of those conditions,
-+ we can't do this optimization. */
-+ && (! DECL_BIT_FIELD (TREE_PURPOSE (elt))
-+ || ((GET_MODE_CLASS (DECL_MODE (TREE_PURPOSE (elt)))
-+ == MODE_INT)
-+ && (GET_MODE_BITSIZE (DECL_MODE (TREE_PURPOSE (elt)))
-+ <= HOST_BITS_PER_WIDE_INT))))
-+ {
-+ if (DECL_BIT_FIELD (TREE_PURPOSE (elt))
-+ && modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ op0 = expand_expr (TREE_VALUE (elt), target, tmode, modifier);
-+ if (DECL_BIT_FIELD (TREE_PURPOSE (elt)))
-+ {
-+ HOST_WIDE_INT bitsize
-+ = TREE_INT_CST_LOW (DECL_SIZE (TREE_PURPOSE (elt)));
-+ enum machine_mode imode
-+ = TYPE_MODE (TREE_TYPE (TREE_PURPOSE (elt)));
-+
-+ if (TREE_UNSIGNED (TREE_TYPE (TREE_PURPOSE (elt))))
-+ {
-+ op1 = GEN_INT (((HOST_WIDE_INT) 1 << bitsize) - 1);
-+ op0 = expand_and (imode, op0, op1, target);
-+ }
-+ else
-+ {
-+ tree count
-+ = build_int_2 (GET_MODE_BITSIZE (imode) - bitsize,
-+ 0);
-+
-+ op0 = expand_shift (LSHIFT_EXPR, imode, op0, count,
-+ target, 0);
-+ op0 = expand_shift (RSHIFT_EXPR, imode, op0, count,
-+ target, 0);
-+ }
-+ }
-+
-+ return op0;
-+ }
-+ }
-+
-+ {
-+ enum machine_mode mode1;
-+ HOST_WIDE_INT bitsize, bitpos;
-+ tree offset;
-+ int volatilep = 0;
-+ tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
-+ &mode1, &unsignedp, &volatilep);
-+ rtx orig_op0;
-+
-+ /* If we got back the original object, something is wrong. Perhaps
-+ we are evaluating an expression too early. In any event, don't
-+ infinitely recurse. */
-+ if (tem == exp)
-+ abort ();
-+
-+ /* If TEM's type is a union of variable size, pass TARGET to the inner
-+ computation, since it will need a temporary and TARGET is known
-+ to have to do. This occurs in unchecked conversion in Ada. */
-+
-+ orig_op0 = op0
-+ = expand_expr (tem,
-+ (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
-+ && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
-+ != INTEGER_CST)
-+ && modifier != EXPAND_STACK_PARM
-+ ? target : NULL_RTX),
-+ VOIDmode,
-+ (modifier == EXPAND_INITIALIZER
-+ || modifier == EXPAND_CONST_ADDRESS
-+ || modifier == EXPAND_STACK_PARM)
-+ ? modifier : EXPAND_NORMAL);
-+
-+ /* If this is a constant, put it into a register if it is a
-+ legitimate constant and OFFSET is 0 and memory if it isn't. */
-+ if (CONSTANT_P (op0))
-+ {
-+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
-+ if (mode != BLKmode && LEGITIMATE_CONSTANT_P (op0)
-+ && offset == 0)
-+ op0 = force_reg (mode, op0);
-+ else
-+ op0 = validize_mem (force_const_mem (mode, op0));
-+ }
-+
-+ if (offset != 0)
-+ {
-+ rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
-+ EXPAND_SUM);
-+
-+ /* If this object is in a register, put it into memory.
-+ This case can't occur in C, but can in Ada if we have
-+ unchecked conversion of an expression from a scalar type to
-+ an array or record type. */
-+ if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
-+ || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
-+ {
-+ /* If the operand is a SAVE_EXPR, we can deal with this by
-+ forcing the SAVE_EXPR into memory. */
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
-+ {
-+ put_var_into_stack (TREE_OPERAND (exp, 0),
-+ /*rescan=*/true);
-+ op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
-+ }
-+ else
-+ {
-+ tree nt
-+ = build_qualified_type (TREE_TYPE (tem),
-+ (TYPE_QUALS (TREE_TYPE (tem))
-+ | TYPE_QUAL_CONST));
-+ rtx memloc = assign_temp (nt, 1, 1, 1);
-+
-+ emit_move_insn (memloc, op0);
-+ op0 = memloc;
-+ }
-+ }
-+
-+ if (GET_CODE (op0) != MEM)
-+ abort ();
-+
-+#ifdef POINTERS_EXTEND_UNSIGNED
-+ if (GET_MODE (offset_rtx) != Pmode)
-+ offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
-+#else
-+ if (GET_MODE (offset_rtx) != ptr_mode)
-+ offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
-+#endif
-+
-+ /* A constant address in OP0 can have VOIDmode, we must not try
-+ to call force_reg for that case. Avoid that case. */
-+ if (GET_CODE (op0) == MEM
-+ && GET_MODE (op0) == BLKmode
-+ && GET_MODE (XEXP (op0, 0)) != VOIDmode
-+ && bitsize != 0
-+ && (bitpos % bitsize) == 0
-+ && (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
-+ && MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
-+ {
-+ op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
-+ bitpos = 0;
-+ }
-+
-+ op0 = offset_address (op0, offset_rtx,
-+ highest_pow2_factor (offset));
-+ }
-+
-+ /* If OFFSET is making OP0 more aligned than BIGGEST_ALIGNMENT,
-+ record its alignment as BIGGEST_ALIGNMENT. */
-+ if (GET_CODE (op0) == MEM && bitpos == 0 && offset != 0
-+ && is_aligning_offset (offset, tem))
-+ set_mem_align (op0, BIGGEST_ALIGNMENT);
-+
-+ /* Don't forget about volatility even if this is a bitfield. */
-+ if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
-+ {
-+ if (op0 == orig_op0)
-+ op0 = copy_rtx (op0);
-+
-+ MEM_VOLATILE_P (op0) = 1;
-+ }
-+
-+ /* The following code doesn't handle CONCAT.
-+ Assume only bitpos == 0 can be used for CONCAT, due to
-+ one element arrays having the same mode as its element. */
-+ if (GET_CODE (op0) == CONCAT)
-+ {
-+ if (bitpos != 0 || bitsize != GET_MODE_BITSIZE (GET_MODE (op0)))
-+ abort ();
-+ return op0;
-+ }
-+
-+ /* In cases where an aligned union has an unaligned object
-+ as a field, we might be extracting a BLKmode value from
-+ an integer-mode (e.g., SImode) object. Handle this case
-+ by doing the extract into an object as wide as the field
-+ (which we know to be the width of a basic mode), then
-+ storing into memory, and changing the mode to BLKmode. */
-+ if (mode1 == VOIDmode
-+ || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
-+ || (mode1 != BLKmode && ! direct_load[(int) mode1]
-+ && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
-+ && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT
-+ && modifier != EXPAND_CONST_ADDRESS
-+ && modifier != EXPAND_INITIALIZER)
-+ /* If the field isn't aligned enough to fetch as a memref,
-+ fetch it as a bit field. */
-+ || (mode1 != BLKmode
-+ && SLOW_UNALIGNED_ACCESS (mode1, MEM_ALIGN (op0))
-+ && ((TYPE_ALIGN (TREE_TYPE (tem))
-+ < GET_MODE_ALIGNMENT (mode))
-+ || (bitpos % GET_MODE_ALIGNMENT (mode) != 0)))
-+ /* If the type and the field are a constant size and the
-+ size of the type isn't the same size as the bitfield,
-+ we must use bitfield operations. */
-+ || (bitsize >= 0
-+ && (TREE_CODE (TYPE_SIZE (TREE_TYPE (exp)))
-+ == INTEGER_CST)
-+ && 0 != compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)),
-+ bitsize)))
-+ {
-+ enum machine_mode ext_mode = mode;
-+
-+ if (ext_mode == BLKmode
-+ && ! (target != 0 && GET_CODE (op0) == MEM
-+ && GET_CODE (target) == MEM
-+ && bitpos % BITS_PER_UNIT == 0))
-+ ext_mode = mode_for_size (bitsize, MODE_INT, 1);
-+
-+ if (ext_mode == BLKmode)
-+ {
-+ /* In this case, BITPOS must start at a byte boundary and
-+ TARGET, if specified, must be a MEM. */
-+ if (GET_CODE (op0) != MEM
-+ || (target != 0 && GET_CODE (target) != MEM)
-+ || bitpos % BITS_PER_UNIT != 0)
-+ abort ();
-+
-+ op0 = adjust_address (op0, VOIDmode, bitpos / BITS_PER_UNIT);
-+ if (target == 0)
-+ target = assign_temp (type, 0, 1, 1);
-+
-+ emit_block_move (target, op0,
-+ GEN_INT ((bitsize + BITS_PER_UNIT - 1)
-+ / BITS_PER_UNIT),
-+ (modifier == EXPAND_STACK_PARM
-+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
-+
-+ return target;
-+ }
-+
-+ op0 = validize_mem (op0);
-+
-+ if (GET_CODE (op0) == MEM && GET_CODE (XEXP (op0, 0)) == REG)
-+ mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
-+
-+ op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
-+ (modifier == EXPAND_STACK_PARM
-+ ? NULL_RTX : target),
-+ ext_mode, ext_mode,
-+ int_size_in_bytes (TREE_TYPE (tem)));
-+
-+ /* If the result is a record type and BITSIZE is narrower than
-+ the mode of OP0, an integral mode, and this is a big endian
-+ machine, we must put the field into the high-order bits. */
-+ if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN
-+ && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
-+ && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0)))
-+ op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
-+ size_int (GET_MODE_BITSIZE (GET_MODE (op0))
-+ - bitsize),
-+ op0, 1);
-+
-+ if (mode == BLKmode)
-+ {
-+ rtx new = assign_temp (build_qualified_type
-+ ((*lang_hooks.types.type_for_mode)
-+ (ext_mode, 0),
-+ TYPE_QUAL_CONST), 0, 1, 1);
-+
-+ emit_move_insn (new, op0);
-+ op0 = copy_rtx (new);
-+ PUT_MODE (op0, BLKmode);
-+ set_mem_attributes (op0, exp, 1);
-+ }
-+
-+ return op0;
-+ }
-+
-+ /* If the result is BLKmode, use that to access the object
-+ now as well. */
-+ if (mode == BLKmode)
-+ mode1 = BLKmode;
-+
-+ /* Get a reference to just this component. */
-+ if (modifier == EXPAND_CONST_ADDRESS
-+ || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
-+ op0 = adjust_address_nv (op0, mode1, bitpos / BITS_PER_UNIT);
-+ else
-+ op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
-+
-+ if (op0 == orig_op0)
-+ op0 = copy_rtx (op0);
-+
-+ set_mem_attributes (op0, exp, 0);
-+ if (GET_CODE (XEXP (op0, 0)) == REG)
-+ mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
-+
-+ MEM_VOLATILE_P (op0) |= volatilep;
-+ if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
-+ || modifier == EXPAND_CONST_ADDRESS
-+ || modifier == EXPAND_INITIALIZER)
-+ return op0;
-+ else if (target == 0)
-+ target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
-+
-+ convert_move (target, op0, unsignedp);
-+ return target;
-+ }
-+
-+ case VTABLE_REF:
-+ {
-+ rtx insn, before = get_last_insn (), vtbl_ref;
-+
-+ /* Evaluate the interior expression. */
-+ subtarget = expand_expr (TREE_OPERAND (exp, 0), target,
-+ tmode, modifier);
-+
-+ /* Get or create an instruction off which to hang a note. */
-+ if (REG_P (subtarget))
-+ {
-+ target = subtarget;
-+ insn = get_last_insn ();
-+ if (insn == before)
-+ abort ();
-+ if (! INSN_P (insn))
-+ insn = prev_nonnote_insn (insn);
-+ }
-+ else
-+ {
-+ target = gen_reg_rtx (GET_MODE (subtarget));
-+ insn = emit_move_insn (target, subtarget);
-+ }
-+
-+ /* Collect the data for the note. */
-+ vtbl_ref = XEXP (DECL_RTL (TREE_OPERAND (exp, 1)), 0);
-+ vtbl_ref = plus_constant (vtbl_ref,
-+ tree_low_cst (TREE_OPERAND (exp, 2), 0));
-+ /* Discard the initial CONST that was added. */
-+ vtbl_ref = XEXP (vtbl_ref, 0);
-+
-+ REG_NOTES (insn)
-+ = gen_rtx_EXPR_LIST (REG_VTABLE_REF, vtbl_ref, REG_NOTES (insn));
-+
-+ return target;
-+ }
-+
-+ /* Intended for a reference to a buffer of a file-object in Pascal.
-+ But it's not certain that a special tree code will really be
-+ necessary for these. INDIRECT_REF might work for them. */
-+ case BUFFER_REF:
-+ abort ();
-+
-+ case IN_EXPR:
-+ {
-+ /* Pascal set IN expression.
-+
-+ Algorithm:
-+ rlo = set_low - (set_low%bits_per_word);
-+ the_word = set [ (index - rlo)/bits_per_word ];
-+ bit_index = index % bits_per_word;
-+ bitmask = 1 << bit_index;
-+ return !!(the_word & bitmask); */
-+
-+ tree set = TREE_OPERAND (exp, 0);
-+ tree index = TREE_OPERAND (exp, 1);
-+ int iunsignedp = TREE_UNSIGNED (TREE_TYPE (index));
-+ tree set_type = TREE_TYPE (set);
-+ tree set_low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (set_type));
-+ tree set_high_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (set_type));
-+ rtx index_val = expand_expr (index, 0, VOIDmode, 0);
-+ rtx lo_r = expand_expr (set_low_bound, 0, VOIDmode, 0);
-+ rtx hi_r = expand_expr (set_high_bound, 0, VOIDmode, 0);
-+ rtx setval = expand_expr (set, 0, VOIDmode, 0);
-+ rtx setaddr = XEXP (setval, 0);
-+ enum machine_mode index_mode = TYPE_MODE (TREE_TYPE (index));
-+ rtx rlow;
-+ rtx diff, quo, rem, addr, bit, result;
-+
-+ /* If domain is empty, answer is no. Likewise if index is constant
-+ and out of bounds. */
-+ if (((TREE_CODE (set_high_bound) == INTEGER_CST
-+ && TREE_CODE (set_low_bound) == INTEGER_CST
-+ && tree_int_cst_lt (set_high_bound, set_low_bound))
-+ || (TREE_CODE (index) == INTEGER_CST
-+ && TREE_CODE (set_low_bound) == INTEGER_CST
-+ && tree_int_cst_lt (index, set_low_bound))
-+ || (TREE_CODE (set_high_bound) == INTEGER_CST
-+ && TREE_CODE (index) == INTEGER_CST
-+ && tree_int_cst_lt (set_high_bound, index))))
-+ return const0_rtx;
-+
-+ if (target == 0)
-+ target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
-+
-+ /* If we get here, we have to generate the code for both cases
-+ (in range and out of range). */
-+
-+ op0 = gen_label_rtx ();
-+ op1 = gen_label_rtx ();
-+
-+ if (! (GET_CODE (index_val) == CONST_INT
-+ && GET_CODE (lo_r) == CONST_INT))
-+ emit_cmp_and_jump_insns (index_val, lo_r, LT, NULL_RTX,
-+ GET_MODE (index_val), iunsignedp, op1);
-+
-+ if (! (GET_CODE (index_val) == CONST_INT
-+ && GET_CODE (hi_r) == CONST_INT))
-+ emit_cmp_and_jump_insns (index_val, hi_r, GT, NULL_RTX,
-+ GET_MODE (index_val), iunsignedp, op1);
-+
-+ /* Calculate the element number of bit zero in the first word
-+ of the set. */
-+ if (GET_CODE (lo_r) == CONST_INT)
-+ rlow = GEN_INT (INTVAL (lo_r)
-+ & ~((HOST_WIDE_INT) 1 << BITS_PER_UNIT));
-+ else
-+ rlow = expand_binop (index_mode, and_optab, lo_r,
-+ GEN_INT (~((HOST_WIDE_INT) 1 << BITS_PER_UNIT)),
-+ NULL_RTX, iunsignedp, OPTAB_LIB_WIDEN);
-+
-+ diff = expand_binop (index_mode, sub_optab, index_val, rlow,
-+ NULL_RTX, iunsignedp, OPTAB_LIB_WIDEN);
-+
-+ quo = expand_divmod (0, TRUNC_DIV_EXPR, index_mode, diff,
-+ GEN_INT (BITS_PER_UNIT), NULL_RTX, iunsignedp);
-+ rem = expand_divmod (1, TRUNC_MOD_EXPR, index_mode, index_val,
-+ GEN_INT (BITS_PER_UNIT), NULL_RTX, iunsignedp);
-+
-+ addr = memory_address (byte_mode,
-+ expand_binop (index_mode, add_optab, diff,
-+ setaddr, NULL_RTX, iunsignedp,
-+ OPTAB_LIB_WIDEN));
-+
-+ /* Extract the bit we want to examine. */
-+ bit = expand_shift (RSHIFT_EXPR, byte_mode,
-+ gen_rtx_MEM (byte_mode, addr),
-+ make_tree (TREE_TYPE (index), rem),
-+ NULL_RTX, 1);
-+ result = expand_binop (byte_mode, and_optab, bit, const1_rtx,
-+ GET_MODE (target) == byte_mode ? target : 0,
-+ 1, OPTAB_LIB_WIDEN);
-+
-+ if (result != target)
-+ convert_move (target, result, 1);
-+
-+ /* Output the code to handle the out-of-range case. */
-+ emit_jump (op0);
-+ emit_label (op1);
-+ emit_move_insn (target, const0_rtx);
-+ emit_label (op0);
-+ return target;
-+ }
-+
-+ case WITH_CLEANUP_EXPR:
-+ if (WITH_CLEANUP_EXPR_RTL (exp) == 0)
-+ {
-+ WITH_CLEANUP_EXPR_RTL (exp)
-+ = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
-+ expand_decl_cleanup_eh (NULL_TREE, TREE_OPERAND (exp, 1),
-+ CLEANUP_EH_ONLY (exp));
-+
-+ /* That's it for this cleanup. */
-+ TREE_OPERAND (exp, 1) = 0;
-+ }
-+ return WITH_CLEANUP_EXPR_RTL (exp);
-+
-+ case CLEANUP_POINT_EXPR:
-+ {
-+ /* Start a new binding layer that will keep track of all cleanup
-+ actions to be performed. */
-+ expand_start_bindings (2);
-+
-+ target_temp_slot_level = temp_slot_level;
-+
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
-+ /* If we're going to use this value, load it up now. */
-+ if (! ignore)
-+ op0 = force_not_mem (op0);
-+ preserve_temp_slots (op0);
-+ expand_end_bindings (NULL_TREE, 0, 0);
-+ }
-+ return op0;
-+
-+ case CALL_EXPR:
-+ /* Check for a built-in function. */
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
-+ && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
-+ == FUNCTION_DECL)
-+ && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
-+ {
-+ if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
-+ == BUILT_IN_FRONTEND)
-+ return (*lang_hooks.expand_expr) (exp, original_target,
-+ tmode, modifier);
-+ else
-+ return expand_builtin (exp, target, subtarget, tmode, ignore);
-+ }
-+
-+ return expand_call (exp, target, ignore);
-+
-+ case NON_LVALUE_EXPR:
-+ case NOP_EXPR:
-+ case CONVERT_EXPR:
-+ case REFERENCE_EXPR:
-+ if (TREE_OPERAND (exp, 0) == error_mark_node)
-+ return const0_rtx;
-+
-+ if (TREE_CODE (type) == UNION_TYPE)
-+ {
-+ tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0));
-+
-+ /* If both input and output are BLKmode, this conversion isn't doing
-+ anything except possibly changing memory attribute. */
-+ if (mode == BLKmode && TYPE_MODE (valtype) == BLKmode)
-+ {
-+ rtx result = expand_expr (TREE_OPERAND (exp, 0), target, tmode,
-+ modifier);
-+
-+ result = copy_rtx (result);
-+ set_mem_attributes (result, exp, 0);
-+ return result;
-+ }
-+
-+ if (target == 0)
-+ target = assign_temp (type, 0, 1, 1);
-+
-+ if (GET_CODE (target) == MEM)
-+ /* Store data into beginning of memory target. */
-+ store_expr (TREE_OPERAND (exp, 0),
-+ adjust_address (target, TYPE_MODE (valtype), 0),
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+
-+ else if (GET_CODE (target) == REG)
-+ /* Store this field into a union of the proper type. */
-+ store_field (target,
-+ MIN ((int_size_in_bytes (TREE_TYPE
-+ (TREE_OPERAND (exp, 0)))
-+ * BITS_PER_UNIT),
-+ (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
-+ 0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
-+ VOIDmode, 0, type, 0);
-+ else
-+ abort ();
-+
-+ /* Return the entire union. */
-+ return target;
-+ }
-+
-+ if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
-+ {
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode,
-+ modifier);
-+
-+ /* If the signedness of the conversion differs and OP0 is
-+ a promoted SUBREG, clear that indication since we now
-+ have to do the proper extension. */
-+ if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))) != unsignedp
-+ && GET_CODE (op0) == SUBREG)
-+ SUBREG_PROMOTED_VAR_P (op0) = 0;
-+
-+ return op0;
-+ }
-+
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
-+ if (GET_MODE (op0) == mode)
-+ return op0;
-+
-+ /* If OP0 is a constant, just convert it into the proper mode. */
-+ if (CONSTANT_P (op0))
-+ {
-+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-+ enum machine_mode inner_mode = TYPE_MODE (inner_type);
-+
-+ if (modifier == EXPAND_INITIALIZER)
-+ return simplify_gen_subreg (mode, op0, inner_mode,
-+ subreg_lowpart_offset (mode,
-+ inner_mode));
-+ else
-+ return convert_modes (mode, inner_mode, op0,
-+ TREE_UNSIGNED (inner_type));
-+ }
-+
-+ if (modifier == EXPAND_INITIALIZER)
-+ return gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
-+
-+ if (target == 0)
-+ return
-+ convert_to_mode (mode, op0,
-+ TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
-+ else
-+ convert_move (target, op0,
-+ TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
-+ return target;
-+
-+ case VIEW_CONVERT_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
-+
-+ /* If the input and output modes are both the same, we are done.
-+ Otherwise, if neither mode is BLKmode and both are within a word, we
-+ can use gen_lowpart. If neither is true, make sure the operand is
-+ in memory and convert the MEM to the new mode. */
-+ if (TYPE_MODE (type) == GET_MODE (op0))
-+ ;
-+ else if (TYPE_MODE (type) != BLKmode && GET_MODE (op0) != BLKmode
-+ && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD
-+ && GET_MODE_SIZE (GET_MODE (op0)) <= UNITS_PER_WORD)
-+ op0 = gen_lowpart (TYPE_MODE (type), op0);
-+ else if (GET_CODE (op0) != MEM)
-+ {
-+ /* If the operand is not a MEM, force it into memory. Since we
-+ are going to be be changing the mode of the MEM, don't call
-+ force_const_mem for constants because we don't allow pool
-+ constants to change mode. */
-+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-+
-+ if (TREE_ADDRESSABLE (exp))
-+ abort ();
-+
-+ if (target == 0 || GET_MODE (target) != TYPE_MODE (inner_type))
-+ target
-+ = assign_stack_temp_for_type
-+ (TYPE_MODE (inner_type),
-+ GET_MODE_SIZE (TYPE_MODE (inner_type)), 0, inner_type);
-+
-+ emit_move_insn (target, op0);
-+ op0 = target;
-+ }
-+
-+ /* At this point, OP0 is in the correct mode. If the output type is such
-+ that the operand is known to be aligned, indicate that it is.
-+ Otherwise, we need only be concerned about alignment for non-BLKmode
-+ results. */
-+ if (GET_CODE (op0) == MEM)
-+ {
-+ op0 = copy_rtx (op0);
-+
-+ if (TYPE_ALIGN_OK (type))
-+ set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type)));
-+ else if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT
-+ && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
-+ {
-+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-+ HOST_WIDE_INT temp_size
-+ = MAX (int_size_in_bytes (inner_type),
-+ (HOST_WIDE_INT) GET_MODE_SIZE (TYPE_MODE (type)));
-+ rtx new = assign_stack_temp_for_type (TYPE_MODE (type),
-+ temp_size, 0, type);
-+ rtx new_with_op0_mode = adjust_address (new, GET_MODE (op0), 0);
-+
-+ if (TREE_ADDRESSABLE (exp))
-+ abort ();
-+
-+ if (GET_MODE (op0) == BLKmode)
-+ emit_block_move (new_with_op0_mode, op0,
-+ GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))),
-+ (modifier == EXPAND_STACK_PARM
-+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
-+ else
-+ emit_move_insn (new_with_op0_mode, op0);
-+
-+ op0 = new;
-+ }
-+
-+ op0 = adjust_address (op0, TYPE_MODE (type), 0);
-+ }
-+
-+ return op0;
-+
-+ case PLUS_EXPR:
-+ this_optab = ! unsignedp && flag_trapv
-+ && (GET_MODE_CLASS (mode) == MODE_INT)
-+ ? addv_optab : add_optab;
-+
-+ /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and
-+ something else, make sure we add the register to the constant and
-+ then to the other thing. This case can occur during strength
-+ reduction and doing it this way will produce better code if the
-+ frame pointer or argument pointer is eliminated.
-+
-+ fold-const.c will ensure that the constant is always in the inner
-+ PLUS_EXPR, so the only case we need to do anything about is if
-+ sp, ap, or fp is our second argument, in which case we must swap
-+ the innermost first argument and our second argument. */
-+
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
-+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
-+ && TREE_CODE (TREE_OPERAND (exp, 1)) == RTL_EXPR
-+ && (RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
-+ || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx
-+ || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx))
-+ {
-+ tree t = TREE_OPERAND (exp, 1);
-+
-+ TREE_OPERAND (exp, 1) = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
-+ TREE_OPERAND (TREE_OPERAND (exp, 0), 0) = t;
-+ }
-+
-+ /* If the result is to be ptr_mode and we are adding an integer to
-+ something, we might be forming a constant. So try to use
-+ plus_constant. If it produces a sum and we can't accept it,
-+ use force_operand. This allows P = &ARR[const] to generate
-+ efficient code on machines where a SYMBOL_REF is not a valid
-+ address.
-+
-+ If this is an EXPAND_SUM call, always return the sum. */
-+ if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
-+ || (mode == ptr_mode && (unsignedp || ! flag_trapv)))
-+ {
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
-+ && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
-+ && TREE_CONSTANT (TREE_OPERAND (exp, 1)))
-+ {
-+ rtx constant_part;
-+
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode,
-+ EXPAND_SUM);
-+ /* Use immed_double_const to ensure that the constant is
-+ truncated according to the mode of OP1, then sign extended
-+ to a HOST_WIDE_INT. Using the constant directly can result
-+ in non-canonical RTL in a 64x32 cross compile. */
-+ constant_part
-+ = immed_double_const (TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)),
-+ (HOST_WIDE_INT) 0,
-+ TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))));
-+ op1 = plus_constant (op1, INTVAL (constant_part));
-+ if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
-+ op1 = force_operand (op1, target);
-+ return op1;
-+ }
-+
-+ else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
-+ && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT
-+ && TREE_CONSTANT (TREE_OPERAND (exp, 0)))
-+ {
-+ rtx constant_part;
-+
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
-+ (modifier == EXPAND_INITIALIZER
-+ ? EXPAND_INITIALIZER : EXPAND_SUM));
-+ if (! CONSTANT_P (op0))
-+ {
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
-+ VOIDmode, modifier);
-+ /* Don't go to both_summands if modifier
-+ says it's not right to return a PLUS. */
-+ if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
-+ goto binop2;
-+ goto both_summands;
-+ }
-+ /* Use immed_double_const to ensure that the constant is
-+ truncated according to the mode of OP1, then sign extended
-+ to a HOST_WIDE_INT. Using the constant directly can result
-+ in non-canonical RTL in a 64x32 cross compile. */
-+ constant_part
-+ = immed_double_const (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)),
-+ (HOST_WIDE_INT) 0,
-+ TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))));
-+ op0 = plus_constant (op0, INTVAL (constant_part));
-+ if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
-+ op0 = force_operand (op0, target);
-+ return op0;
-+ }
-+ }
-+
-+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
-+ subtarget = 0;
-+
-+ /* No sense saving up arithmetic to be done
-+ if it's all in the wrong mode to form part of an address.
-+ And force_operand won't know whether to sign-extend or
-+ zero-extend. */
-+ if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
-+ || mode != ptr_mode)
-+ {
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+ if (op0 == const0_rtx)
-+ return op1;
-+ if (op1 == const0_rtx)
-+ return op0;
-+ goto binop2;
-+ }
-+
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
-+
-+ /* We come here from MINUS_EXPR when the second operand is a
-+ constant. */
-+ both_summands:
-+ /* Make sure any term that's a sum with a constant comes last. */
-+ if (GET_CODE (op0) == PLUS
-+ && CONSTANT_P (XEXP (op0, 1)))
-+ {
-+ temp = op0;
-+ op0 = op1;
-+ op1 = temp;
-+ }
-+ /* If adding to a sum including a constant,
-+ associate it to put the constant outside. */
-+ if (GET_CODE (op1) == PLUS
-+ && CONSTANT_P (XEXP (op1, 1)))
-+ {
-+ rtx constant_term = const0_rtx;
-+
-+ temp = simplify_binary_operation (PLUS, mode, XEXP (op1, 0), op0);
-+ if (temp != 0)
-+ op0 = temp;
-+ /* Ensure that MULT comes first if there is one. */
-+ else if (GET_CODE (op0) == MULT)
-+ op0 = gen_rtx_PLUS (mode, op0, XEXP (op1, 0));
-+ else
-+ op0 = gen_rtx_PLUS (mode, XEXP (op1, 0), op0);
-+
-+ /* Let's also eliminate constants from op0 if possible. */
-+ op0 = eliminate_constant_term (op0, &constant_term);
-+
-+ /* CONSTANT_TERM and XEXP (op1, 1) are known to be constant, so
-+ their sum should be a constant. Form it into OP1, since the
-+ result we want will then be OP0 + OP1. */
-+
-+ temp = simplify_binary_operation (PLUS, mode, constant_term,
-+ XEXP (op1, 1));
-+ if (temp != 0)
-+ op1 = temp;
-+ else
-+ op1 = gen_rtx_PLUS (mode, constant_term, XEXP (op1, 1));
-+ }
-+
-+ /* Put a constant term last and put a multiplication first. */
-+ if (CONSTANT_P (op0) || GET_CODE (op1) == MULT)
-+ temp = op1, op1 = op0, op0 = temp;
-+
-+ temp = simplify_binary_operation (PLUS, mode, op0, op1);
-+ return temp ? temp : gen_rtx_PLUS (mode, op0, op1);
-+
-+ case MINUS_EXPR:
-+ /* For initializers, we are allowed to return a MINUS of two
-+ symbolic constants. Here we handle all cases when both operands
-+ are constant. */
-+ /* Handle difference of two symbolic constants,
-+ for the sake of an initializer. */
-+ if ((modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
-+ && really_constant_p (TREE_OPERAND (exp, 0))
-+ && really_constant_p (TREE_OPERAND (exp, 1)))
-+ {
-+ rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode,
-+ modifier);
-+ rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode,
-+ modifier);
-+
-+ /* If the last operand is a CONST_INT, use plus_constant of
-+ the negated constant. Else make the MINUS. */
-+ if (GET_CODE (op1) == CONST_INT)
-+ return plus_constant (op0, - INTVAL (op1));
-+ else
-+ return gen_rtx_MINUS (mode, op0, op1);
-+ }
-+
-+ this_optab = ! unsignedp && flag_trapv
-+ && (GET_MODE_CLASS(mode) == MODE_INT)
-+ ? subv_optab : sub_optab;
-+
-+ /* No sense saving up arithmetic to be done
-+ if it's all in the wrong mode to form part of an address.
-+ And force_operand won't know whether to sign-extend or
-+ zero-extend. */
-+ if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
-+ || mode != ptr_mode)
-+ goto binop;
-+
-+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
-+ subtarget = 0;
-+
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
-+
-+ /* Convert A - const to A + (-const). */
-+ if (GET_CODE (op1) == CONST_INT)
-+ {
-+ op1 = negate_rtx (mode, op1);
-+ goto both_summands;
-+ }
-+
-+ goto binop2;
-+
-+ case MULT_EXPR:
-+ /* If first operand is constant, swap them.
-+ Thus the following special case checks need only
-+ check the second operand. */
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
-+ {
-+ tree t1 = TREE_OPERAND (exp, 0);
-+ TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
-+ TREE_OPERAND (exp, 1) = t1;
-+ }
-+
-+ /* Attempt to return something suitable for generating an
-+ indexed address, for machines that support that. */
-+
-+ if (modifier == EXPAND_SUM && mode == ptr_mode
-+ && host_integerp (TREE_OPERAND (exp, 1), 0))
-+ {
-+ tree exp1 = TREE_OPERAND (exp, 1);
-+
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
-+ EXPAND_SUM);
-+
-+ /* If we knew for certain that this is arithmetic for an array
-+ reference, and we knew the bounds of the array, then we could
-+ apply the distributive law across (PLUS X C) for constant C.
-+ Without such knowledge, we risk overflowing the computation
-+ when both X and C are large, but X+C isn't. */
-+ /* ??? Could perhaps special-case EXP being unsigned and C being
-+ positive. In that case we are certain that X+C is no smaller
-+ than X and so the transformed expression will overflow iff the
-+ original would have. */
-+
-+ if (GET_CODE (op0) != REG)
-+ op0 = force_operand (op0, NULL_RTX);
-+ if (GET_CODE (op0) != REG)
-+ op0 = copy_to_mode_reg (mode, op0);
-+
-+ return gen_rtx_MULT (mode, op0,
-+ gen_int_mode (tree_low_cst (exp1, 0),
-+ TYPE_MODE (TREE_TYPE (exp1))));
-+ }
-+
-+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
-+ subtarget = 0;
-+
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+
-+ /* Check for multiplying things that have been extended
-+ from a narrower type. If this machine supports multiplying
-+ in that narrower type with a result in the desired type,
-+ do it that way, and avoid the explicit type-conversion. */
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
-+ && TREE_CODE (type) == INTEGER_TYPE
-+ && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
-+ < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
-+ && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
-+ && int_fits_type_p (TREE_OPERAND (exp, 1),
-+ TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
-+ /* Don't use a widening multiply if a shift will do. */
-+ && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))))
-+ > HOST_BITS_PER_WIDE_INT)
-+ || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0))
-+ ||
-+ (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
-+ && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
-+ ==
-+ TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
-+ /* If both operands are extended, they must either both
-+ be zero-extended or both be sign-extended. */
-+ && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
-+ ==
-+ TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
-+ {
-+ enum machine_mode innermode
-+ = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
-+ optab other_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
-+ ? smul_widen_optab : umul_widen_optab);
-+ this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
-+ ? umul_widen_optab : smul_widen_optab);
-+ if (mode == GET_MODE_WIDER_MODE (innermode))
-+ {
-+ if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-+ NULL_RTX, VOIDmode, 0);
-+ if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
-+ VOIDmode, 0);
-+ else
-+ op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
-+ NULL_RTX, VOIDmode, 0);
-+ goto binop2;
-+ }
-+ else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
-+ && innermode == word_mode)
-+ {
-+ rtx htem;
-+ op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-+ NULL_RTX, VOIDmode, 0);
-+ if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
-+ op1 = convert_modes (innermode, mode,
-+ expand_expr (TREE_OPERAND (exp, 1),
-+ NULL_RTX, VOIDmode, 0),
-+ unsignedp);
-+ else
-+ op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
-+ NULL_RTX, VOIDmode, 0);
-+ temp = expand_binop (mode, other_optab, op0, op1, target,
-+ unsignedp, OPTAB_LIB_WIDEN);
-+ htem = expand_mult_highpart_adjust (innermode,
-+ gen_highpart (innermode, temp),
-+ op0, op1,
-+ gen_highpart (innermode, temp),
-+ unsignedp);
-+ emit_move_insn (gen_highpart (innermode, temp), htem);
-+ return temp;
-+ }
-+ }
-+ }
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+ return expand_mult (mode, op0, op1, target, unsignedp);
-+
-+ case TRUNC_DIV_EXPR:
-+ case FLOOR_DIV_EXPR:
-+ case CEIL_DIV_EXPR:
-+ case ROUND_DIV_EXPR:
-+ case EXACT_DIV_EXPR:
-+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
-+ subtarget = 0;
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ /* Possible optimization: compute the dividend with EXPAND_SUM
-+ then if the divisor is constant can optimize the case
-+ where some terms of the dividend have coeffs divisible by it. */
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+ return expand_divmod (0, code, mode, op0, op1, target, unsignedp);
-+
-+ case RDIV_EXPR:
-+ /* Emit a/b as a*(1/b). Later we may manage CSE the reciprocal saving
-+ expensive divide. If not, combine will rebuild the original
-+ computation. */
-+ if (flag_unsafe_math_optimizations && optimize && !optimize_size
-+ && TREE_CODE (type) == REAL_TYPE
-+ && !real_onep (TREE_OPERAND (exp, 0)))
-+ return expand_expr (build (MULT_EXPR, type, TREE_OPERAND (exp, 0),
-+ build (RDIV_EXPR, type,
-+ build_real (type, dconst1),
-+ TREE_OPERAND (exp, 1))),
-+ target, tmode, modifier);
-+ this_optab = sdiv_optab;
-+ goto binop;
-+
-+ case TRUNC_MOD_EXPR:
-+ case FLOOR_MOD_EXPR:
-+ case CEIL_MOD_EXPR:
-+ case ROUND_MOD_EXPR:
-+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
-+ subtarget = 0;
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+ return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
-+
-+ case FIX_ROUND_EXPR:
-+ case FIX_FLOOR_EXPR:
-+ case FIX_CEIL_EXPR:
-+ abort (); /* Not used for C. */
-+
-+ case FIX_TRUNC_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
-+ if (target == 0 || modifier == EXPAND_STACK_PARM)
-+ target = gen_reg_rtx (mode);
-+ expand_fix (target, op0, unsignedp);
-+ return target;
-+
-+ case FLOAT_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
-+ if (target == 0 || modifier == EXPAND_STACK_PARM)
-+ target = gen_reg_rtx (mode);
-+ /* expand_float can't figure out what to do if FROM has VOIDmode.
-+ So give it the correct mode. With -O, cse will optimize this. */
-+ if (GET_MODE (op0) == VOIDmode)
-+ op0 = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
-+ op0);
-+ expand_float (target, op0,
-+ TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
-+ return target;
-+
-+ case NEGATE_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ temp = expand_unop (mode,
-+ ! unsignedp && flag_trapv
-+ && (GET_MODE_CLASS(mode) == MODE_INT)
-+ ? negv_optab : neg_optab, op0, target, 0);
-+ if (temp == 0)
-+ abort ();
-+ return temp;
-+
-+ case ABS_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+
-+ /* Handle complex values specially. */
-+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
-+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
-+ return expand_complex_abs (mode, op0, target, unsignedp);
-+
-+ /* Unsigned abs is simply the operand. Testing here means we don't
-+ risk generating incorrect code below. */
-+ if (TREE_UNSIGNED (type))
-+ return op0;
-+
-+ return expand_abs (mode, op0, target, unsignedp,
-+ safe_from_p (target, TREE_OPERAND (exp, 0), 1));
-+
-+ case MAX_EXPR:
-+ case MIN_EXPR:
-+ target = original_target;
-+ if (target == 0
-+ || modifier == EXPAND_STACK_PARM
-+ || ! safe_from_p (target, TREE_OPERAND (exp, 1), 1)
-+ || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
-+ || GET_MODE (target) != mode
-+ || (GET_CODE (target) == REG
-+ && REGNO (target) < FIRST_PSEUDO_REGISTER))
-+ target = gen_reg_rtx (mode);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
-+
-+ /* First try to do it with a special MIN or MAX instruction.
-+ If that does not win, use a conditional jump to select the proper
-+ value. */
-+ this_optab = (TREE_UNSIGNED (type)
-+ ? (code == MIN_EXPR ? umin_optab : umax_optab)
-+ : (code == MIN_EXPR ? smin_optab : smax_optab));
-+
-+ temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
-+ OPTAB_WIDEN);
-+ if (temp != 0)
-+ return temp;
-+
-+ /* At this point, a MEM target is no longer useful; we will get better
-+ code without it. */
-+
-+ if (GET_CODE (target) == MEM)
-+ target = gen_reg_rtx (mode);
-+
-+ if (target != op0)
-+ emit_move_insn (target, op0);
-+
-+ op0 = gen_label_rtx ();
-+
-+ /* If this mode is an integer too wide to compare properly,
-+ compare word by word. Rely on cse to optimize constant cases. */
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && ! can_compare_p (GE, mode, ccp_jump))
-+ {
-+ if (code == MAX_EXPR)
-+ do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type),
-+ target, op1, NULL_RTX, op0);
-+ else
-+ do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type),
-+ op1, target, NULL_RTX, op0);
-+ }
-+ else
-+ {
-+ int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)));
-+ do_compare_rtx_and_jump (target, op1, code == MAX_EXPR ? GE : LE,
-+ unsignedp, mode, NULL_RTX, NULL_RTX,
-+ op0);
-+ }
-+ emit_move_insn (target, op1);
-+ emit_label (op0);
-+ return target;
-+
-+ case BIT_NOT_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
-+ if (temp == 0)
-+ abort ();
-+ return temp;
-+
-+ case FFS_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ temp = expand_unop (mode, ffs_optab, op0, target, 1);
-+ if (temp == 0)
-+ abort ();
-+ return temp;
-+
-+ /* ??? Can optimize bitwise operations with one arg constant.
-+ Can optimize (a bitwise1 n) bitwise2 (a bitwise3 b)
-+ and (a bitwise1 b) bitwise2 b (etc)
-+ but that is probably not worth while. */
-+
-+ /* BIT_AND_EXPR is for bitwise anding. TRUTH_AND_EXPR is for anding two
-+ boolean values when we want in all cases to compute both of them. In
-+ general it is fastest to do TRUTH_AND_EXPR by computing both operands
-+ as actual zero-or-1 values and then bitwise anding. In cases where
-+ there cannot be any side effects, better code would be made by
-+ treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR; but the question is
-+ how to recognize those cases. */
-+
-+ case TRUTH_AND_EXPR:
-+ case BIT_AND_EXPR:
-+ this_optab = and_optab;
-+ goto binop;
-+
-+ case TRUTH_OR_EXPR:
-+ case BIT_IOR_EXPR:
-+ this_optab = ior_optab;
-+ goto binop;
-+
-+ case TRUTH_XOR_EXPR:
-+ case BIT_XOR_EXPR:
-+ this_optab = xor_optab;
-+ goto binop;
-+
-+ case LSHIFT_EXPR:
-+ case RSHIFT_EXPR:
-+ case LROTATE_EXPR:
-+ case RROTATE_EXPR:
-+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
-+ subtarget = 0;
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
-+ unsignedp);
-+
-+ /* Could determine the answer when only additive constants differ. Also,
-+ the addition of one can be handled by changing the condition. */
-+ case LT_EXPR:
-+ case LE_EXPR:
-+ case GT_EXPR:
-+ case GE_EXPR:
-+ case EQ_EXPR:
-+ case NE_EXPR:
-+ case UNORDERED_EXPR:
-+ case ORDERED_EXPR:
-+ case UNLT_EXPR:
-+ case UNLE_EXPR:
-+ case UNGT_EXPR:
-+ case UNGE_EXPR:
-+ case UNEQ_EXPR:
-+ temp = do_store_flag (exp,
-+ modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
-+ tmode != VOIDmode ? tmode : mode, 0);
-+ if (temp != 0)
-+ return temp;
-+
-+ /* For foo != 0, load foo, and if it is nonzero load 1 instead. */
-+ if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1))
-+ && original_target
-+ && GET_CODE (original_target) == REG
-+ && (GET_MODE (original_target)
-+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
-+ {
-+ temp = expand_expr (TREE_OPERAND (exp, 0), original_target,
-+ VOIDmode, 0);
-+
-+ /* If temp is constant, we can just compute the result. */
-+ if (GET_CODE (temp) == CONST_INT)
-+ {
-+ if (INTVAL (temp) != 0)
-+ emit_move_insn (target, const1_rtx);
-+ else
-+ emit_move_insn (target, const0_rtx);
-+
-+ return target;
-+ }
-+
-+ if (temp != original_target)
-+ {
-+ enum machine_mode mode1 = GET_MODE (temp);
-+ if (mode1 == VOIDmode)
-+ mode1 = tmode != VOIDmode ? tmode : mode;
-+
-+ temp = copy_to_mode_reg (mode1, temp);
-+ }
-+
-+ op1 = gen_label_rtx ();
-+ emit_cmp_and_jump_insns (temp, const0_rtx, EQ, NULL_RTX,
-+ GET_MODE (temp), unsignedp, op1);
-+ emit_move_insn (temp, const1_rtx);
-+ emit_label (op1);
-+ return temp;
-+ }
-+
-+ /* If no set-flag instruction, must generate a conditional
-+ store into a temporary variable. Drop through
-+ and handle this like && and ||. */
-+
-+ case TRUTH_ANDIF_EXPR:
-+ case TRUTH_ORIF_EXPR:
-+ if (! ignore
-+ && (target == 0
-+ || modifier == EXPAND_STACK_PARM
-+ || ! safe_from_p (target, exp, 1)
-+ /* Make sure we don't have a hard reg (such as function's return
-+ value) live across basic blocks, if not optimizing. */
-+ || (!optimize && GET_CODE (target) == REG
-+ && REGNO (target) < FIRST_PSEUDO_REGISTER)))
-+ target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
-+
-+ if (target)
-+ emit_clr_insn (target);
-+
-+ op1 = gen_label_rtx ();
-+ jumpifnot (exp, op1);
-+
-+ if (target)
-+ emit_0_to_1_insn (target);
-+
-+ emit_label (op1);
-+ return ignore ? const0_rtx : target;
-+
-+ case TRUTH_NOT_EXPR:
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
-+ /* The parser is careful to generate TRUTH_NOT_EXPR
-+ only with operands that are always zero or one. */
-+ temp = expand_binop (mode, xor_optab, op0, const1_rtx,
-+ target, 1, OPTAB_LIB_WIDEN);
-+ if (temp == 0)
-+ abort ();
-+ return temp;
-+
-+ case COMPOUND_EXPR:
-+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
-+ emit_queue ();
-+ return expand_expr (TREE_OPERAND (exp, 1),
-+ (ignore ? const0_rtx : target),
-+ VOIDmode, modifier);
-+
-+ case COND_EXPR:
-+ /* If we would have a "singleton" (see below) were it not for a
-+ conversion in each arm, bring that conversion back out. */
-+ if (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
-+ && TREE_CODE (TREE_OPERAND (exp, 2)) == NOP_EXPR
-+ && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0))
-+ == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 2), 0))))
-+ {
-+ tree iftrue = TREE_OPERAND (TREE_OPERAND (exp, 1), 0);
-+ tree iffalse = TREE_OPERAND (TREE_OPERAND (exp, 2), 0);
-+
-+ if ((TREE_CODE_CLASS (TREE_CODE (iftrue)) == '2'
-+ && operand_equal_p (iffalse, TREE_OPERAND (iftrue, 0), 0))
-+ || (TREE_CODE_CLASS (TREE_CODE (iffalse)) == '2'
-+ && operand_equal_p (iftrue, TREE_OPERAND (iffalse, 0), 0))
-+ || (TREE_CODE_CLASS (TREE_CODE (iftrue)) == '1'
-+ && operand_equal_p (iffalse, TREE_OPERAND (iftrue, 0), 0))
-+ || (TREE_CODE_CLASS (TREE_CODE (iffalse)) == '1'
-+ && operand_equal_p (iftrue, TREE_OPERAND (iffalse, 0), 0)))
-+ return expand_expr (build1 (NOP_EXPR, type,
-+ build (COND_EXPR, TREE_TYPE (iftrue),
-+ TREE_OPERAND (exp, 0),
-+ iftrue, iffalse)),
-+ target, tmode, modifier);
-+ }
-+
-+ {
-+ /* Note that COND_EXPRs whose type is a structure or union
-+ are required to be constructed to contain assignments of
-+ a temporary variable, so that we can evaluate them here
-+ for side effect only. If type is void, we must do likewise. */
-+
-+ /* If an arm of the branch requires a cleanup,
-+ only that cleanup is performed. */
-+
-+ tree singleton = 0;
-+ tree binary_op = 0, unary_op = 0;
-+
-+ /* If this is (A ? 1 : 0) and A is a condition, just evaluate it and
-+ convert it to our mode, if necessary. */
-+ if (integer_onep (TREE_OPERAND (exp, 1))
-+ && integer_zerop (TREE_OPERAND (exp, 2))
-+ && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
-+ {
-+ if (ignore)
-+ {
-+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
-+ modifier);
-+ return const0_rtx;
-+ }
-+
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier);
-+ if (GET_MODE (op0) == mode)
-+ return op0;
-+
-+ if (target == 0)
-+ target = gen_reg_rtx (mode);
-+ convert_move (target, op0, unsignedp);
-+ return target;
-+ }
-+
-+ /* Check for X ? A + B : A. If we have this, we can copy A to the
-+ output and conditionally add B. Similarly for unary operations.
-+ Don't do this if X has side-effects because those side effects
-+ might affect A or B and the "?" operation is a sequence point in
-+ ANSI. (operand_equal_p tests for side effects.) */
-+
-+ if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '2'
-+ && operand_equal_p (TREE_OPERAND (exp, 2),
-+ TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
-+ singleton = TREE_OPERAND (exp, 2), binary_op = TREE_OPERAND (exp, 1);
-+ else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '2'
-+ && operand_equal_p (TREE_OPERAND (exp, 1),
-+ TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
-+ singleton = TREE_OPERAND (exp, 1), binary_op = TREE_OPERAND (exp, 2);
-+ else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '1'
-+ && operand_equal_p (TREE_OPERAND (exp, 2),
-+ TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
-+ singleton = TREE_OPERAND (exp, 2), unary_op = TREE_OPERAND (exp, 1);
-+ else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '1'
-+ && operand_equal_p (TREE_OPERAND (exp, 1),
-+ TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
-+ singleton = TREE_OPERAND (exp, 1), unary_op = TREE_OPERAND (exp, 2);
-+
-+ /* If we are not to produce a result, we have no target. Otherwise,
-+ if a target was specified use it; it will not be used as an
-+ intermediate target unless it is safe. If no target, use a
-+ temporary. */
-+
-+ if (ignore)
-+ temp = 0;
-+ else if (modifier == EXPAND_STACK_PARM)
-+ temp = assign_temp (type, 0, 0, 1);
-+ else if (original_target
-+ && (safe_from_p (original_target, TREE_OPERAND (exp, 0), 1)
-+ || (singleton && GET_CODE (original_target) == REG
-+ && REGNO (original_target) >= FIRST_PSEUDO_REGISTER
-+ && original_target == var_rtx (singleton)))
-+ && GET_MODE (original_target) == mode
-+#ifdef HAVE_conditional_move
-+ && (! can_conditionally_move_p (mode)
-+ || GET_CODE (original_target) == REG
-+ || TREE_ADDRESSABLE (type))
-+#endif
-+ && (GET_CODE (original_target) != MEM
-+ || TREE_ADDRESSABLE (type)))
-+ temp = original_target;
-+ else if (TREE_ADDRESSABLE (type))
-+ abort ();
-+ else
-+ temp = assign_temp (type, 0, 0, 1);
-+
-+ /* If we had X ? A + C : A, with C a constant power of 2, and we can
-+ do the test of X as a store-flag operation, do this as
-+ A + ((X != 0) << log C). Similarly for other simple binary
-+ operators. Only do for C == 1 if BRANCH_COST is low. */
-+ if (temp && singleton && binary_op
-+ && (TREE_CODE (binary_op) == PLUS_EXPR
-+ || TREE_CODE (binary_op) == MINUS_EXPR
-+ || TREE_CODE (binary_op) == BIT_IOR_EXPR
-+ || TREE_CODE (binary_op) == BIT_XOR_EXPR)
-+ && (BRANCH_COST >= 3 ? integer_pow2p (TREE_OPERAND (binary_op, 1))
-+ : integer_onep (TREE_OPERAND (binary_op, 1)))
-+ && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
-+ {
-+ rtx result;
-+ tree cond;
-+ optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR
-+ ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
-+ ? addv_optab : add_optab)
-+ : TREE_CODE (binary_op) == MINUS_EXPR
-+ ? (TYPE_TRAP_SIGNED (TREE_TYPE (binary_op))
-+ ? subv_optab : sub_optab)
-+ : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
-+ : xor_optab);
-+
-+ /* If we had X ? A : A + 1, do this as A + (X == 0). */
-+ if (singleton == TREE_OPERAND (exp, 1))
-+ cond = invert_truthvalue (TREE_OPERAND (exp, 0));
-+ else
-+ cond = TREE_OPERAND (exp, 0);
-+
-+ result = do_store_flag (cond, (safe_from_p (temp, singleton, 1)
-+ ? temp : NULL_RTX),
-+ mode, BRANCH_COST <= 1);
-+
-+ if (result != 0 && ! integer_onep (TREE_OPERAND (binary_op, 1)))
-+ result = expand_shift (LSHIFT_EXPR, mode, result,
-+ build_int_2 (tree_log2
-+ (TREE_OPERAND
-+ (binary_op, 1)),
-+ 0),
-+ (safe_from_p (temp, singleton, 1)
-+ ? temp : NULL_RTX), 0);
-+
-+ if (result)
-+ {
-+ op1 = expand_expr (singleton, NULL_RTX, VOIDmode, 0);
-+ return expand_binop (mode, boptab, op1, result, temp,
-+ unsignedp, OPTAB_LIB_WIDEN);
-+ }
-+ }
-+
-+ do_pending_stack_adjust ();
-+ NO_DEFER_POP;
-+ op0 = gen_label_rtx ();
-+
-+ if (singleton && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
-+ {
-+ if (temp != 0)
-+ {
-+ /* If the target conflicts with the other operand of the
-+ binary op, we can't use it. Also, we can't use the target
-+ if it is a hard register, because evaluating the condition
-+ might clobber it. */
-+ if ((binary_op
-+ && ! safe_from_p (temp, TREE_OPERAND (binary_op, 1), 1))
-+ || (GET_CODE (temp) == REG
-+ && REGNO (temp) < FIRST_PSEUDO_REGISTER))
-+ temp = gen_reg_rtx (mode);
-+ store_expr (singleton, temp,
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ }
-+ else
-+ expand_expr (singleton,
-+ ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-+ if (singleton == TREE_OPERAND (exp, 1))
-+ jumpif (TREE_OPERAND (exp, 0), op0);
-+ else
-+ jumpifnot (TREE_OPERAND (exp, 0), op0);
-+
-+ start_cleanup_deferral ();
-+ if (binary_op && temp == 0)
-+ /* Just touch the other operand. */
-+ expand_expr (TREE_OPERAND (binary_op, 1),
-+ ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-+ else if (binary_op)
-+ store_expr (build (TREE_CODE (binary_op), type,
-+ make_tree (type, temp),
-+ TREE_OPERAND (binary_op, 1)),
-+ temp, modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ else
-+ store_expr (build1 (TREE_CODE (unary_op), type,
-+ make_tree (type, temp)),
-+ temp, modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ op1 = op0;
-+ }
-+ /* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any
-+ comparison operator. If we have one of these cases, set the
-+ output to A, branch on A (cse will merge these two references),
-+ then set the output to FOO. */
-+ else if (temp
-+ && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
-+ && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
-+ && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-+ TREE_OPERAND (exp, 1), 0)
-+ && (! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
-+ || TREE_CODE (TREE_OPERAND (exp, 1)) == SAVE_EXPR)
-+ && safe_from_p (temp, TREE_OPERAND (exp, 2), 1))
-+ {
-+ if (GET_CODE (temp) == REG
-+ && REGNO (temp) < FIRST_PSEUDO_REGISTER)
-+ temp = gen_reg_rtx (mode);
-+ store_expr (TREE_OPERAND (exp, 1), temp,
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ jumpif (TREE_OPERAND (exp, 0), op0);
-+
-+ start_cleanup_deferral ();
-+ store_expr (TREE_OPERAND (exp, 2), temp,
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ op1 = op0;
-+ }
-+ else if (temp
-+ && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
-+ && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
-+ && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
-+ TREE_OPERAND (exp, 2), 0)
-+ && (! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
-+ || TREE_CODE (TREE_OPERAND (exp, 2)) == SAVE_EXPR)
-+ && safe_from_p (temp, TREE_OPERAND (exp, 1), 1))
-+ {
-+ if (GET_CODE (temp) == REG
-+ && REGNO (temp) < FIRST_PSEUDO_REGISTER)
-+ temp = gen_reg_rtx (mode);
-+ store_expr (TREE_OPERAND (exp, 2), temp,
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ jumpifnot (TREE_OPERAND (exp, 0), op0);
-+
-+ start_cleanup_deferral ();
-+ store_expr (TREE_OPERAND (exp, 1), temp,
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ op1 = op0;
-+ }
-+ else
-+ {
-+ op1 = gen_label_rtx ();
-+ jumpifnot (TREE_OPERAND (exp, 0), op0);
-+
-+ start_cleanup_deferral ();
-+
-+ /* One branch of the cond can be void, if it never returns. For
-+ example A ? throw : E */
-+ if (temp != 0
-+ && TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
-+ store_expr (TREE_OPERAND (exp, 1), temp,
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ else
-+ expand_expr (TREE_OPERAND (exp, 1),
-+ ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-+ end_cleanup_deferral ();
-+ emit_queue ();
-+ emit_jump_insn (gen_jump (op1));
-+ emit_barrier ();
-+ emit_label (op0);
-+ start_cleanup_deferral ();
-+ if (temp != 0
-+ && TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
-+ store_expr (TREE_OPERAND (exp, 2), temp,
-+ modifier == EXPAND_STACK_PARM ? 2 : 0);
-+ else
-+ expand_expr (TREE_OPERAND (exp, 2),
-+ ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
-+ }
-+
-+ end_cleanup_deferral ();
-+
-+ emit_queue ();
-+ emit_label (op1);
-+ OK_DEFER_POP;
-+
-+ return temp;
-+ }
-+
-+ case TARGET_EXPR:
-+ {
-+ /* Something needs to be initialized, but we didn't know
-+ where that thing was when building the tree. For example,
-+ it could be the return value of a function, or a parameter
-+ to a function which lays down in the stack, or a temporary
-+ variable which must be passed by reference.
-+
-+ We guarantee that the expression will either be constructed
-+ or copied into our original target. */
-+
-+ tree slot = TREE_OPERAND (exp, 0);
-+ tree cleanups = NULL_TREE;
-+ tree exp1;
-+
-+ if (TREE_CODE (slot) != VAR_DECL)
-+ abort ();
-+
-+ if (! ignore)
-+ target = original_target;
-+
-+ /* Set this here so that if we get a target that refers to a
-+ register variable that's already been used, put_reg_into_stack
-+ knows that it should fix up those uses. */
-+ TREE_USED (slot) = 1;
-+
-+ if (target == 0)
-+ {
-+ if (DECL_RTL_SET_P (slot))
-+ {
-+ target = DECL_RTL (slot);
-+ /* If we have already expanded the slot, so don't do
-+ it again. (mrs) */
-+ if (TREE_OPERAND (exp, 1) == NULL_TREE)
-+ return target;
-+ }
-+ else
-+ {
-+ target = assign_temp (type, 2, 0, 1);
-+ /* All temp slots at this level must not conflict. */
-+ preserve_temp_slots (target);
-+ SET_DECL_RTL (slot, target);
-+ if (TREE_ADDRESSABLE (slot))
-+ put_var_into_stack (slot, /*rescan=*/false);
-+
-+ /* Since SLOT is not known to the called function
-+ to belong to its stack frame, we must build an explicit
-+ cleanup. This case occurs when we must build up a reference
-+ to pass the reference as an argument. In this case,
-+ it is very likely that such a reference need not be
-+ built here. */
-+
-+ if (TREE_OPERAND (exp, 2) == 0)
-+ TREE_OPERAND (exp, 2)
-+ = (*lang_hooks.maybe_build_cleanup) (slot);
-+ cleanups = TREE_OPERAND (exp, 2);
-+ }
-+ }
-+ else
-+ {
-+ /* This case does occur, when expanding a parameter which
-+ needs to be constructed on the stack. The target
-+ is the actual stack address that we want to initialize.
-+ The function we call will perform the cleanup in this case. */
-+
-+ /* If we have already assigned it space, use that space,
-+ not target that we were passed in, as our target
-+ parameter is only a hint. */
-+ if (DECL_RTL_SET_P (slot))
-+ {
-+ target = DECL_RTL (slot);
-+ /* If we have already expanded the slot, so don't do
-+ it again. (mrs) */
-+ if (TREE_OPERAND (exp, 1) == NULL_TREE)
-+ return target;
-+ }
-+ else
-+ {
-+ SET_DECL_RTL (slot, target);
-+ /* If we must have an addressable slot, then make sure that
-+ the RTL that we just stored in slot is OK. */
-+ if (TREE_ADDRESSABLE (slot))
-+ put_var_into_stack (slot, /*rescan=*/true);
-+ }
-+ }
-+
-+ exp1 = TREE_OPERAND (exp, 3) = TREE_OPERAND (exp, 1);
-+ /* Mark it as expanded. */
-+ TREE_OPERAND (exp, 1) = NULL_TREE;
-+
-+ store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
-+
-+ expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp));
-+
-+ return target;
-+ }
-+
-+ case INIT_EXPR:
-+ {
-+ tree lhs = TREE_OPERAND (exp, 0);
-+ tree rhs = TREE_OPERAND (exp, 1);
-+
-+ temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
-+ return temp;
-+ }
-+
-+ case MODIFY_EXPR:
-+ {
-+ /* If lhs is complex, expand calls in rhs before computing it.
-+ That's so we don't compute a pointer and save it over a
-+ call. If lhs is simple, compute it first so we can give it
-+ as a target if the rhs is just a call. This avoids an
-+ extra temp and copy and that prevents a partial-subsumption
-+ which makes bad code. Actually we could treat
-+ component_ref's of vars like vars. */
-+
-+ tree lhs = TREE_OPERAND (exp, 0);
-+ tree rhs = TREE_OPERAND (exp, 1);
-+
-+ temp = 0;
-+
-+ /* Check for |= or &= of a bitfield of size one into another bitfield
-+ of size 1. In this case, (unless we need the result of the
-+ assignment) we can do this more efficiently with a
-+ test followed by an assignment, if necessary.
-+
-+ ??? At this point, we can't get a BIT_FIELD_REF here. But if
-+ things change so we do, this code should be enhanced to
-+ support it. */
-+ if (ignore
-+ && TREE_CODE (lhs) == COMPONENT_REF
-+ && (TREE_CODE (rhs) == BIT_IOR_EXPR
-+ || TREE_CODE (rhs) == BIT_AND_EXPR)
-+ && TREE_OPERAND (rhs, 0) == lhs
-+ && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF
-+ && integer_onep (DECL_SIZE (TREE_OPERAND (lhs, 1)))
-+ && integer_onep (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))))
-+ {
-+ rtx label = gen_label_rtx ();
-+
-+ do_jump (TREE_OPERAND (rhs, 1),
-+ TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0,
-+ TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0);
-+ expand_assignment (lhs, convert (TREE_TYPE (rhs),
-+ (TREE_CODE (rhs) == BIT_IOR_EXPR
-+ ? integer_one_node
-+ : integer_zero_node)),
-+ 0, 0);
-+ do_pending_stack_adjust ();
-+ emit_label (label);
-+ return const0_rtx;
-+ }
-+
-+ temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
-+
-+ return temp;
-+ }
-+
-+ case RETURN_EXPR:
-+ if (!TREE_OPERAND (exp, 0))
-+ expand_null_return ();
-+ else
-+ expand_return (TREE_OPERAND (exp, 0));
-+ return const0_rtx;
-+
-+ case PREINCREMENT_EXPR:
-+ case PREDECREMENT_EXPR:
-+ return expand_increment (exp, 0, ignore);
-+
-+ case POSTINCREMENT_EXPR:
-+ case POSTDECREMENT_EXPR:
-+ /* Faster to treat as pre-increment if result is not used. */
-+ return expand_increment (exp, ! ignore, ignore);
-+
-+ case ADDR_EXPR:
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ /* Are we taking the address of a nested function? */
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL
-+ && decl_function_context (TREE_OPERAND (exp, 0)) != 0
-+ && ! DECL_NO_STATIC_CHAIN (TREE_OPERAND (exp, 0))
-+ && ! TREE_STATIC (exp))
-+ {
-+ op0 = trampoline_address (TREE_OPERAND (exp, 0));
-+ op0 = force_operand (op0, target);
-+ }
-+ /* If we are taking the address of something erroneous, just
-+ return a zero. */
-+ else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
-+ return const0_rtx;
-+ /* If we are taking the address of a constant and are at the
-+ top level, we have to use output_constant_def since we can't
-+ call force_const_mem at top level. */
-+ else if (cfun == 0
-+ && (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
-+ || (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0)))
-+ == 'c')))
-+ op0 = XEXP (output_constant_def (TREE_OPERAND (exp, 0), 0), 0);
-+ else
-+ {
-+ /* We make sure to pass const0_rtx down if we came in with
-+ ignore set, to avoid doing the cleanups twice for something. */
-+ op0 = expand_expr (TREE_OPERAND (exp, 0),
-+ ignore ? const0_rtx : NULL_RTX, VOIDmode,
-+ (modifier == EXPAND_INITIALIZER
-+ ? modifier : EXPAND_CONST_ADDRESS));
-+
-+ /* If we are going to ignore the result, OP0 will have been set
-+ to const0_rtx, so just return it. Don't get confused and
-+ think we are taking the address of the constant. */
-+ if (ignore)
-+ return op0;
-+
-+ /* Pass 1 for MODIFY, so that protect_from_queue doesn't get
-+ clever and returns a REG when given a MEM. */
-+ op0 = protect_from_queue (op0, 1);
-+
-+ /* We would like the object in memory. If it is a constant, we can
-+ have it be statically allocated into memory. For a non-constant,
-+ we need to allocate some memory and store the value into it. */
-+
-+ if (CONSTANT_P (op0))
-+ op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
-+ op0);
-+ else if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
-+ || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
-+ || GET_CODE (op0) == PARALLEL)
-+ {
-+ /* If the operand is a SAVE_EXPR, we can deal with this by
-+ forcing the SAVE_EXPR into memory. */
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
-+ {
-+ put_var_into_stack (TREE_OPERAND (exp, 0),
-+ /*rescan=*/true);
-+ op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
-+ }
-+ else
-+ {
-+ /* If this object is in a register, it can't be BLKmode. */
-+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-+ rtx memloc = assign_temp (inner_type, 1, 1, 1);
-+
-+ if (GET_CODE (op0) == PARALLEL)
-+ /* Handle calls that pass values in multiple
-+ non-contiguous locations. The Irix 6 ABI has examples
-+ of this. */
-+ emit_group_store (memloc, op0,
-+ int_size_in_bytes (inner_type));
-+ else
-+ emit_move_insn (memloc, op0);
-+
-+ op0 = memloc;
-+ }
-+ }
-+
-+ if (GET_CODE (op0) != MEM)
-+ abort ();
-+
-+ mark_temp_addr_taken (op0);
-+ if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
-+ {
-+ op0 = XEXP (op0, 0);
-+#ifdef POINTERS_EXTEND_UNSIGNED
-+ if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode
-+ && mode == ptr_mode)
-+ op0 = convert_memory_address (ptr_mode, op0);
-+#endif
-+ return op0;
-+ }
-+
-+ /* If OP0 is not aligned as least as much as the type requires, we
-+ need to make a temporary, copy OP0 to it, and take the address of
-+ the temporary. We want to use the alignment of the type, not of
-+ the operand. Note that this is incorrect for FUNCTION_TYPE, but
-+ the test for BLKmode means that can't happen. The test for
-+ BLKmode is because we never make mis-aligned MEMs with
-+ non-BLKmode.
-+
-+ We don't need to do this at all if the machine doesn't have
-+ strict alignment. */
-+ if (STRICT_ALIGNMENT && GET_MODE (op0) == BLKmode
-+ && (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
-+ > MEM_ALIGN (op0))
-+ && MEM_ALIGN (op0) < BIGGEST_ALIGNMENT)
-+ {
-+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-+ rtx new;
-+
-+ if (TYPE_ALIGN_OK (inner_type))
-+ abort ();
-+
-+ if (TREE_ADDRESSABLE (inner_type))
-+ {
-+ /* We can't make a bitwise copy of this object, so fail. */
-+ error ("cannot take the address of an unaligned member");
-+ return const0_rtx;
-+ }
-+
-+ new = assign_stack_temp_for_type
-+ (TYPE_MODE (inner_type),
-+ MEM_SIZE (op0) ? INTVAL (MEM_SIZE (op0))
-+ : int_size_in_bytes (inner_type),
-+ 1, build_qualified_type (inner_type,
-+ (TYPE_QUALS (inner_type)
-+ | TYPE_QUAL_CONST)));
-+
-+ emit_block_move (new, op0, expr_size (TREE_OPERAND (exp, 0)),
-+ (modifier == EXPAND_STACK_PARM
-+ ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
-+
-+ op0 = new;
-+ }
-+
-+ op0 = force_operand (XEXP (op0, 0), target);
-+ }
-+
-+ if (flag_force_addr
-+ && GET_CODE (op0) != REG
-+ && modifier != EXPAND_CONST_ADDRESS
-+ && modifier != EXPAND_INITIALIZER
-+ && modifier != EXPAND_SUM)
-+ op0 = force_reg (Pmode, op0);
-+
-+ if (GET_CODE (op0) == REG
-+ && ! REG_USERVAR_P (op0))
-+ mark_reg_pointer (op0, TYPE_ALIGN (TREE_TYPE (type)));
-+
-+#ifdef POINTERS_EXTEND_UNSIGNED
-+ if (GET_MODE (op0) == Pmode && GET_MODE (op0) != mode
-+ && mode == ptr_mode)
-+ op0 = convert_memory_address (ptr_mode, op0);
-+#endif
-+
-+ return op0;
-+
-+ case ENTRY_VALUE_EXPR:
-+ abort ();
-+
-+ /* COMPLEX type for Extended Pascal & Fortran */
-+ case COMPLEX_EXPR:
-+ {
-+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
-+ rtx insns;
-+
-+ /* Get the rtx code of the operands. */
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
-+
-+ if (! target)
-+ target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
-+
-+ start_sequence ();
-+
-+ /* Move the real (op0) and imaginary (op1) parts to their location. */
-+ emit_move_insn (gen_realpart (mode, target), op0);
-+ emit_move_insn (gen_imagpart (mode, target), op1);
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ /* Complex construction should appear as a single unit. */
-+ /* If TARGET is a CONCAT, we got insns like RD = RS, ID = IS,
-+ each with a separate pseudo as destination.
-+ It's not correct for flow to treat them as a unit. */
-+ if (GET_CODE (target) != CONCAT)
-+ emit_no_conflict_block (insns, target, op0, op1, NULL_RTX);
-+ else
-+ emit_insn (insns);
-+
-+ return target;
-+ }
-+
-+ case REALPART_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
-+ return gen_realpart (mode, op0);
-+
-+ case IMAGPART_EXPR:
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
-+ return gen_imagpart (mode, op0);
-+
-+ case CONJ_EXPR:
-+ {
-+ enum machine_mode partmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
-+ rtx imag_t;
-+ rtx insns;
-+
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
-+
-+ if (! target)
-+ target = gen_reg_rtx (mode);
-+
-+ start_sequence ();
-+
-+ /* Store the realpart and the negated imagpart to target. */
-+ emit_move_insn (gen_realpart (partmode, target),
-+ gen_realpart (partmode, op0));
-+
-+ imag_t = gen_imagpart (partmode, target);
-+ temp = expand_unop (partmode,
-+ ! unsignedp && flag_trapv
-+ && (GET_MODE_CLASS(partmode) == MODE_INT)
-+ ? negv_optab : neg_optab,
-+ gen_imagpart (partmode, op0), imag_t, 0);
-+ if (temp != imag_t)
-+ emit_move_insn (imag_t, temp);
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ /* Conjugate should appear as a single unit
-+ If TARGET is a CONCAT, we got insns like RD = RS, ID = - IS,
-+ each with a separate pseudo as destination.
-+ It's not correct for flow to treat them as a unit. */
-+ if (GET_CODE (target) != CONCAT)
-+ emit_no_conflict_block (insns, target, op0, NULL_RTX, NULL_RTX);
-+ else
-+ emit_insn (insns);
-+
-+ return target;
-+ }
-+
-+ case TRY_CATCH_EXPR:
-+ {
-+ tree handler = TREE_OPERAND (exp, 1);
-+
-+ expand_eh_region_start ();
-+
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
-+
-+ expand_eh_region_end_cleanup (handler);
-+
-+ return op0;
-+ }
-+
-+ case TRY_FINALLY_EXPR:
-+ {
-+ tree try_block = TREE_OPERAND (exp, 0);
-+ tree finally_block = TREE_OPERAND (exp, 1);
-+
-+ if (!optimize || unsafe_for_reeval (finally_block) > 1)
-+ {
-+ /* In this case, wrapping FINALLY_BLOCK in an UNSAVE_EXPR
-+ is not sufficient, so we cannot expand the block twice.
-+ So we play games with GOTO_SUBROUTINE_EXPR to let us
-+ expand the thing only once. */
-+ /* When not optimizing, we go ahead with this form since
-+ (1) user breakpoints operate more predictably without
-+ code duplication, and
-+ (2) we're not running any of the global optimizers
-+ that would explode in time/space with the highly
-+ connected CFG created by the indirect branching. */
-+
-+ rtx finally_label = gen_label_rtx ();
-+ rtx done_label = gen_label_rtx ();
-+ rtx return_link = gen_reg_rtx (Pmode);
-+ tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node,
-+ (tree) finally_label, (tree) return_link);
-+ TREE_SIDE_EFFECTS (cleanup) = 1;
-+
-+ /* Start a new binding layer that will keep track of all cleanup
-+ actions to be performed. */
-+ expand_start_bindings (2);
-+ target_temp_slot_level = temp_slot_level;
-+
-+ expand_decl_cleanup (NULL_TREE, cleanup);
-+ op0 = expand_expr (try_block, target, tmode, modifier);
-+
-+ preserve_temp_slots (op0);
-+ expand_end_bindings (NULL_TREE, 0, 0);
-+ emit_jump (done_label);
-+ emit_label (finally_label);
-+ expand_expr (finally_block, const0_rtx, VOIDmode, 0);
-+ emit_indirect_jump (return_link);
-+ emit_label (done_label);
-+ }
-+ else
-+ {
-+ expand_start_bindings (2);
-+ target_temp_slot_level = temp_slot_level;
-+
-+ expand_decl_cleanup (NULL_TREE, finally_block);
-+ op0 = expand_expr (try_block, target, tmode, modifier);
-+
-+ preserve_temp_slots (op0);
-+ expand_end_bindings (NULL_TREE, 0, 0);
-+ }
-+
-+ return op0;
-+ }
-+
-+ case GOTO_SUBROUTINE_EXPR:
-+ {
-+ rtx subr = (rtx) TREE_OPERAND (exp, 0);
-+ rtx return_link = *(rtx *) &TREE_OPERAND (exp, 1);
-+ rtx return_address = gen_label_rtx ();
-+ emit_move_insn (return_link,
-+ gen_rtx_LABEL_REF (Pmode, return_address));
-+ emit_jump (subr);
-+ emit_label (return_address);
-+ return const0_rtx;
-+ }
-+
-+ case VA_ARG_EXPR:
-+ return expand_builtin_va_arg (TREE_OPERAND (exp, 0), type);
-+
-+ case EXC_PTR_EXPR:
-+ return get_exception_pointer (cfun);
-+
-+ case FDESC_EXPR:
-+ /* Function descriptors are not valid except for as
-+ initialization constants, and should not be expanded. */
-+ abort ();
-+
-+ default:
-+ return (*lang_hooks.expand_expr) (exp, original_target, tmode, modifier);
-+ }
-+
-+ /* Here to do an ordinary binary operator, generating an instruction
-+ from the optab already placed in `this_optab'. */
-+ binop:
-+ if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
-+ subtarget = 0;
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+ binop2:
-+ if (modifier == EXPAND_STACK_PARM)
-+ target = 0;
-+ temp = expand_binop (mode, this_optab, op0, op1, target,
-+ unsignedp, OPTAB_LIB_WIDEN);
-+ if (temp == 0)
-+ abort ();
-+ return temp;
-+}
-+\f
-+/* Subroutine of above: returns 1 if OFFSET corresponds to an offset that
-+ when applied to the address of EXP produces an address known to be
-+ aligned more than BIGGEST_ALIGNMENT. */
-+
-+static int
-+is_aligning_offset (offset, exp)
-+ tree offset;
-+ tree exp;
-+{
-+ /* Strip off any conversions and WITH_RECORD_EXPR nodes. */
-+ while (TREE_CODE (offset) == NON_LVALUE_EXPR
-+ || TREE_CODE (offset) == NOP_EXPR
-+ || TREE_CODE (offset) == CONVERT_EXPR
-+ || TREE_CODE (offset) == WITH_RECORD_EXPR)
-+ offset = TREE_OPERAND (offset, 0);
-+
-+ /* We must now have a BIT_AND_EXPR with a constant that is one less than
-+ power of 2 and which is larger than BIGGEST_ALIGNMENT. */
-+ if (TREE_CODE (offset) != BIT_AND_EXPR
-+ || !host_integerp (TREE_OPERAND (offset, 1), 1)
-+ || compare_tree_int (TREE_OPERAND (offset, 1), BIGGEST_ALIGNMENT) <= 0
-+ || !exact_log2 (tree_low_cst (TREE_OPERAND (offset, 1), 1) + 1) < 0)
-+ return 0;
-+
-+ /* Look at the first operand of BIT_AND_EXPR and strip any conversion.
-+ It must be NEGATE_EXPR. Then strip any more conversions. */
-+ offset = TREE_OPERAND (offset, 0);
-+ while (TREE_CODE (offset) == NON_LVALUE_EXPR
-+ || TREE_CODE (offset) == NOP_EXPR
-+ || TREE_CODE (offset) == CONVERT_EXPR)
-+ offset = TREE_OPERAND (offset, 0);
-+
-+ if (TREE_CODE (offset) != NEGATE_EXPR)
-+ return 0;
-+
-+ offset = TREE_OPERAND (offset, 0);
-+ while (TREE_CODE (offset) == NON_LVALUE_EXPR
-+ || TREE_CODE (offset) == NOP_EXPR
-+ || TREE_CODE (offset) == CONVERT_EXPR)
-+ offset = TREE_OPERAND (offset, 0);
-+
-+ /* This must now be the address either of EXP or of a PLACEHOLDER_EXPR
-+ whose type is the same as EXP. */
-+ return (TREE_CODE (offset) == ADDR_EXPR
-+ && (TREE_OPERAND (offset, 0) == exp
-+ || (TREE_CODE (TREE_OPERAND (offset, 0)) == PLACEHOLDER_EXPR
-+ && (TREE_TYPE (TREE_OPERAND (offset, 0))
-+ == TREE_TYPE (exp)))));
-+}
-+\f
-+/* Return the tree node if an ARG corresponds to a string constant or zero
-+ if it doesn't. If we return nonzero, set *PTR_OFFSET to the offset
-+ in bytes within the string that ARG is accessing. The type of the
-+ offset will be `sizetype'. */
-+
-+tree
-+string_constant (arg, ptr_offset)
-+ tree arg;
-+ tree *ptr_offset;
-+{
-+ STRIP_NOPS (arg);
-+
-+ if (TREE_CODE (arg) == ADDR_EXPR
-+ && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
-+ {
-+ *ptr_offset = size_zero_node;
-+ return TREE_OPERAND (arg, 0);
-+ }
-+ else if (TREE_CODE (arg) == PLUS_EXPR)
-+ {
-+ tree arg0 = TREE_OPERAND (arg, 0);
-+ tree arg1 = TREE_OPERAND (arg, 1);
-+
-+ STRIP_NOPS (arg0);
-+ STRIP_NOPS (arg1);
-+
-+ if (TREE_CODE (arg0) == ADDR_EXPR
-+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST)
-+ {
-+ *ptr_offset = convert (sizetype, arg1);
-+ return TREE_OPERAND (arg0, 0);
-+ }
-+ else if (TREE_CODE (arg1) == ADDR_EXPR
-+ && TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST)
-+ {
-+ *ptr_offset = convert (sizetype, arg0);
-+ return TREE_OPERAND (arg1, 0);
-+ }
-+ }
-+
-+ return 0;
-+}
-+\f
-+/* Expand code for a post- or pre- increment or decrement
-+ and return the RTX for the result.
-+ POST is 1 for postinc/decrements and 0 for preinc/decrements. */
-+
-+static rtx
-+expand_increment (exp, post, ignore)
-+ tree exp;
-+ int post, ignore;
-+{
-+ rtx op0, op1;
-+ rtx temp, value;
-+ tree incremented = TREE_OPERAND (exp, 0);
-+ optab this_optab = add_optab;
-+ int icode;
-+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
-+ int op0_is_copy = 0;
-+ int single_insn = 0;
-+ /* 1 means we can't store into OP0 directly,
-+ because it is a subreg narrower than a word,
-+ and we don't dare clobber the rest of the word. */
-+ int bad_subreg = 0;
-+
-+ /* Stabilize any component ref that might need to be
-+ evaluated more than once below. */
-+ if (!post
-+ || TREE_CODE (incremented) == BIT_FIELD_REF
-+ || (TREE_CODE (incremented) == COMPONENT_REF
-+ && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
-+ || DECL_BIT_FIELD (TREE_OPERAND (incremented, 1)))))
-+ incremented = stabilize_reference (incremented);
-+ /* Nested *INCREMENT_EXPRs can happen in C++. We must force innermost
-+ ones into save exprs so that they don't accidentally get evaluated
-+ more than once by the code below. */
-+ if (TREE_CODE (incremented) == PREINCREMENT_EXPR
-+ || TREE_CODE (incremented) == PREDECREMENT_EXPR)
-+ incremented = save_expr (incremented);
-+
-+ /* Compute the operands as RTX.
-+ Note whether OP0 is the actual lvalue or a copy of it:
-+ I believe it is a copy iff it is a register or subreg
-+ and insns were generated in computing it. */
-+
-+ temp = get_last_insn ();
-+ op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0);
-+
-+ /* If OP0 is a SUBREG made for a promoted variable, we cannot increment
-+ in place but instead must do sign- or zero-extension during assignment,
-+ so we copy it into a new register and let the code below use it as
-+ a copy.
-+
-+ Note that we can safely modify this SUBREG since it is know not to be
-+ shared (it was made by the expand_expr call above). */
-+
-+ if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0))
-+ {
-+ if (post)
-+ SUBREG_REG (op0) = copy_to_reg (SUBREG_REG (op0));
-+ else
-+ bad_subreg = 1;
-+ }
-+ else if (GET_CODE (op0) == SUBREG
-+ && GET_MODE_BITSIZE (GET_MODE (op0)) < BITS_PER_WORD)
-+ {
-+ /* We cannot increment this SUBREG in place. If we are
-+ post-incrementing, get a copy of the old value. Otherwise,
-+ just mark that we cannot increment in place. */
-+ if (post)
-+ op0 = copy_to_reg (op0);
-+ else
-+ bad_subreg = 1;
-+ }
-+
-+ op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
-+ && temp != get_last_insn ());
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+
-+ /* Decide whether incrementing or decrementing. */
-+ if (TREE_CODE (exp) == POSTDECREMENT_EXPR
-+ || TREE_CODE (exp) == PREDECREMENT_EXPR)
-+ this_optab = sub_optab;
-+
-+ /* Convert decrement by a constant into a negative increment. */
-+ if (this_optab == sub_optab
-+ && GET_CODE (op1) == CONST_INT)
-+ {
-+ op1 = GEN_INT (-INTVAL (op1));
-+ this_optab = add_optab;
-+ }
-+
-+ if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
-+ this_optab = this_optab == add_optab ? addv_optab : subv_optab;
-+
-+ /* For a preincrement, see if we can do this with a single instruction. */
-+ if (!post)
-+ {
-+ icode = (int) this_optab->handlers[(int) mode].insn_code;
-+ if (icode != (int) CODE_FOR_nothing
-+ /* Make sure that OP0 is valid for operands 0 and 1
-+ of the insn we want to queue. */
-+ && (*insn_data[icode].operand[0].predicate) (op0, mode)
-+ && (*insn_data[icode].operand[1].predicate) (op0, mode)
-+ && (*insn_data[icode].operand[2].predicate) (op1, mode))
-+ single_insn = 1;
-+ }
-+
-+ /* If OP0 is not the actual lvalue, but rather a copy in a register,
-+ then we cannot just increment OP0. We must therefore contrive to
-+ increment the original value. Then, for postincrement, we can return
-+ OP0 since it is a copy of the old value. For preincrement, expand here
-+ unless we can do it with a single insn.
-+
-+ Likewise if storing directly into OP0 would clobber high bits
-+ we need to preserve (bad_subreg). */
-+ if (op0_is_copy || (!post && !single_insn) || bad_subreg)
-+ {
-+ /* This is the easiest way to increment the value wherever it is.
-+ Problems with multiple evaluation of INCREMENTED are prevented
-+ because either (1) it is a component_ref or preincrement,
-+ in which case it was stabilized above, or (2) it is an array_ref
-+ with constant index in an array in a register, which is
-+ safe to reevaluate. */
-+ tree newexp = build (((TREE_CODE (exp) == POSTDECREMENT_EXPR
-+ || TREE_CODE (exp) == PREDECREMENT_EXPR)
-+ ? MINUS_EXPR : PLUS_EXPR),
-+ TREE_TYPE (exp),
-+ incremented,
-+ TREE_OPERAND (exp, 1));
-+
-+ while (TREE_CODE (incremented) == NOP_EXPR
-+ || TREE_CODE (incremented) == CONVERT_EXPR)
-+ {
-+ newexp = convert (TREE_TYPE (incremented), newexp);
-+ incremented = TREE_OPERAND (incremented, 0);
-+ }
-+
-+ temp = expand_assignment (incremented, newexp, ! post && ! ignore , 0);
-+ return post ? op0 : temp;
-+ }
-+
-+ if (post)
-+ {
-+ /* We have a true reference to the value in OP0.
-+ If there is an insn to add or subtract in this mode, queue it.
-+ Queueing the increment insn avoids the register shuffling
-+ that often results if we must increment now and first save
-+ the old value for subsequent use. */
-+
-+#if 0 /* Turned off to avoid making extra insn for indexed memref. */
-+ op0 = stabilize (op0);
-+#endif
-+
-+ icode = (int) this_optab->handlers[(int) mode].insn_code;
-+ if (icode != (int) CODE_FOR_nothing
-+ /* Make sure that OP0 is valid for operands 0 and 1
-+ of the insn we want to queue. */
-+ && (*insn_data[icode].operand[0].predicate) (op0, mode)
-+ && (*insn_data[icode].operand[1].predicate) (op0, mode))
-+ {
-+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
-+ op1 = force_reg (mode, op1);
-+
-+ return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
-+ }
-+ if (icode != (int) CODE_FOR_nothing && GET_CODE (op0) == MEM)
-+ {
-+ rtx addr = (general_operand (XEXP (op0, 0), mode)
-+ ? force_reg (Pmode, XEXP (op0, 0))
-+ : copy_to_reg (XEXP (op0, 0)));
-+ rtx temp, result;
-+
-+ op0 = replace_equiv_address (op0, addr);
-+ temp = force_reg (GET_MODE (op0), op0);
-+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode))
-+ op1 = force_reg (mode, op1);
-+
-+ /* The increment queue is LIFO, thus we have to `queue'
-+ the instructions in reverse order. */
-+ enqueue_insn (op0, gen_move_insn (op0, temp));
-+ result = enqueue_insn (temp, GEN_FCN (icode) (temp, temp, op1));
-+ return result;
-+ }
-+ }
-+
-+ /* Preincrement, or we can't increment with one simple insn. */
-+ if (post)
-+ /* Save a copy of the value before inc or dec, to return it later. */
-+ temp = value = copy_to_reg (op0);
-+ else
-+ /* Arrange to return the incremented value. */
-+ /* Copy the rtx because expand_binop will protect from the queue,
-+ and the results of that would be invalid for us to return
-+ if our caller does emit_queue before using our result. */
-+ temp = copy_rtx (value = op0);
-+
-+ /* Increment however we can. */
-+ op1 = expand_binop (mode, this_optab, value, op1, op0,
-+ TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
-+
-+ /* Make sure the value is stored into OP0. */
-+ if (op1 != op0)
-+ emit_move_insn (op0, op1);
-+
-+ return temp;
-+}
-+\f
-+/* At the start of a function, record that we have no previously-pushed
-+ arguments waiting to be popped. */
-+
-+void
-+init_pending_stack_adjust ()
-+{
-+ pending_stack_adjust = 0;
-+}
-+
-+/* When exiting from function, if safe, clear out any pending stack adjust
-+ so the adjustment won't get done.
-+
-+ Note, if the current function calls alloca, then it must have a
-+ frame pointer regardless of the value of flag_omit_frame_pointer. */
-+
-+void
-+clear_pending_stack_adjust ()
-+{
-+#ifdef EXIT_IGNORE_STACK
-+ if (optimize > 0
-+ && (! flag_omit_frame_pointer || current_function_calls_alloca)
-+ && EXIT_IGNORE_STACK
-+ && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
-+ && ! flag_inline_functions)
-+ {
-+ stack_pointer_delta -= pending_stack_adjust,
-+ pending_stack_adjust = 0;
-+ }
-+#endif
-+}
-+
-+/* Pop any previously-pushed arguments that have not been popped yet. */
-+
-+void
-+do_pending_stack_adjust ()
-+{
-+ if (inhibit_defer_pop == 0)
-+ {
-+ if (pending_stack_adjust != 0)
-+ adjust_stack (GEN_INT (pending_stack_adjust));
-+ pending_stack_adjust = 0;
-+ }
-+}
-+\f
-+/* Expand conditional expressions. */
-+
-+/* Generate code to evaluate EXP and jump to LABEL if the value is zero.
-+ LABEL is an rtx of code CODE_LABEL, in this function and all the
-+ functions here. */
-+
-+void
-+jumpifnot (exp, label)
-+ tree exp;
-+ rtx label;
-+{
-+ do_jump (exp, label, NULL_RTX);
-+}
-+
-+/* Generate code to evaluate EXP and jump to LABEL if the value is nonzero. */
-+
-+void
-+jumpif (exp, label)
-+ tree exp;
-+ rtx label;
-+{
-+ do_jump (exp, NULL_RTX, label);
-+}
-+
-+/* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
-+ the result is zero, or IF_TRUE_LABEL if the result is one.
-+ Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
-+ meaning fall through in that case.
-+
-+ do_jump always does any pending stack adjust except when it does not
-+ actually perform a jump. An example where there is no jump
-+ is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.
-+
-+ This function is responsible for optimizing cases such as
-+ &&, || and comparison operators in EXP. */
-+
-+void
-+do_jump (exp, if_false_label, if_true_label)
-+ tree exp;
-+ rtx if_false_label, if_true_label;
-+{
-+ enum tree_code code = TREE_CODE (exp);
-+ /* Some cases need to create a label to jump to
-+ in order to properly fall through.
-+ These cases set DROP_THROUGH_LABEL nonzero. */
-+ rtx drop_through_label = 0;
-+ rtx temp;
-+ int i;
-+ tree type;
-+ enum machine_mode mode;
-+
-+#ifdef MAX_INTEGER_COMPUTATION_MODE
-+ check_max_integer_computation_mode (exp);
-+#endif
-+
-+ emit_queue ();
-+
-+ switch (code)
-+ {
-+ case ERROR_MARK:
-+ break;
-+
-+ case INTEGER_CST:
-+ temp = integer_zerop (exp) ? if_false_label : if_true_label;
-+ if (temp)
-+ emit_jump (temp);
-+ break;
-+
-+#if 0
-+ /* This is not true with #pragma weak */
-+ case ADDR_EXPR:
-+ /* The address of something can never be zero. */
-+ if (if_true_label)
-+ emit_jump (if_true_label);
-+ break;
-+#endif
-+
-+ case UNSAVE_EXPR:
-+ do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
-+ TREE_OPERAND (exp, 0)
-+ = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
-+ break;
-+
-+ case NOP_EXPR:
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
-+ || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
-+ || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
-+ || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
-+ goto normal;
-+ case CONVERT_EXPR:
-+ /* If we are narrowing the operand, we have to do the compare in the
-+ narrower mode. */
-+ if ((TYPE_PRECISION (TREE_TYPE (exp))
-+ < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
-+ goto normal;
-+ case NON_LVALUE_EXPR:
-+ case REFERENCE_EXPR:
-+ case ABS_EXPR:
-+ case NEGATE_EXPR:
-+ case LROTATE_EXPR:
-+ case RROTATE_EXPR:
-+ /* These cannot change zero->nonzero or vice versa. */
-+ do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
-+ break;
-+
-+ case WITH_RECORD_EXPR:
-+ /* Put the object on the placeholder list, recurse through our first
-+ operand, and pop the list. */
-+ placeholder_list = tree_cons (TREE_OPERAND (exp, 1), NULL_TREE,
-+ placeholder_list);
-+ do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
-+ placeholder_list = TREE_CHAIN (placeholder_list);
-+ break;
-+
-+#if 0
-+ /* This is never less insns than evaluating the PLUS_EXPR followed by
-+ a test and can be longer if the test is eliminated. */
-+ case PLUS_EXPR:
-+ /* Reduce to minus. */
-+ exp = build (MINUS_EXPR, TREE_TYPE (exp),
-+ TREE_OPERAND (exp, 0),
-+ fold (build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
-+ TREE_OPERAND (exp, 1))));
-+ /* Process as MINUS. */
-+#endif
-+
-+ case MINUS_EXPR:
-+ /* Nonzero iff operands of minus differ. */
-+ do_compare_and_jump (build (NE_EXPR, TREE_TYPE (exp),
-+ TREE_OPERAND (exp, 0),
-+ TREE_OPERAND (exp, 1)),
-+ NE, NE, if_false_label, if_true_label);
-+ break;
-+
-+ case BIT_AND_EXPR:
-+ /* If we are AND'ing with a small constant, do this comparison in the
-+ smallest type that fits. If the machine doesn't have comparisons
-+ that small, it will be converted back to the wider comparison.
-+ This helps if we are testing the sign bit of a narrower object.
-+ combine can't do this for us because it can't know whether a
-+ ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */
-+
-+ if (! SLOW_BYTE_ACCESS
-+ && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
-+ && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
-+ && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
-+ && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
-+ && (type = (*lang_hooks.types.type_for_mode) (mode, 1)) != 0
-+ && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
-+ && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
-+ != CODE_FOR_nothing))
-+ {
-+ do_jump (convert (type, exp), if_false_label, if_true_label);
-+ break;
-+ }
-+ goto normal;
-+
-+ case TRUTH_NOT_EXPR:
-+ do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
-+ break;
-+
-+ case TRUTH_ANDIF_EXPR:
-+ if (if_false_label == 0)
-+ if_false_label = drop_through_label = gen_label_rtx ();
-+ do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
-+ start_cleanup_deferral ();
-+ do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
-+ end_cleanup_deferral ();
-+ break;
-+
-+ case TRUTH_ORIF_EXPR:
-+ if (if_true_label == 0)
-+ if_true_label = drop_through_label = gen_label_rtx ();
-+ do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
-+ start_cleanup_deferral ();
-+ do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
-+ end_cleanup_deferral ();
-+ break;
-+
-+ case COMPOUND_EXPR:
-+ push_temp_slots ();
-+ expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
-+ preserve_temp_slots (NULL_RTX);
-+ free_temp_slots ();
-+ pop_temp_slots ();
-+ emit_queue ();
-+ do_pending_stack_adjust ();
-+ do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
-+ break;
-+
-+ case COMPONENT_REF:
-+ case BIT_FIELD_REF:
-+ case ARRAY_REF:
-+ case ARRAY_RANGE_REF:
-+ {
-+ HOST_WIDE_INT bitsize, bitpos;
-+ int unsignedp;
-+ enum machine_mode mode;
-+ tree type;
-+ tree offset;
-+ int volatilep = 0;
-+
-+ /* Get description of this reference. We don't actually care
-+ about the underlying object here. */
-+ get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
-+ &unsignedp, &volatilep);
-+
-+ type = (*lang_hooks.types.type_for_size) (bitsize, unsignedp);
-+ if (! SLOW_BYTE_ACCESS
-+ && type != 0 && bitsize >= 0
-+ && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
-+ && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
-+ != CODE_FOR_nothing))
-+ {
-+ do_jump (convert (type, exp), if_false_label, if_true_label);
-+ break;
-+ }
-+ goto normal;
-+ }
-+
-+ case COND_EXPR:
-+ /* Do (a ? 1 : 0) and (a ? 0 : 1) as special cases. */
-+ if (integer_onep (TREE_OPERAND (exp, 1))
-+ && integer_zerop (TREE_OPERAND (exp, 2)))
-+ do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
-+
-+ else if (integer_zerop (TREE_OPERAND (exp, 1))
-+ && integer_onep (TREE_OPERAND (exp, 2)))
-+ do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
-+
-+ else
-+ {
-+ rtx label1 = gen_label_rtx ();
-+ drop_through_label = gen_label_rtx ();
-+
-+ do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
-+
-+ start_cleanup_deferral ();
-+ /* Now the THEN-expression. */
-+ do_jump (TREE_OPERAND (exp, 1),
-+ if_false_label ? if_false_label : drop_through_label,
-+ if_true_label ? if_true_label : drop_through_label);
-+ /* In case the do_jump just above never jumps. */
-+ do_pending_stack_adjust ();
-+ emit_label (label1);
-+
-+ /* Now the ELSE-expression. */
-+ do_jump (TREE_OPERAND (exp, 2),
-+ if_false_label ? if_false_label : drop_through_label,
-+ if_true_label ? if_true_label : drop_through_label);
-+ end_cleanup_deferral ();
-+ }
-+ break;
-+
-+ case EQ_EXPR:
-+ {
-+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-+
-+ if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
-+ || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
-+ {
-+ tree exp0 = save_expr (TREE_OPERAND (exp, 0));
-+ tree exp1 = save_expr (TREE_OPERAND (exp, 1));
-+ do_jump
-+ (fold
-+ (build (TRUTH_ANDIF_EXPR, TREE_TYPE (exp),
-+ fold (build (EQ_EXPR, TREE_TYPE (exp),
-+ fold (build1 (REALPART_EXPR,
-+ TREE_TYPE (inner_type),
-+ exp0)),
-+ fold (build1 (REALPART_EXPR,
-+ TREE_TYPE (inner_type),
-+ exp1)))),
-+ fold (build (EQ_EXPR, TREE_TYPE (exp),
-+ fold (build1 (IMAGPART_EXPR,
-+ TREE_TYPE (inner_type),
-+ exp0)),
-+ fold (build1 (IMAGPART_EXPR,
-+ TREE_TYPE (inner_type),
-+ exp1)))))),
-+ if_false_label, if_true_label);
-+ }
-+
-+ else if (integer_zerop (TREE_OPERAND (exp, 1)))
-+ do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
-+
-+ else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
-+ && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
-+ do_jump_by_parts_equality (exp, if_false_label, if_true_label);
-+ else
-+ do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label);
-+ break;
-+ }
-+
-+ case NE_EXPR:
-+ {
-+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-+
-+ if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
-+ || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
-+ {
-+ tree exp0 = save_expr (TREE_OPERAND (exp, 0));
-+ tree exp1 = save_expr (TREE_OPERAND (exp, 1));
-+ do_jump
-+ (fold
-+ (build (TRUTH_ORIF_EXPR, TREE_TYPE (exp),
-+ fold (build (NE_EXPR, TREE_TYPE (exp),
-+ fold (build1 (REALPART_EXPR,
-+ TREE_TYPE (inner_type),
-+ exp0)),
-+ fold (build1 (REALPART_EXPR,
-+ TREE_TYPE (inner_type),
-+ exp1)))),
-+ fold (build (NE_EXPR, TREE_TYPE (exp),
-+ fold (build1 (IMAGPART_EXPR,
-+ TREE_TYPE (inner_type),
-+ exp0)),
-+ fold (build1 (IMAGPART_EXPR,
-+ TREE_TYPE (inner_type),
-+ exp1)))))),
-+ if_false_label, if_true_label);
-+ }
-+
-+ else if (integer_zerop (TREE_OPERAND (exp, 1)))
-+ do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
-+
-+ else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
-+ && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
-+ do_jump_by_parts_equality (exp, if_true_label, if_false_label);
-+ else
-+ do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label);
-+ break;
-+ }
-+
-+ case LT_EXPR:
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && ! can_compare_p (LT, mode, ccp_jump))
-+ do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
-+ else
-+ do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label);
-+ break;
-+
-+ case LE_EXPR:
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && ! can_compare_p (LE, mode, ccp_jump))
-+ do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
-+ else
-+ do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label);
-+ break;
-+
-+ case GT_EXPR:
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && ! can_compare_p (GT, mode, ccp_jump))
-+ do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
-+ else
-+ do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label);
-+ break;
-+
-+ case GE_EXPR:
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && ! can_compare_p (GE, mode, ccp_jump))
-+ do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
-+ else
-+ do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label);
-+ break;
-+
-+ case UNORDERED_EXPR:
-+ case ORDERED_EXPR:
-+ {
-+ enum rtx_code cmp, rcmp;
-+ int do_rev;
-+
-+ if (code == UNORDERED_EXPR)
-+ cmp = UNORDERED, rcmp = ORDERED;
-+ else
-+ cmp = ORDERED, rcmp = UNORDERED;
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+
-+ do_rev = 0;
-+ if (! can_compare_p (cmp, mode, ccp_jump)
-+ && (can_compare_p (rcmp, mode, ccp_jump)
-+ /* If the target doesn't provide either UNORDERED or ORDERED
-+ comparisons, canonicalize on UNORDERED for the library. */
-+ || rcmp == UNORDERED))
-+ do_rev = 1;
-+
-+ if (! do_rev)
-+ do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label);
-+ else
-+ do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label);
-+ }
-+ break;
-+
-+ {
-+ enum rtx_code rcode1;
-+ enum tree_code tcode2;
-+
-+ case UNLT_EXPR:
-+ rcode1 = UNLT;
-+ tcode2 = LT_EXPR;
-+ goto unordered_bcc;
-+ case UNLE_EXPR:
-+ rcode1 = UNLE;
-+ tcode2 = LE_EXPR;
-+ goto unordered_bcc;
-+ case UNGT_EXPR:
-+ rcode1 = UNGT;
-+ tcode2 = GT_EXPR;
-+ goto unordered_bcc;
-+ case UNGE_EXPR:
-+ rcode1 = UNGE;
-+ tcode2 = GE_EXPR;
-+ goto unordered_bcc;
-+ case UNEQ_EXPR:
-+ rcode1 = UNEQ;
-+ tcode2 = EQ_EXPR;
-+ goto unordered_bcc;
-+
-+ unordered_bcc:
-+ mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ if (can_compare_p (rcode1, mode, ccp_jump))
-+ do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
-+ if_true_label);
-+ else
-+ {
-+ tree op0 = save_expr (TREE_OPERAND (exp, 0));
-+ tree op1 = save_expr (TREE_OPERAND (exp, 1));
-+ tree cmp0, cmp1;
-+
-+ /* If the target doesn't support combined unordered
-+ compares, decompose into UNORDERED + comparison. */
-+ cmp0 = fold (build (UNORDERED_EXPR, TREE_TYPE (exp), op0, op1));
-+ cmp1 = fold (build (tcode2, TREE_TYPE (exp), op0, op1));
-+ exp = build (TRUTH_ORIF_EXPR, TREE_TYPE (exp), cmp0, cmp1);
-+ do_jump (exp, if_false_label, if_true_label);
-+ }
-+ }
-+ break;
-+
-+ /* Special case:
-+ __builtin_expect (<test>, 0) and
-+ __builtin_expect (<test>, 1)
-+
-+ We need to do this here, so that <test> is not converted to a SCC
-+ operation on machines that use condition code registers and COMPARE
-+ like the PowerPC, and then the jump is done based on whether the SCC
-+ operation produced a 1 or 0. */
-+ case CALL_EXPR:
-+ /* Check for a built-in function. */
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
-+ {
-+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
-+ tree arglist = TREE_OPERAND (exp, 1);
-+
-+ if (TREE_CODE (fndecl) == FUNCTION_DECL
-+ && DECL_BUILT_IN (fndecl)
-+ && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
-+ && arglist != NULL_TREE
-+ && TREE_CHAIN (arglist) != NULL_TREE)
-+ {
-+ rtx seq = expand_builtin_expect_jump (exp, if_false_label,
-+ if_true_label);
-+
-+ if (seq != NULL_RTX)
-+ {
-+ emit_insn (seq);
-+ return;
-+ }
-+ }
-+ }
-+ /* fall through and generate the normal code. */
-+
-+ default:
-+ normal:
-+ temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
-+#if 0
-+ /* This is not needed any more and causes poor code since it causes
-+ comparisons and tests from non-SI objects to have different code
-+ sequences. */
-+ /* Copy to register to avoid generating bad insns by cse
-+ from (set (mem ...) (arithop)) (set (cc0) (mem ...)). */
-+ if (!cse_not_expected && GET_CODE (temp) == MEM)
-+ temp = copy_to_reg (temp);
-+#endif
-+ do_pending_stack_adjust ();
-+ /* Do any postincrements in the expression that was tested. */
-+ emit_queue ();
-+
-+ if (GET_CODE (temp) == CONST_INT
-+ || (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode)
-+ || GET_CODE (temp) == LABEL_REF)
-+ {
-+ rtx target = temp == const0_rtx ? if_false_label : if_true_label;
-+ if (target)
-+ emit_jump (target);
-+ }
-+ else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
-+ && ! can_compare_p (NE, GET_MODE (temp), ccp_jump))
-+ /* Note swapping the labels gives us not-equal. */
-+ do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
-+ else if (GET_MODE (temp) != VOIDmode)
-+ do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
-+ NE, TREE_UNSIGNED (TREE_TYPE (exp)),
-+ GET_MODE (temp), NULL_RTX,
-+ if_false_label, if_true_label);
-+ else
-+ abort ();
-+ }
-+
-+ if (drop_through_label)
-+ {
-+ /* If do_jump produces code that might be jumped around,
-+ do any stack adjusts from that code, before the place
-+ where control merges in. */
-+ do_pending_stack_adjust ();
-+ emit_label (drop_through_label);
-+ }
-+}
-+\f
-+/* Given a comparison expression EXP for values too wide to be compared
-+ with one insn, test the comparison and jump to the appropriate label.
-+ The code of EXP is ignored; we always test GT if SWAP is 0,
-+ and LT if SWAP is 1. */
-+
-+static void
-+do_jump_by_parts_greater (exp, swap, if_false_label, if_true_label)
-+ tree exp;
-+ int swap;
-+ rtx if_false_label, if_true_label;
-+{
-+ rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0);
-+ rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0);
-+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+
-+ do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, if_true_label);
-+}
-+
-+/* Compare OP0 with OP1, word at a time, in mode MODE.
-+ UNSIGNEDP says to do unsigned comparison.
-+ Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise. */
-+
-+void
-+do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label, if_true_label)
-+ enum machine_mode mode;
-+ int unsignedp;
-+ rtx op0, op1;
-+ rtx if_false_label, if_true_label;
-+{
-+ int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
-+ rtx drop_through_label = 0;
-+ int i;
-+
-+ if (! if_true_label || ! if_false_label)
-+ drop_through_label = gen_label_rtx ();
-+ if (! if_true_label)
-+ if_true_label = drop_through_label;
-+ if (! if_false_label)
-+ if_false_label = drop_through_label;
-+
-+ /* Compare a word at a time, high order first. */
-+ for (i = 0; i < nwords; i++)
-+ {
-+ rtx op0_word, op1_word;
-+
-+ if (WORDS_BIG_ENDIAN)
-+ {
-+ op0_word = operand_subword_force (op0, i, mode);
-+ op1_word = operand_subword_force (op1, i, mode);
-+ }
-+ else
-+ {
-+ op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
-+ op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
-+ }
-+
-+ /* All but high-order word must be compared as unsigned. */
-+ do_compare_rtx_and_jump (op0_word, op1_word, GT,
-+ (unsignedp || i > 0), word_mode, NULL_RTX,
-+ NULL_RTX, if_true_label);
-+
-+ /* Consider lower words only if these are equal. */
-+ do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
-+ NULL_RTX, NULL_RTX, if_false_label);
-+ }
-+
-+ if (if_false_label)
-+ emit_jump (if_false_label);
-+ if (drop_through_label)
-+ emit_label (drop_through_label);
-+}
-+
-+/* Given an EQ_EXPR expression EXP for values too wide to be compared
-+ with one insn, test the comparison and jump to the appropriate label. */
-+
-+static void
-+do_jump_by_parts_equality (exp, if_false_label, if_true_label)
-+ tree exp;
-+ rtx if_false_label, if_true_label;
-+{
-+ rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
-+ rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-+ int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
-+ int i;
-+ rtx drop_through_label = 0;
-+
-+ if (! if_false_label)
-+ drop_through_label = if_false_label = gen_label_rtx ();
-+
-+ for (i = 0; i < nwords; i++)
-+ do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
-+ operand_subword_force (op1, i, mode),
-+ EQ, TREE_UNSIGNED (TREE_TYPE (exp)),
-+ word_mode, NULL_RTX, if_false_label, NULL_RTX);
-+
-+ if (if_true_label)
-+ emit_jump (if_true_label);
-+ if (drop_through_label)
-+ emit_label (drop_through_label);
-+}
-+\f
-+/* Jump according to whether OP0 is 0.
-+ We assume that OP0 has an integer mode that is too wide
-+ for the available compare insns. */
-+
-+void
-+do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
-+ rtx op0;
-+ rtx if_false_label, if_true_label;
-+{
-+ int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD;
-+ rtx part;
-+ int i;
-+ rtx drop_through_label = 0;
-+
-+ /* The fastest way of doing this comparison on almost any machine is to
-+ "or" all the words and compare the result. If all have to be loaded
-+ from memory and this is a very wide item, it's possible this may
-+ be slower, but that's highly unlikely. */
-+
-+ part = gen_reg_rtx (word_mode);
-+ emit_move_insn (part, operand_subword_force (op0, 0, GET_MODE (op0)));
-+ for (i = 1; i < nwords && part != 0; i++)
-+ part = expand_binop (word_mode, ior_optab, part,
-+ operand_subword_force (op0, i, GET_MODE (op0)),
-+ part, 1, OPTAB_WIDEN);
-+
-+ if (part != 0)
-+ {
-+ do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
-+ NULL_RTX, if_false_label, if_true_label);
-+
-+ return;
-+ }
-+
-+ /* If we couldn't do the "or" simply, do this with a series of compares. */
-+ if (! if_false_label)
-+ drop_through_label = if_false_label = gen_label_rtx ();
-+
-+ for (i = 0; i < nwords; i++)
-+ do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)),
-+ const0_rtx, EQ, 1, word_mode, NULL_RTX,
-+ if_false_label, NULL_RTX);
-+
-+ if (if_true_label)
-+ emit_jump (if_true_label);
-+
-+ if (drop_through_label)
-+ emit_label (drop_through_label);
-+}
-+\f
-+/* Generate code for a comparison of OP0 and OP1 with rtx code CODE.
-+ (including code to compute the values to be compared)
-+ and set (CC0) according to the result.
-+ The decision as to signed or unsigned comparison must be made by the caller.
-+
-+ We force a stack adjustment unless there are currently
-+ things pushed on the stack that aren't yet used.
-+
-+ If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
-+ compared. */
-+
-+rtx
-+compare_from_rtx (op0, op1, code, unsignedp, mode, size)
-+ rtx op0, op1;
-+ enum rtx_code code;
-+ int unsignedp;
-+ enum machine_mode mode;
-+ rtx size;
-+{
-+ enum rtx_code ucode;
-+ rtx tem;
-+
-+ /* If one operand is constant, make it the second one. Only do this
-+ if the other operand is not constant as well. */
-+
-+ if (swap_commutative_operands_p (op0, op1))
-+ {
-+ tem = op0;
-+ op0 = op1;
-+ op1 = tem;
-+ code = swap_condition (code);
-+ }
-+
-+ if (flag_force_mem)
-+ {
-+ op0 = force_not_mem (op0);
-+ op1 = force_not_mem (op1);
-+ }
-+
-+ do_pending_stack_adjust ();
-+
-+ ucode = unsignedp ? unsigned_condition (code) : code;
-+ if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
-+ return tem;
-+
-+#if 0
-+ /* There's no need to do this now that combine.c can eliminate lots of
-+ sign extensions. This can be less efficient in certain cases on other
-+ machines. */
-+
-+ /* If this is a signed equality comparison, we can do it as an
-+ unsigned comparison since zero-extension is cheaper than sign
-+ extension and comparisons with zero are done as unsigned. This is
-+ the case even on machines that can do fast sign extension, since
-+ zero-extension is easier to combine with other operations than
-+ sign-extension is. If we are comparing against a constant, we must
-+ convert it to what it would look like unsigned. */
-+ if ((code == EQ || code == NE) && ! unsignedp
-+ && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
-+ {
-+ if (GET_CODE (op1) == CONST_INT
-+ && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
-+ op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
-+ unsignedp = 1;
-+ }
-+#endif
-+
-+ emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
-+
-+#if HAVE_cc0
-+ return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
-+#else
-+ return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
-+#endif
-+}
-+
-+/* Like do_compare_and_jump but expects the values to compare as two rtx's.
-+ The decision as to signed or unsigned comparison must be made by the caller.
-+
-+ If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
-+ compared. */
-+
-+void
-+do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode, size,
-+ if_false_label, if_true_label)
-+ rtx op0, op1;
-+ enum rtx_code code;
-+ int unsignedp;
-+ enum machine_mode mode;
-+ rtx size;
-+ rtx if_false_label, if_true_label;
-+{
-+ enum rtx_code ucode;
-+ rtx tem;
-+ int dummy_true_label = 0;
-+
-+ /* Reverse the comparison if that is safe and we want to jump if it is
-+ false. */
-+ if (! if_true_label && ! FLOAT_MODE_P (mode))
-+ {
-+ if_true_label = if_false_label;
-+ if_false_label = 0;
-+ code = reverse_condition (code);
-+ }
-+
-+ /* If one operand is constant, make it the second one. Only do this
-+ if the other operand is not constant as well. */
-+
-+ if (swap_commutative_operands_p (op0, op1))
-+ {
-+ tem = op0;
-+ op0 = op1;
-+ op1 = tem;
-+ code = swap_condition (code);
-+ }
-+
-+ if (flag_force_mem)
-+ {
-+ op0 = force_not_mem (op0);
-+ op1 = force_not_mem (op1);
-+ }
-+
-+ do_pending_stack_adjust ();
-+
-+ ucode = unsignedp ? unsigned_condition (code) : code;
-+ if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0)
-+ {
-+ if (tem == const_true_rtx)
-+ {
-+ if (if_true_label)
-+ emit_jump (if_true_label);
-+ }
-+ else
-+ {
-+ if (if_false_label)
-+ emit_jump (if_false_label);
-+ }
-+ return;
-+ }
-+
-+#if 0
-+ /* There's no need to do this now that combine.c can eliminate lots of
-+ sign extensions. This can be less efficient in certain cases on other
-+ machines. */
-+
-+ /* If this is a signed equality comparison, we can do it as an
-+ unsigned comparison since zero-extension is cheaper than sign
-+ extension and comparisons with zero are done as unsigned. This is
-+ the case even on machines that can do fast sign extension, since
-+ zero-extension is easier to combine with other operations than
-+ sign-extension is. If we are comparing against a constant, we must
-+ convert it to what it would look like unsigned. */
-+ if ((code == EQ || code == NE) && ! unsignedp
-+ && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
-+ {
-+ if (GET_CODE (op1) == CONST_INT
-+ && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
-+ op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
-+ unsignedp = 1;
-+ }
-+#endif
-+
-+ if (! if_true_label)
-+ {
-+ dummy_true_label = 1;
-+ if_true_label = gen_label_rtx ();
-+ }
-+
-+ emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
-+ if_true_label);
-+
-+ if (if_false_label)
-+ emit_jump (if_false_label);
-+ if (dummy_true_label)
-+ emit_label (if_true_label);
-+}
-+
-+/* Generate code for a comparison expression EXP (including code to compute
-+ the values to be compared) and a conditional jump to IF_FALSE_LABEL and/or
-+ IF_TRUE_LABEL. One of the labels can be NULL_RTX, in which case the
-+ generated code will drop through.
-+ SIGNED_CODE should be the rtx operation for this comparison for
-+ signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
-+
-+ We force a stack adjustment unless there are currently
-+ things pushed on the stack that aren't yet used. */
-+
-+static void
-+do_compare_and_jump (exp, signed_code, unsigned_code, if_false_label,
-+ if_true_label)
-+ tree exp;
-+ enum rtx_code signed_code, unsigned_code;
-+ rtx if_false_label, if_true_label;
-+{
-+ rtx op0, op1;
-+ tree type;
-+ enum machine_mode mode;
-+ int unsignedp;
-+ enum rtx_code code;
-+
-+ /* Don't crash if the comparison was erroneous. */
-+ op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
-+ return;
-+
-+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
-+ if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
-+ return;
-+
-+ type = TREE_TYPE (TREE_OPERAND (exp, 0));
-+ mode = TYPE_MODE (type);
-+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
-+ && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
-+ || (GET_MODE_BITSIZE (mode)
-+ > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
-+ 1)))))))
-+ {
-+ /* op0 might have been replaced by promoted constant, in which
-+ case the type of second argument should be used. */
-+ type = TREE_TYPE (TREE_OPERAND (exp, 1));
-+ mode = TYPE_MODE (type);
-+ }
-+ unsignedp = TREE_UNSIGNED (type);
-+ code = unsignedp ? unsigned_code : signed_code;
-+
-+#ifdef HAVE_canonicalize_funcptr_for_compare
-+ /* If function pointers need to be "canonicalized" before they can
-+ be reliably compared, then canonicalize them. */
-+ if (HAVE_canonicalize_funcptr_for_compare
-+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
-+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
-+ == FUNCTION_TYPE))
-+ {
-+ rtx new_op0 = gen_reg_rtx (mode);
-+
-+ emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
-+ op0 = new_op0;
-+ }
-+
-+ if (HAVE_canonicalize_funcptr_for_compare
-+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
-+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
-+ == FUNCTION_TYPE))
-+ {
-+ rtx new_op1 = gen_reg_rtx (mode);
-+
-+ emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
-+ op1 = new_op1;
-+ }
-+#endif
-+
-+ /* Do any postincrements in the expression that was tested. */
-+ emit_queue ();
-+
-+ do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
-+ ((mode == BLKmode)
-+ ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
-+ if_false_label, if_true_label);
-+}
-+\f
-+/* Generate code to calculate EXP using a store-flag instruction
-+ and return an rtx for the result. EXP is either a comparison
-+ or a TRUTH_NOT_EXPR whose operand is a comparison.
-+
-+ If TARGET is nonzero, store the result there if convenient.
-+
-+ If ONLY_CHEAP is nonzero, only do this if it is likely to be very
-+ cheap.
-+
-+ Return zero if there is no suitable set-flag instruction
-+ available on this machine.
-+
-+ Once expand_expr has been called on the arguments of the comparison,
-+ we are committed to doing the store flag, since it is not safe to
-+ re-evaluate the expression. We emit the store-flag insn by calling
-+ emit_store_flag, but only expand the arguments if we have a reason
-+ to believe that emit_store_flag will be successful. If we think that
-+ it will, but it isn't, we have to simulate the store-flag with a
-+ set/jump/set sequence. */
-+
-+static rtx
-+do_store_flag (exp, target, mode, only_cheap)
-+ tree exp;
-+ rtx target;
-+ enum machine_mode mode;
-+ int only_cheap;
-+{
-+ enum rtx_code code;
-+ tree arg0, arg1, type;
-+ tree tem;
-+ enum machine_mode operand_mode;
-+ int invert = 0;
-+ int unsignedp;
-+ rtx op0, op1;
-+ enum insn_code icode;
-+ rtx subtarget = target;
-+ rtx result, label;
-+
-+ /* If this is a TRUTH_NOT_EXPR, set a flag indicating we must invert the
-+ result at the end. We can't simply invert the test since it would
-+ have already been inverted if it were valid. This case occurs for
-+ some floating-point comparisons. */
-+
-+ if (TREE_CODE (exp) == TRUTH_NOT_EXPR)
-+ invert = 1, exp = TREE_OPERAND (exp, 0);
-+
-+ arg0 = TREE_OPERAND (exp, 0);
-+ arg1 = TREE_OPERAND (exp, 1);
-+
-+ /* Don't crash if the comparison was erroneous. */
-+ if (arg0 == error_mark_node || arg1 == error_mark_node)
-+ return const0_rtx;
-+
-+ type = TREE_TYPE (arg0);
-+ operand_mode = TYPE_MODE (type);
-+ unsignedp = TREE_UNSIGNED (type);
-+
-+ /* We won't bother with BLKmode store-flag operations because it would mean
-+ passing a lot of information to emit_store_flag. */
-+ if (operand_mode == BLKmode)
-+ return 0;
-+
-+ /* We won't bother with store-flag operations involving function pointers
-+ when function pointers must be canonicalized before comparisons. */
-+#ifdef HAVE_canonicalize_funcptr_for_compare
-+ if (HAVE_canonicalize_funcptr_for_compare
-+ && ((TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
-+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
-+ == FUNCTION_TYPE))
-+ || (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
-+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
-+ == FUNCTION_TYPE))))
-+ return 0;
-+#endif
-+
-+ STRIP_NOPS (arg0);
-+ STRIP_NOPS (arg1);
-+
-+ /* Get the rtx comparison code to use. We know that EXP is a comparison
-+ operation of some type. Some comparisons against 1 and -1 can be
-+ converted to comparisons with zero. Do so here so that the tests
-+ below will be aware that we have a comparison with zero. These
-+ tests will not catch constants in the first operand, but constants
-+ are rarely passed as the first operand. */
-+
-+ switch (TREE_CODE (exp))
-+ {
-+ case EQ_EXPR:
-+ code = EQ;
-+ break;
-+ case NE_EXPR:
-+ code = NE;
-+ break;
-+ case LT_EXPR:
-+ if (integer_onep (arg1))
-+ arg1 = integer_zero_node, code = unsignedp ? LEU : LE;
-+ else
-+ code = unsignedp ? LTU : LT;
-+ break;
-+ case LE_EXPR:
-+ if (! unsignedp && integer_all_onesp (arg1))
-+ arg1 = integer_zero_node, code = LT;
-+ else
-+ code = unsignedp ? LEU : LE;
-+ break;
-+ case GT_EXPR:
-+ if (! unsignedp && integer_all_onesp (arg1))
-+ arg1 = integer_zero_node, code = GE;
-+ else
-+ code = unsignedp ? GTU : GT;
-+ break;
-+ case GE_EXPR:
-+ if (integer_onep (arg1))
-+ arg1 = integer_zero_node, code = unsignedp ? GTU : GT;
-+ else
-+ code = unsignedp ? GEU : GE;
-+ break;
-+
-+ case UNORDERED_EXPR:
-+ code = UNORDERED;
-+ break;
-+ case ORDERED_EXPR:
-+ code = ORDERED;
-+ break;
-+ case UNLT_EXPR:
-+ code = UNLT;
-+ break;
-+ case UNLE_EXPR:
-+ code = UNLE;
-+ break;
-+ case UNGT_EXPR:
-+ code = UNGT;
-+ break;
-+ case UNGE_EXPR:
-+ code = UNGE;
-+ break;
-+ case UNEQ_EXPR:
-+ code = UNEQ;
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+
-+ /* Put a constant second. */
-+ if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST)
-+ {
-+ tem = arg0; arg0 = arg1; arg1 = tem;
-+ code = swap_condition (code);
-+ }
-+
-+ /* If this is an equality or inequality test of a single bit, we can
-+ do this by shifting the bit being tested to the low-order bit and
-+ masking the result with the constant 1. If the condition was EQ,
-+ we xor it with 1. This does not require an scc insn and is faster
-+ than an scc insn even if we have it. */
-+
-+ if ((code == NE || code == EQ)
-+ && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
-+ && integer_pow2p (TREE_OPERAND (arg0, 1)))
-+ {
-+ tree inner = TREE_OPERAND (arg0, 0);
-+ int bitnum = tree_log2 (TREE_OPERAND (arg0, 1));
-+ int ops_unsignedp;
-+
-+ /* If INNER is a right shift of a constant and it plus BITNUM does
-+ not overflow, adjust BITNUM and INNER. */
-+
-+ if (TREE_CODE (inner) == RSHIFT_EXPR
-+ && TREE_CODE (TREE_OPERAND (inner, 1)) == INTEGER_CST
-+ && TREE_INT_CST_HIGH (TREE_OPERAND (inner, 1)) == 0
-+ && bitnum < TYPE_PRECISION (type)
-+ && 0 > compare_tree_int (TREE_OPERAND (inner, 1),
-+ bitnum - TYPE_PRECISION (type)))
-+ {
-+ bitnum += TREE_INT_CST_LOW (TREE_OPERAND (inner, 1));
-+ inner = TREE_OPERAND (inner, 0);
-+ }
-+
-+ /* If we are going to be able to omit the AND below, we must do our
-+ operations as unsigned. If we must use the AND, we have a choice.
-+ Normally unsigned is faster, but for some machines signed is. */
-+ ops_unsignedp = (bitnum == TYPE_PRECISION (type) - 1 ? 1
-+#ifdef LOAD_EXTEND_OP
-+ : (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1)
-+#else
-+ : 1
-+#endif
-+ );
-+
-+ if (! get_subtarget (subtarget)
-+ || GET_MODE (subtarget) != operand_mode
-+ || ! safe_from_p (subtarget, inner, 1))
-+ subtarget = 0;
-+
-+ op0 = expand_expr (inner, subtarget, VOIDmode, 0);
-+
-+ if (bitnum != 0)
-+ op0 = expand_shift (RSHIFT_EXPR, operand_mode, op0,
-+ size_int (bitnum), subtarget, ops_unsignedp);
-+
-+ if (GET_MODE (op0) != mode)
-+ op0 = convert_to_mode (mode, op0, ops_unsignedp);
-+
-+ if ((code == EQ && ! invert) || (code == NE && invert))
-+ op0 = expand_binop (mode, xor_optab, op0, const1_rtx, subtarget,
-+ ops_unsignedp, OPTAB_LIB_WIDEN);
-+
-+ /* Put the AND last so it can combine with more things. */
-+ if (bitnum != TYPE_PRECISION (type) - 1)
-+ op0 = expand_and (mode, op0, const1_rtx, subtarget);
-+
-+ return op0;
-+ }
-+
-+ /* Now see if we are likely to be able to do this. Return if not. */
-+ if (! can_compare_p (code, operand_mode, ccp_store_flag))
-+ return 0;
-+
-+ icode = setcc_gen_code[(int) code];
-+ if (icode == CODE_FOR_nothing
-+ || (only_cheap && insn_data[(int) icode].operand[0].mode != mode))
-+ {
-+ /* We can only do this if it is one of the special cases that
-+ can be handled without an scc insn. */
-+ if ((code == LT && integer_zerop (arg1))
-+ || (! only_cheap && code == GE && integer_zerop (arg1)))
-+ ;
-+ else if (BRANCH_COST >= 0
-+ && ! only_cheap && (code == NE || code == EQ)
-+ && TREE_CODE (type) != REAL_TYPE
-+ && ((abs_optab->handlers[(int) operand_mode].insn_code
-+ != CODE_FOR_nothing)
-+ || (ffs_optab->handlers[(int) operand_mode].insn_code
-+ != CODE_FOR_nothing)))
-+ ;
-+ else
-+ return 0;
-+ }
-+
-+ if (! get_subtarget (target)
-+ || GET_MODE (subtarget) != operand_mode
-+ || ! safe_from_p (subtarget, arg1, 1))
-+ subtarget = 0;
-+
-+ op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
-+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
-+
-+ if (target == 0)
-+ target = gen_reg_rtx (mode);
-+
-+ /* Pass copies of OP0 and OP1 in case they contain a QUEUED. This is safe
-+ because, if the emit_store_flag does anything it will succeed and
-+ OP0 and OP1 will not be used subsequently. */
-+
-+ result = emit_store_flag (target, code,
-+ queued_subexp_p (op0) ? copy_rtx (op0) : op0,
-+ queued_subexp_p (op1) ? copy_rtx (op1) : op1,
-+ operand_mode, unsignedp, 1);
-+
-+ if (result)
-+ {
-+ if (invert)
-+ result = expand_binop (mode, xor_optab, result, const1_rtx,
-+ result, 0, OPTAB_LIB_WIDEN);
-+ return result;
-+ }
-+
-+ /* If this failed, we have to do this with set/compare/jump/set code. */
-+ if (GET_CODE (target) != REG
-+ || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1))
-+ target = gen_reg_rtx (GET_MODE (target));
-+
-+ emit_move_insn (target, invert ? const0_rtx : const1_rtx);
-+ result = compare_from_rtx (op0, op1, code, unsignedp,
-+ operand_mode, NULL_RTX);
-+ if (GET_CODE (result) == CONST_INT)
-+ return (((result == const0_rtx && ! invert)
-+ || (result != const0_rtx && invert))
-+ ? const0_rtx : const1_rtx);
-+
-+ /* The code of RESULT may not match CODE if compare_from_rtx
-+ decided to swap its operands and reverse the original code.
-+
-+ We know that compare_from_rtx returns either a CONST_INT or
-+ a new comparison code, so it is safe to just extract the
-+ code from RESULT. */
-+ code = GET_CODE (result);
-+
-+ label = gen_label_rtx ();
-+ if (bcc_gen_fctn[(int) code] == 0)
-+ abort ();
-+
-+ emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
-+ emit_move_insn (target, invert ? const1_rtx : const0_rtx);
-+ emit_label (label);
-+
-+ return target;
-+}
-+\f
-+
-+/* Stubs in case we haven't got a casesi insn. */
-+#ifndef HAVE_casesi
-+# define HAVE_casesi 0
-+# define gen_casesi(a, b, c, d, e) (0)
-+# define CODE_FOR_casesi CODE_FOR_nothing
-+#endif
-+
-+/* If the machine does not have a case insn that compares the bounds,
-+ this means extra overhead for dispatch tables, which raises the
-+ threshold for using them. */
-+#ifndef CASE_VALUES_THRESHOLD
-+#define CASE_VALUES_THRESHOLD (HAVE_casesi ? 4 : 5)
-+#endif /* CASE_VALUES_THRESHOLD */
-+
-+unsigned int
-+case_values_threshold ()
-+{
-+ return CASE_VALUES_THRESHOLD;
-+}
-+
-+/* Attempt to generate a casesi instruction. Returns 1 if successful,
-+ 0 otherwise (i.e. if there is no casesi instruction). */
-+int
-+try_casesi (index_type, index_expr, minval, range,
-+ table_label, default_label)
-+ tree index_type, index_expr, minval, range;
-+ rtx table_label ATTRIBUTE_UNUSED;
-+ rtx default_label;
-+{
-+ enum machine_mode index_mode = SImode;
-+ int index_bits = GET_MODE_BITSIZE (index_mode);
-+ rtx op1, op2, index;
-+ enum machine_mode op_mode;
-+
-+ if (! HAVE_casesi)
-+ return 0;
-+
-+ /* Convert the index to SImode. */
-+ if (GET_MODE_BITSIZE (TYPE_MODE (index_type)) > GET_MODE_BITSIZE (index_mode))
-+ {
-+ enum machine_mode omode = TYPE_MODE (index_type);
-+ rtx rangertx = expand_expr (range, NULL_RTX, VOIDmode, 0);
-+
-+ /* We must handle the endpoints in the original mode. */
-+ index_expr = build (MINUS_EXPR, index_type,
-+ index_expr, minval);
-+ minval = integer_zero_node;
-+ index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
-+ emit_cmp_and_jump_insns (rangertx, index, LTU, NULL_RTX,
-+ omode, 1, default_label);
-+ /* Now we can safely truncate. */
-+ index = convert_to_mode (index_mode, index, 0);
-+ }
-+ else
-+ {
-+ if (TYPE_MODE (index_type) != index_mode)
-+ {
-+ index_expr = convert ((*lang_hooks.types.type_for_size)
-+ (index_bits, 0), index_expr);
-+ index_type = TREE_TYPE (index_expr);
-+ }
-+
-+ index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
-+ }
-+ emit_queue ();
-+ index = protect_from_queue (index, 0);
-+ do_pending_stack_adjust ();
-+
-+ op_mode = insn_data[(int) CODE_FOR_casesi].operand[0].mode;
-+ if (! (*insn_data[(int) CODE_FOR_casesi].operand[0].predicate)
-+ (index, op_mode))
-+ index = copy_to_mode_reg (op_mode, index);
-+
-+ op1 = expand_expr (minval, NULL_RTX, VOIDmode, 0);
-+
-+ op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode;
-+ op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)),
-+ op1, TREE_UNSIGNED (TREE_TYPE (minval)));
-+ if (! (*insn_data[(int) CODE_FOR_casesi].operand[1].predicate)
-+ (op1, op_mode))
-+ op1 = copy_to_mode_reg (op_mode, op1);
-+
-+ op2 = expand_expr (range, NULL_RTX, VOIDmode, 0);
-+
-+ op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode;
-+ op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)),
-+ op2, TREE_UNSIGNED (TREE_TYPE (range)));
-+ if (! (*insn_data[(int) CODE_FOR_casesi].operand[2].predicate)
-+ (op2, op_mode))
-+ op2 = copy_to_mode_reg (op_mode, op2);
-+
-+ emit_jump_insn (gen_casesi (index, op1, op2,
-+ table_label, default_label));
-+ return 1;
-+}
-+
-+/* Attempt to generate a tablejump instruction; same concept. */
-+#ifndef HAVE_tablejump
-+#define HAVE_tablejump 0
-+#define gen_tablejump(x, y) (0)
-+#endif
-+
-+/* Subroutine of the next function.
-+
-+ INDEX is the value being switched on, with the lowest value
-+ in the table already subtracted.
-+ MODE is its expected mode (needed if INDEX is constant).
-+ RANGE is the length of the jump table.
-+ TABLE_LABEL is a CODE_LABEL rtx for the table itself.
-+
-+ DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
-+ index value is out of range. */
-+
-+static void
-+do_tablejump (index, mode, range, table_label, default_label)
-+ rtx index, range, table_label, default_label;
-+ enum machine_mode mode;
-+{
-+ rtx temp, vector;
-+
-+ if (INTVAL (range) > cfun->max_jumptable_ents)
-+ cfun->max_jumptable_ents = INTVAL (range);
-+
-+ /* Do an unsigned comparison (in the proper mode) between the index
-+ expression and the value which represents the length of the range.
-+ Since we just finished subtracting the lower bound of the range
-+ from the index expression, this comparison allows us to simultaneously
-+ check that the original index expression value is both greater than
-+ or equal to the minimum value of the range and less than or equal to
-+ the maximum value of the range. */
-+
-+ emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
-+ default_label);
-+
-+ /* If index is in range, it must fit in Pmode.
-+ Convert to Pmode so we can index with it. */
-+ if (mode != Pmode)
-+ index = convert_to_mode (Pmode, index, 1);
-+
-+ /* Don't let a MEM slip thru, because then INDEX that comes
-+ out of PIC_CASE_VECTOR_ADDRESS won't be a valid address,
-+ and break_out_memory_refs will go to work on it and mess it up. */
-+#ifdef PIC_CASE_VECTOR_ADDRESS
-+ if (flag_pic && GET_CODE (index) != REG)
-+ index = copy_to_mode_reg (Pmode, index);
-+#endif
-+
-+ /* If flag_force_addr were to affect this address
-+ it could interfere with the tricky assumptions made
-+ about addresses that contain label-refs,
-+ which may be valid only very near the tablejump itself. */
-+ /* ??? The only correct use of CASE_VECTOR_MODE is the one inside the
-+ GET_MODE_SIZE, because this indicates how large insns are. The other
-+ uses should all be Pmode, because they are addresses. This code
-+ could fail if addresses and insns are not the same size. */
-+ index = gen_rtx_PLUS (Pmode,
-+ gen_rtx_MULT (Pmode, index,
-+ GEN_INT (GET_MODE_SIZE (CASE_VECTOR_MODE))),
-+ gen_rtx_LABEL_REF (Pmode, table_label));
-+#ifdef PIC_CASE_VECTOR_ADDRESS
-+ if (flag_pic)
-+ index = PIC_CASE_VECTOR_ADDRESS (index);
-+ else
-+#endif
-+ index = memory_address_noforce (CASE_VECTOR_MODE, index);
-+ temp = gen_reg_rtx (CASE_VECTOR_MODE);
-+ vector = gen_rtx_MEM (CASE_VECTOR_MODE, index);
-+ RTX_UNCHANGING_P (vector) = 1;
-+ MEM_NOTRAP_P (vector) = 1;
-+ convert_move (temp, vector, 0);
-+
-+ emit_jump_insn (gen_tablejump (temp, table_label));
-+
-+ /* If we are generating PIC code or if the table is PC-relative, the
-+ table and JUMP_INSN must be adjacent, so don't output a BARRIER. */
-+ if (! CASE_VECTOR_PC_RELATIVE && ! flag_pic)
-+ emit_barrier ();
-+}
-+
-+int
-+try_tablejump (index_type, index_expr, minval, range,
-+ table_label, default_label)
-+ tree index_type, index_expr, minval, range;
-+ rtx table_label, default_label;
-+{
-+ rtx index;
-+
-+ if (! HAVE_tablejump)
-+ return 0;
-+
-+ index_expr = fold (build (MINUS_EXPR, index_type,
-+ convert (index_type, index_expr),
-+ convert (index_type, minval)));
-+ index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
-+ emit_queue ();
-+ index = protect_from_queue (index, 0);
-+ do_pending_stack_adjust ();
-+
-+ do_tablejump (index, TYPE_MODE (index_type),
-+ convert_modes (TYPE_MODE (index_type),
-+ TYPE_MODE (TREE_TYPE (range)),
-+ expand_expr (range, NULL_RTX,
-+ VOIDmode, 0),
-+ TREE_UNSIGNED (TREE_TYPE (range))),
-+ table_label, default_label);
-+ return 1;
-+}
-+
-+/* Nonzero if the mode is a valid vector mode for this architecture.
-+ This returns nonzero even if there is no hardware support for the
-+ vector mode, but we can emulate with narrower modes. */
-+
-+int
-+vector_mode_valid_p (mode)
-+ enum machine_mode mode;
-+{
-+ enum mode_class class = GET_MODE_CLASS (mode);
-+ enum machine_mode innermode;
-+
-+ /* Doh! What's going on? */
-+ if (class != MODE_VECTOR_INT
-+ && class != MODE_VECTOR_FLOAT)
-+ return 0;
-+
-+ /* Hardware support. Woo hoo! */
-+ if (VECTOR_MODE_SUPPORTED_P (mode))
-+ return 1;
-+
-+ innermode = GET_MODE_INNER (mode);
-+
-+ /* We should probably return 1 if requesting V4DI and we have no DI,
-+ but we have V2DI, but this is probably very unlikely. */
-+
-+ /* If we have support for the inner mode, we can safely emulate it.
-+ We may not have V2DI, but me can emulate with a pair of DIs. */
-+ return mov_optab->handlers[innermode].insn_code != CODE_FOR_nothing;
-+}
-+
-+/* Return a CONST_VECTOR rtx for a VECTOR_CST tree. */
-+static rtx
-+const_vector_from_tree (exp)
-+ tree exp;
-+{
-+ rtvec v;
-+ int units, i;
-+ tree link, elt;
-+ enum machine_mode inner, mode;
-+
-+ mode = TYPE_MODE (TREE_TYPE (exp));
-+
-+ if (is_zeros_p (exp))
-+ return CONST0_RTX (mode);
-+
-+ units = GET_MODE_NUNITS (mode);
-+ inner = GET_MODE_INNER (mode);
-+
-+ v = rtvec_alloc (units);
-+
-+ link = TREE_VECTOR_CST_ELTS (exp);
-+ for (i = 0; link; link = TREE_CHAIN (link), ++i)
-+ {
-+ elt = TREE_VALUE (link);
-+
-+ if (TREE_CODE (elt) == REAL_CST)
-+ RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
-+ inner);
-+ else
-+ RTVEC_ELT (v, i) = immed_double_const (TREE_INT_CST_LOW (elt),
-+ TREE_INT_CST_HIGH (elt),
-+ inner);
-+ }
-+
-+ return gen_rtx_raw_CONST_VECTOR (mode, v);
-+}
-+
-+#include "gt-expr.h"
-diff -ruN gcc-3.3.1/gcc/flags.h gcc-3.3.1.pp/gcc/flags.h
---- gcc-3.3.1/gcc/flags.h 2003-06-20 21:18:41.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/flags.h 2003-09-05 11:58:59.000000000 +0000
-@@ -690,4 +690,12 @@
- #define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
- (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations)
-
-+/* Nonzero means use propolice as a stack protection method */
-+
-+extern int flag_propolice_protection;
-+
-+/* Warn when not issuing stack smashing protection for some reason */
-+
-+extern int warn_stack_protector;
-+
- #endif /* ! GCC_FLAGS_H */
-diff -ruN gcc-3.3.1/gcc/flags.h.orig gcc-3.3.1.pp/gcc/flags.h.orig
---- gcc-3.3.1/gcc/flags.h.orig 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/flags.h.orig 2003-06-20 21:18:41.000000000 +0000
-@@ -0,0 +1,693 @@
-+/* Compilation switch flag definitions for GCC.
-+ Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002
-+ Free Software Foundation, Inc.
-+
-+This file is part of GCC.
-+
-+GCC is free software; you can redistribute it and/or modify it under
-+the terms of the GNU General Public License as published by the Free
-+Software Foundation; either version 2, or (at your option) any later
-+version.
-+
-+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-+WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GCC; see the file COPYING. If not, write to the Free
-+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-+02111-1307, USA. */
-+
-+#ifndef GCC_FLAGS_H
-+#define GCC_FLAGS_H
-+
-+/* Name of the input .c file being compiled. */
-+extern const char *main_input_filename;
-+
-+enum debug_info_type
-+{
-+ NO_DEBUG, /* Write no debug info. */
-+ DBX_DEBUG, /* Write BSD .stabs for DBX (using dbxout.c). */
-+ SDB_DEBUG, /* Write COFF for (old) SDB (using sdbout.c). */
-+ DWARF_DEBUG, /* Write Dwarf debug info (using dwarfout.c). */
-+ DWARF2_DEBUG, /* Write Dwarf v2 debug info (using dwarf2out.c). */
-+ XCOFF_DEBUG, /* Write IBM/Xcoff debug info (using dbxout.c). */
-+ VMS_DEBUG, /* Write VMS debug info (using vmsdbgout.c). */
-+ VMS_AND_DWARF2_DEBUG /* Write VMS debug info (using vmsdbgout.c).
-+ and DWARF v2 debug info (using dwarf2out.c). */
-+};
-+
-+/* Specify which kind of debugging info to generate. */
-+extern enum debug_info_type write_symbols;
-+
-+enum debug_info_level
-+{
-+ DINFO_LEVEL_NONE, /* Write no debugging info. */
-+ DINFO_LEVEL_TERSE, /* Write minimal info to support tracebacks only. */
-+ DINFO_LEVEL_NORMAL, /* Write info for all declarations (and line table). */
-+ DINFO_LEVEL_VERBOSE /* Write normal info plus #define/#undef info. */
-+};
-+
-+/* Specify how much debugging info to generate. */
-+extern enum debug_info_level debug_info_level;
-+
-+/* Nonzero means use GNU-only extensions in the generated symbolic
-+ debugging information. */
-+extern int use_gnu_debug_info_extensions;
-+
-+/* Nonzero means do optimizations. -opt. */
-+
-+extern int optimize;
-+
-+/* Nonzero means optimize for size. -Os. */
-+
-+extern int optimize_size;
-+
-+/* Don't print functions as they are compiled and don't print
-+ times taken by the various passes. -quiet. */
-+
-+extern int quiet_flag;
-+
-+/* Print times taken by the various passes. -ftime-report. */
-+
-+extern int time_report;
-+
-+/* Print memory still in use at end of compilation (which may have little
-+ to do with peak memory consumption). -fmem-report. */
-+
-+extern int mem_report;
-+
-+/* Don't print warning messages. -w. */
-+
-+extern int inhibit_warnings;
-+
-+/* Don't suppress warnings from system headers. -Wsystem-headers. */
-+
-+extern int warn_system_headers;
-+
-+/* Do print extra warnings (such as for uninitialized variables). -W. */
-+
-+extern int extra_warnings;
-+
-+/* Nonzero to warn about unused variables, functions et.al. Use
-+ set_Wunused() to update the -Wunused-* flags that correspond to the
-+ -Wunused option. */
-+
-+extern void set_Wunused PARAMS ((int setting));
-+
-+extern int warn_unused_function;
-+extern int warn_unused_label;
-+extern int warn_unused_parameter;
-+extern int warn_unused_variable;
-+extern int warn_unused_value;
-+
-+/* Nonzero to warn about code which is never reached. */
-+
-+extern int warn_notreached;
-+
-+/* Nonzero means warn if inline function is too large. */
-+
-+extern int warn_inline;
-+
-+/* Nonzero to warn about variables used before they are initialized. */
-+
-+extern int warn_uninitialized;
-+
-+/* Zero if unknown pragmas are ignored
-+ One if the compiler should warn about an unknown pragma not in
-+ a system include file.
-+ Greater than one if the compiler should warn for all unknown
-+ pragmas. */
-+
-+extern int warn_unknown_pragmas;
-+
-+/* Nonzero means warn about all declarations which shadow others. */
-+
-+extern int warn_shadow;
-+
-+/* Warn if a switch on an enum, that does not have a default case,
-+ fails to have a case for every enum value. */
-+
-+extern int warn_switch;
-+
-+/* Warn if a switch does not have a default case. */
-+
-+extern int warn_switch_default;
-+
-+/* Warn if a switch on an enum fails to have a case for every enum
-+ value (regardless of the presence or otherwise of a default case). */
-+
-+extern int warn_switch_enum;
-+
-+/* Nonzero means warn about function definitions that default the return type
-+ or that use a null return and have a return-type other than void. */
-+
-+extern int warn_return_type;
-+
-+/* Warn about functions which might be candidates for attribute noreturn. */
-+
-+extern int warn_missing_noreturn;
-+
-+/* Nonzero means warn about pointer casts that increase the required
-+ alignment of the target type (and might therefore lead to a crash
-+ due to a misaligned access). */
-+
-+extern int warn_cast_align;
-+
-+/* Nonzero means warn about any objects definitions whose size is larger
-+ than N bytes. Also want about function definitions whose returned
-+ values are larger than N bytes. The value N is in `larger_than_size'. */
-+
-+extern int warn_larger_than;
-+extern HOST_WIDE_INT larger_than_size;
-+
-+/* Warn if a function returns an aggregate,
-+ since there are often incompatible calling conventions for doing this. */
-+
-+extern int warn_aggregate_return;
-+
-+/* Warn if packed attribute on struct is unnecessary and inefficient. */
-+
-+extern int warn_packed;
-+
-+/* Warn when gcc pads a structure to an alignment boundary. */
-+
-+extern int warn_padded;
-+
-+/* Warn when an optimization pass is disabled. */
-+
-+extern int warn_disabled_optimization;
-+
-+/* Nonzero means warn about uses of __attribute__((deprecated))
-+ declarations. */
-+
-+extern int warn_deprecated_decl;
-+
-+/* Nonzero means warn about constructs which might not be strict
-+ aliasing safe. */
-+
-+extern int warn_strict_aliasing;
-+
-+/* Nonzero if generating code to do profiling. */
-+
-+extern int profile_flag;
-+
-+/* Nonzero if generating code to profile program flow graph arcs. */
-+
-+extern int profile_arc_flag;
-+
-+/* Nonzero if generating info for gcov to calculate line test coverage. */
-+
-+extern int flag_test_coverage;
-+
-+/* Nonzero indicates that branch taken probabilities should be calculated. */
-+
-+extern int flag_branch_probabilities;
-+
-+/* Nonzero if basic blocks should be reordered. */
-+
-+extern int flag_reorder_blocks;
-+
-+/* Nonzero if functions should be reordered. */
-+
-+extern int flag_reorder_functions;
-+
-+/* Nonzero if registers should be renamed. */
-+
-+extern int flag_rename_registers;
-+
-+/* Nonzero for -pedantic switch: warn about anything
-+ that standard C forbids. */
-+
-+extern int pedantic;
-+
-+/* Temporarily suppress certain warnings.
-+ This is set while reading code from a system header file. */
-+
-+extern int in_system_header;
-+
-+/* Nonzero for -dp: annotate the assembly with a comment describing the
-+ pattern and alternative used. */
-+
-+extern int flag_print_asm_name;
-+\f
-+/* Now the symbols that are set with `-f' switches. */
-+
-+/* Nonzero means `char' should be signed. */
-+
-+extern int flag_signed_char;
-+
-+/* Nonzero means give an enum type only as many bytes as it needs. */
-+
-+extern int flag_short_enums;
-+
-+/* Nonzero for -fcaller-saves: allocate values in regs that need to
-+ be saved across function calls, if that produces overall better code.
-+ Optional now, so people can test it. */
-+
-+extern int flag_caller_saves;
-+
-+/* Nonzero for -fpcc-struct-return: return values the same way PCC does. */
-+
-+extern int flag_pcc_struct_return;
-+
-+/* Nonzero for -fforce-mem: load memory value into a register
-+ before arithmetic on it. This makes better cse but slower compilation. */
-+
-+extern int flag_force_mem;
-+
-+/* Nonzero for -fforce-addr: load memory address into a register before
-+ reference to memory. This makes better cse but slower compilation. */
-+
-+extern int flag_force_addr;
-+
-+/* Nonzero for -fdefer-pop: don't pop args after each function call;
-+ instead save them up to pop many calls' args with one insns. */
-+
-+extern int flag_defer_pop;
-+
-+/* Nonzero for -ffloat-store: don't allocate floats and doubles
-+ in extended-precision registers. */
-+
-+extern int flag_float_store;
-+
-+/* Nonzero enables strength-reduction in loop.c. */
-+
-+extern int flag_strength_reduce;
-+
-+/* Nonzero enables loop unrolling in unroll.c. Only loops for which the
-+ number of iterations can be calculated at compile-time (UNROLL_COMPLETELY,
-+ UNROLL_MODULO) or at run-time (preconditioned to be UNROLL_MODULO) are
-+ unrolled. */
-+
-+extern int flag_unroll_loops;
-+
-+/* Nonzero enables loop unrolling in unroll.c. All loops are unrolled.
-+ This is generally not a win. */
-+
-+extern int flag_unroll_all_loops;
-+
-+/* Nonzero forces all invariant computations in loops to be moved
-+ outside the loop. */
-+
-+extern int flag_move_all_movables;
-+
-+/* Nonzero enables prefetch optimizations for arrays in loops. */
-+
-+extern int flag_prefetch_loop_arrays;
-+
-+/* Nonzero forces all general induction variables in loops to be
-+ strength reduced. */
-+
-+extern int flag_reduce_all_givs;
-+
-+/* Nonzero for -fcse-follow-jumps:
-+ have cse follow jumps to do a more extensive job. */
-+
-+extern int flag_cse_follow_jumps;
-+
-+/* Nonzero for -fcse-skip-blocks:
-+ have cse follow a branch around a block. */
-+
-+extern int flag_cse_skip_blocks;
-+
-+/* Nonzero for -fexpensive-optimizations:
-+ perform miscellaneous relatively-expensive optimizations. */
-+extern int flag_expensive_optimizations;
-+
-+/* Nonzero for -fwritable-strings:
-+ store string constants in data segment and don't uniquize them. */
-+
-+extern int flag_writable_strings;
-+
-+/* Nonzero means don't put addresses of constant functions in registers.
-+ Used for compiling the Unix kernel, where strange substitutions are
-+ done on the assembly output. */
-+
-+extern int flag_no_function_cse;
-+
-+/* Nonzero for -fomit-frame-pointer:
-+ don't make a frame pointer in simple functions that don't require one. */
-+
-+extern int flag_omit_frame_pointer;
-+
-+/* Nonzero to inhibit use of define_optimization peephole opts. */
-+
-+extern int flag_no_peephole;
-+
-+/* Nonzero means all references through pointers are volatile. */
-+
-+extern int flag_volatile;
-+
-+/* Nonzero means treat all global and extern variables as volatile. */
-+
-+extern int flag_volatile_global;
-+
-+/* Nonzero means treat all static variables as volatile. */
-+
-+extern int flag_volatile_static;
-+
-+/* Nonzero allows GCC to optimize sibling and tail recursive calls. */
-+
-+extern int flag_optimize_sibling_calls;
-+
-+/* Nonzero means the front end generally wants `errno' maintained by math
-+ operations, like built-in SQRT. */
-+
-+extern int flag_errno_math;
-+
-+/* Nonzero means that unsafe floating-point math optimizations are allowed
-+ for the sake of speed. IEEE compliance is not guaranteed, and operations
-+ are allowed to assume that their arguments and results are "normal"
-+ (e.g., nonnegative for SQRT). */
-+
-+extern int flag_unsafe_math_optimizations;
-+
-+/* Nonzero means that no NaNs or +-Infs are expected. */
-+
-+extern int flag_finite_math_only;
-+
-+/* Zero means that floating-point math operations cannot generate a
-+ (user-visible) trap. This is the case, for example, in nonstop
-+ IEEE 754 arithmetic. */
-+
-+extern int flag_trapping_math;
-+
-+/* 0 means straightforward implementation of complex divide acceptable.
-+ 1 means wide ranges of inputs must work for complex divide.
-+ 2 means C99-like requirements for complex divide (not yet implemented). */
-+
-+extern int flag_complex_divide_method;
-+
-+/* Nonzero means to run loop optimizations twice. */
-+
-+extern int flag_rerun_loop_opt;
-+
-+/* Nonzero means make functions that look like good inline candidates
-+ go inline. */
-+
-+extern int flag_inline_functions;
-+
-+/* Nonzero for -fkeep-inline-functions: even if we make a function
-+ go inline everywhere, keep its definition around for debugging
-+ purposes. */
-+
-+extern int flag_keep_inline_functions;
-+
-+/* Nonzero means that functions declared `inline' will be treated
-+ as `static'. Prevents generation of zillions of copies of unused
-+ static inline functions; instead, `inlines' are written out
-+ only when actually used. Used in conjunction with -g. Also
-+ does the right thing with #pragma interface. */
-+
-+extern int flag_no_inline;
-+
-+/* Nonzero means that we don't want inlining by virtue of -fno-inline,
-+ not just because the tree inliner turned us off. */
-+
-+extern int flag_really_no_inline;
-+
-+/* Nonzero if we are only using compiler to check syntax errors. */
-+
-+extern int flag_syntax_only;
-+
-+/* Nonzero means we should save auxiliary info into a .X file. */
-+
-+extern int flag_gen_aux_info;
-+
-+/* Nonzero means make the text shared if supported. */
-+
-+extern int flag_shared_data;
-+
-+/* flag_schedule_insns means schedule insns within basic blocks (before
-+ local_alloc).
-+ flag_schedule_insns_after_reload means schedule insns after
-+ global_alloc. */
-+
-+extern int flag_schedule_insns;
-+extern int flag_schedule_insns_after_reload;
-+
-+/* The following flags have effect only for scheduling before register
-+ allocation:
-+
-+ flag_schedule_interblock means schedule insns across basic blocks.
-+ flag_schedule_speculative means allow speculative motion of non-load insns.
-+ flag_schedule_speculative_load means allow speculative motion of some
-+ load insns.
-+ flag_schedule_speculative_load_dangerous allows speculative motion of more
-+ load insns. */
-+
-+extern int flag_schedule_interblock;
-+extern int flag_schedule_speculative;
-+extern int flag_schedule_speculative_load;
-+extern int flag_schedule_speculative_load_dangerous;
-+
-+/* flag_branch_on_count_reg means try to replace add-1,compare,branch tupple
-+ by a cheaper branch, on a count register. */
-+extern int flag_branch_on_count_reg;
-+
-+/* This option is set to 1 on -fsingle-precision-constant option which is
-+ used to convert the floating point constants to single precision
-+ constants. */
-+
-+extern int flag_single_precision_constant;
-+
-+/* Nonzero means put things in delayed-branch slots if supported. */
-+
-+extern int flag_delayed_branch;
-+
-+/* Nonzero means suppress output of instruction numbers and line number
-+ notes in debugging dumps. */
-+
-+extern int flag_dump_unnumbered;
-+
-+/* Nonzero means change certain warnings into errors.
-+ Usually these are warnings about failure to conform to some standard. */
-+
-+extern int flag_pedantic_errors;
-+
-+/* Nonzero means generate position-independent code. 1 vs 2 for a
-+ target-dependent "small" or "large" mode. */
-+
-+extern int flag_pic;
-+
-+/* Nonzero means generate extra code for exception handling and enable
-+ exception handling. */
-+
-+extern int flag_exceptions;
-+
-+/* Nonzero means generate frame unwind info table when supported */
-+
-+extern int flag_unwind_tables;
-+
-+/* Nonzero means generate frame unwind info table exact at each insn boundary */
-+
-+extern int flag_asynchronous_unwind_tables;
-+
-+/* Nonzero means don't place uninitialized global data in common storage
-+ by default. */
-+
-+extern int flag_no_common;
-+
-+/* -finhibit-size-directive inhibits output of .size for ELF.
-+ This is used only for compiling crtstuff.c,
-+ and it may be extended to other effects
-+ needed for crtstuff.c on other systems. */
-+extern int flag_inhibit_size_directive;
-+
-+/* Nonzero means place each function into its own section on those platforms
-+ which support arbitrary section names and unlimited numbers of sections. */
-+
-+extern int flag_function_sections;
-+
-+/* ... and similar for data. */
-+
-+extern int flag_data_sections;
-+
-+/* -fverbose-asm causes extra commentary information to be produced in
-+ the generated assembly code (to make it more readable). This option
-+ is generally only of use to those who actually need to read the
-+ generated assembly code (perhaps while debugging the compiler itself).
-+ -fno-verbose-asm, the default, causes the extra information
-+ to not be added and is useful when comparing two assembler files. */
-+
-+extern int flag_verbose_asm;
-+
-+/* -dA causes debug information to be produced in
-+ the generated assembly code (to make it more readable). This option
-+ is generally only of use to those who actually need to read the
-+ generated assembly code (perhaps while debugging the compiler itself).
-+ Currently, this switch is only used by dwarfout.c; however, it is intended
-+ to be a catchall for printing debug information in the assembler file. */
-+
-+extern int flag_debug_asm;
-+
-+extern int flag_dump_rtl_in_asm;
-+
-+/* -fgnu-linker specifies use of the GNU linker for initializations.
-+ -fno-gnu-linker says that collect will be used. */
-+extern int flag_gnu_linker;
-+
-+/* Tag all structures with __attribute__(packed) */
-+extern int flag_pack_struct;
-+
-+/* This flag is only tested if alias checking is enabled.
-+ 0 if pointer arguments may alias each other. True in C.
-+ 1 if pointer arguments may not alias each other but may alias
-+ global variables.
-+ 2 if pointer arguments may not alias each other and may not
-+ alias global variables. True in Fortran.
-+ The value is ignored if flag_alias_check is 0. */
-+extern int flag_argument_noalias;
-+
-+/* Nonzero if we should do (language-dependent) alias analysis.
-+ Typically, this analysis will assume that expressions of certain
-+ types do not alias expressions of certain other types. Only used
-+ if alias analysis (in general) is enabled. */
-+extern int flag_strict_aliasing;
-+
-+/* Emit code to probe the stack, to help detect stack overflow; also
-+ may cause large objects to be allocated dynamically. */
-+extern int flag_stack_check;
-+
-+/* Do the full regmove optimization pass. */
-+extern int flag_regmove;
-+
-+/* Instrument functions with calls at entry and exit, for profiling. */
-+extern int flag_instrument_function_entry_exit;
-+
-+/* Perform a peephole pass before sched2. */
-+extern int flag_peephole2;
-+
-+/* Try to guess branch probablities. */
-+extern int flag_guess_branch_prob;
-+
-+/* -fcheck-bounds causes gcc to generate array bounds checks.
-+ For C, C++ and ObjC: defaults off.
-+ For Java: defaults to on.
-+ For Fortran: defaults to off. */
-+extern int flag_bounds_check;
-+
-+/* This will attempt to merge constant section constants, if 1 only
-+ string constants and constants from constant pool, if 2 also constant
-+ variables. */
-+extern int flag_merge_constants;
-+
-+/* If one, renumber instruction UIDs to reduce the number of
-+ unused UIDs if there are a lot of instructions. If greater than
-+ one, unconditionally renumber instruction UIDs. */
-+extern int flag_renumber_insns;
-+\f
-+/* Other basic status info about current function. */
-+
-+/* Nonzero means current function must be given a frame pointer.
-+ Set in stmt.c if anything is allocated on the stack there.
-+ Set in reload1.c if anything is allocated on the stack there. */
-+
-+extern int frame_pointer_needed;
-+
-+/* Nonzero if the generated code should trap on signed overflow
-+ for PLUS / SUB / MULT. */
-+extern int flag_trapv;
-+
-+/* Value of the -G xx switch, and whether it was passed or not. */
-+extern int g_switch_value;
-+extern int g_switch_set;
-+
-+/* Values of the -falign-* flags: how much to align labels in code.
-+ 0 means `use default', 1 means `don't align'.
-+ For each variable, there is an _log variant which is the power
-+ of two not less than the variable, for .align output. */
-+
-+extern int align_loops;
-+extern int align_loops_log;
-+extern int align_loops_max_skip;
-+extern int align_jumps;
-+extern int align_jumps_log;
-+extern int align_jumps_max_skip;
-+extern int align_labels;
-+extern int align_labels_log;
-+extern int align_labels_max_skip;
-+extern int align_functions;
-+extern int align_functions_log;
-+
-+/* Like align_functions_log above, but used by front-ends to force the
-+ minimum function alignment. Zero means no alignment is forced. */
-+extern int force_align_functions_log;
-+
-+/* Nonzero if we dump in VCG format, not plain text. */
-+extern int dump_for_graph;
-+
-+/* Selection of the graph form. */
-+enum graph_dump_types
-+{
-+ no_graph = 0,
-+ vcg
-+};
-+extern enum graph_dump_types graph_dump_format;
-+
-+/* Nonzero means ignore `#ident' directives. 0 means handle them.
-+ On SVR4 targets, it also controls whether or not to emit a
-+ string identifying the compiler. */
-+
-+extern int flag_no_ident;
-+
-+/* Nonzero if we want to perform enhanced load motion during gcse. */
-+
-+extern int flag_gcse_lm;
-+
-+/* Nonzero if we want to perform store motion after gcse. */
-+
-+extern int flag_gcse_sm;
-+
-+
-+/* Nonzero means we should do dwarf2 duplicate elimination. */
-+
-+extern int flag_eliminate_dwarf2_dups;
-+
-+/* Nonzero means to collect statistics which might be expensive
-+ and to print them when we are done. */
-+extern int flag_detailed_statistics;
-+
-+/* Nonzero means enable synchronous exceptions for non-call instructions. */
-+extern int flag_non_call_exceptions;
-+
-+/* Nonzero means put zero initialized data in the bss section. */
-+extern int flag_zero_initialized_in_bss;
-+
-+/* Nonzero means disable transformations observable by signaling NaNs. */
-+extern int flag_signaling_nans;
-+
-+/* A string that's used when a random name is required. NULL means
-+ to make it really random. */
-+
-+extern const char *flag_random_seed;
-+
-+/* True if the given mode has a NaN representation and the treatment of
-+ NaN operands is important. Certain optimizations, such as folding
-+ x * 0 into x, are not correct for NaN operands, and are normally
-+ disabled for modes with NaNs. The user can ask for them to be
-+ done anyway using the -funsafe-math-optimizations switch. */
-+#define HONOR_NANS(MODE) \
-+ (MODE_HAS_NANS (MODE) && !flag_finite_math_only)
-+
-+/* Like HONOR_NANs, but true if we honor signaling NaNs (or sNaNs). */
-+#define HONOR_SNANS(MODE) (flag_signaling_nans && HONOR_NANS (MODE))
-+
-+/* As for HONOR_NANS, but true if the mode can represent infinity and
-+ the treatment of infinite values is important. */
-+#define HONOR_INFINITIES(MODE) \
-+ (MODE_HAS_INFINITIES (MODE) && !flag_finite_math_only)
-+
-+/* Like HONOR_NANS, but true if the given mode distinguishes between
-+ postive and negative zero, and the sign of zero is important. */
-+#define HONOR_SIGNED_ZEROS(MODE) \
-+ (MODE_HAS_SIGNED_ZEROS (MODE) && !flag_unsafe_math_optimizations)
-+
-+/* Like HONOR_NANS, but true if given mode supports sign-dependent rounding,
-+ and the rounding mode is important. */
-+#define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
-+ (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations)
-+
-+#endif /* ! GCC_FLAGS_H */
-diff -ruN gcc-3.3.1/gcc/function.c gcc-3.3.1.pp/gcc/function.c
---- gcc-3.3.1/gcc/function.c 2003-04-10 22:26:04.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/function.c 2003-09-05 11:58:59.000000000 +0000
-@@ -59,6 +59,7 @@
- #include "tm_p.h"
- #include "integrate.h"
- #include "langhooks.h"
-+#include "protector.h"
-
- #ifndef TRAMPOLINE_ALIGNMENT
- #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
-@@ -142,6 +143,10 @@
- /* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue
- in this function. */
- static GTY(()) varray_type sibcall_epilogue;
-+
-+/* Current boundary mark for character arrays. */
-+int temp_boundary_mark = 0;
-+
- \f
- /* In order to evaluate some expressions, such as function calls returning
- structures in memory, we need to temporarily allocate stack locations.
-@@ -195,6 +200,8 @@
- /* The size of the slot, including extra space for alignment. This
- info is for combine_temp_slots. */
- HOST_WIDE_INT full_size;
-+ /* Boundary mark of a character array and the others. This info is for propolice */
-+ int boundary_mark;
- };
- \f
- /* This structure is used to record MEMs or pseudos used to replace VAR, any
-@@ -629,6 +636,7 @@
- whose lifetime is controlled by CLEANUP_POINT_EXPRs. KEEP is 3
- if we are to allocate something at an inner level to be treated as
- a variable in the block (e.g., a SAVE_EXPR).
-+ KEEP is 5 if we allocate a place to return structure.
-
- TYPE is the type that will be used for the stack slot. */
-
-@@ -642,6 +650,8 @@
- unsigned int align;
- struct temp_slot *p, *best_p = 0;
- rtx slot;
-+ int char_array = (flag_propolice_protection
-+ && keep == 1 && search_string_def (type));
-
- /* If SIZE is -1 it means that somebody tried to allocate a temporary
- of a variable size. */
-@@ -667,7 +677,8 @@
- && ! p->in_use
- && objects_must_conflict_p (p->type, type)
- && (best_p == 0 || best_p->size > p->size
-- || (best_p->size == p->size && best_p->align > p->align)))
-+ || (best_p->size == p->size && best_p->align > p->align))
-+ && (! char_array || p->boundary_mark != 0))
- {
- if (p->align == align && p->size == size)
- {
-@@ -702,6 +713,7 @@
- p->address = 0;
- p->rtl_expr = 0;
- p->type = best_p->type;
-+ p->boundary_mark = best_p->boundary_mark;
- p->next = temp_slots;
- temp_slots = p;
-
-@@ -762,6 +774,7 @@
- p->full_size = frame_offset - frame_offset_old;
- #endif
- p->address = 0;
-+ p->boundary_mark = char_array?++temp_boundary_mark:0;
- p->next = temp_slots;
- temp_slots = p;
- }
-@@ -932,14 +945,16 @@
- int delete_q = 0;
- if (! q->in_use && GET_MODE (q->slot) == BLKmode)
- {
-- if (p->base_offset + p->full_size == q->base_offset)
-+ if (p->base_offset + p->full_size == q->base_offset &&
-+ p->boundary_mark == q->boundary_mark)
- {
- /* Q comes after P; combine Q into P. */
- p->size += q->size;
- p->full_size += q->full_size;
- delete_q = 1;
- }
-- else if (q->base_offset + q->full_size == p->base_offset)
-+ else if (q->base_offset + q->full_size == p->base_offset &&
-+ p->boundary_mark == q->boundary_mark)
- {
- /* P comes after Q; combine P into Q. */
- q->size += p->size;
-@@ -1497,7 +1512,9 @@
- new = func->x_parm_reg_stack_loc[regno];
-
- if (new == 0)
-- new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func);
-+ new = function ?
-+ assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func):
-+ assign_stack_local_for_pseudo_reg (decl_mode, GET_MODE_SIZE (decl_mode), 0);
-
- PUT_CODE (reg, MEM);
- PUT_MODE (reg, decl_mode);
-@@ -3961,7 +3978,8 @@
- constant with that register. */
- temp = gen_reg_rtx (Pmode);
- XEXP (x, 0) = new;
-- if (validate_change (object, &XEXP (x, 1), temp, 0))
-+ if (validate_change (object, &XEXP (x, 1), temp, 0)
-+ && ! flag_propolice_protection)
- emit_insn_before (gen_move_insn (temp, new_offset), object);
- else
- {
-diff -ruN gcc-3.3.1/gcc/gcse.c gcc-3.3.1.pp/gcc/gcse.c
---- gcc-3.3.1/gcc/gcse.c 2003-07-14 09:21:22.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/gcse.c 2003-09-05 11:58:59.000000000 +0000
-@@ -4211,7 +4211,7 @@
- /* Find an assignment that sets reg_used and is available
- at the start of the block. */
- set = find_avail_set (regno, insn);
-- if (! set)
-+ if (! set || set->expr->volatil)
- continue;
-
- pat = set->expr;
-diff -ruN gcc-3.3.1/gcc/gcse.c.orig gcc-3.3.1.pp/gcc/gcse.c.orig
---- gcc-3.3.1/gcc/gcse.c.orig 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/gcse.c.orig 2003-07-14 09:21:22.000000000 +0000
-@@ -0,0 +1,7477 @@
-+/* Global common subexpression elimination/Partial redundancy elimination
-+ and global constant/copy propagation for GNU compiler.
-+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
-+ Free Software Foundation, Inc.
-+
-+This file is part of GCC.
-+
-+GCC is free software; you can redistribute it and/or modify it under
-+the terms of the GNU General Public License as published by the Free
-+Software Foundation; either version 2, or (at your option) any later
-+version.
-+
-+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-+WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GCC; see the file COPYING. If not, write to the Free
-+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-+02111-1307, USA. */
-+
-+/* TODO
-+ - reordering of memory allocation and freeing to be more space efficient
-+ - do rough calc of how many regs are needed in each block, and a rough
-+ calc of how many regs are available in each class and use that to
-+ throttle back the code in cases where RTX_COST is minimal.
-+ - a store to the same address as a load does not kill the load if the
-+ source of the store is also the destination of the load. Handling this
-+ allows more load motion, particularly out of loops.
-+ - ability to realloc sbitmap vectors would allow one initial computation
-+ of reg_set_in_block with only subsequent additions, rather than
-+ recomputing it for each pass
-+
-+*/
-+
-+/* References searched while implementing this.
-+
-+ Compilers Principles, Techniques and Tools
-+ Aho, Sethi, Ullman
-+ Addison-Wesley, 1988
-+
-+ Global Optimization by Suppression of Partial Redundancies
-+ E. Morel, C. Renvoise
-+ communications of the acm, Vol. 22, Num. 2, Feb. 1979
-+
-+ A Portable Machine-Independent Global Optimizer - Design and Measurements
-+ Frederick Chow
-+ Stanford Ph.D. thesis, Dec. 1983
-+
-+ A Fast Algorithm for Code Movement Optimization
-+ D.M. Dhamdhere
-+ SIGPLAN Notices, Vol. 23, Num. 10, Oct. 1988
-+
-+ A Solution to a Problem with Morel and Renvoise's
-+ Global Optimization by Suppression of Partial Redundancies
-+ K-H Drechsler, M.P. Stadel
-+ ACM TOPLAS, Vol. 10, Num. 4, Oct. 1988
-+
-+ Practical Adaptation of the Global Optimization
-+ Algorithm of Morel and Renvoise
-+ D.M. Dhamdhere
-+ ACM TOPLAS, Vol. 13, Num. 2. Apr. 1991
-+
-+ Efficiently Computing Static Single Assignment Form and the Control
-+ Dependence Graph
-+ R. Cytron, J. Ferrante, B.K. Rosen, M.N. Wegman, and F.K. Zadeck
-+ ACM TOPLAS, Vol. 13, Num. 4, Oct. 1991
-+
-+ Lazy Code Motion
-+ J. Knoop, O. Ruthing, B. Steffen
-+ ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
-+
-+ What's In a Region? Or Computing Control Dependence Regions in Near-Linear
-+ Time for Reducible Flow Control
-+ Thomas Ball
-+ ACM Letters on Programming Languages and Systems,
-+ Vol. 2, Num. 1-4, Mar-Dec 1993
-+
-+ An Efficient Representation for Sparse Sets
-+ Preston Briggs, Linda Torczon
-+ ACM Letters on Programming Languages and Systems,
-+ Vol. 2, Num. 1-4, Mar-Dec 1993
-+
-+ A Variation of Knoop, Ruthing, and Steffen's Lazy Code Motion
-+ K-H Drechsler, M.P. Stadel
-+ ACM SIGPLAN Notices, Vol. 28, Num. 5, May 1993
-+
-+ Partial Dead Code Elimination
-+ J. Knoop, O. Ruthing, B. Steffen
-+ ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
-+
-+ Effective Partial Redundancy Elimination
-+ P. Briggs, K.D. Cooper
-+ ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
-+
-+ The Program Structure Tree: Computing Control Regions in Linear Time
-+ R. Johnson, D. Pearson, K. Pingali
-+ ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994
-+
-+ Optimal Code Motion: Theory and Practice
-+ J. Knoop, O. Ruthing, B. Steffen
-+ ACM TOPLAS, Vol. 16, Num. 4, Jul. 1994
-+
-+ The power of assignment motion
-+ J. Knoop, O. Ruthing, B. Steffen
-+ ACM SIGPLAN Notices Vol. 30, Num. 6, Jun. 1995, '95 Conference on PLDI
-+
-+ Global code motion / global value numbering
-+ C. Click
-+ ACM SIGPLAN Notices Vol. 30, Num. 6, Jun. 1995, '95 Conference on PLDI
-+
-+ Value Driven Redundancy Elimination
-+ L.T. Simpson
-+ Rice University Ph.D. thesis, Apr. 1996
-+
-+ Value Numbering
-+ L.T. Simpson
-+ Massively Scalar Compiler Project, Rice University, Sep. 1996
-+
-+ High Performance Compilers for Parallel Computing
-+ Michael Wolfe
-+ Addison-Wesley, 1996
-+
-+ Advanced Compiler Design and Implementation
-+ Steven Muchnick
-+ Morgan Kaufmann, 1997
-+
-+ Building an Optimizing Compiler
-+ Robert Morgan
-+ Digital Press, 1998
-+
-+ People wishing to speed up the code here should read:
-+ Elimination Algorithms for Data Flow Analysis
-+ B.G. Ryder, M.C. Paull
-+ ACM Computing Surveys, Vol. 18, Num. 3, Sep. 1986
-+
-+ How to Analyze Large Programs Efficiently and Informatively
-+ D.M. Dhamdhere, B.K. Rosen, F.K. Zadeck
-+ ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI
-+
-+ People wishing to do something different can find various possibilities
-+ in the above papers and elsewhere.
-+*/
-+
-+#include "config.h"
-+#include "system.h"
-+#include "toplev.h"
-+
-+#include "rtl.h"
-+#include "tm_p.h"
-+#include "regs.h"
-+#include "hard-reg-set.h"
-+#include "flags.h"
-+#include "real.h"
-+#include "insn-config.h"
-+#include "recog.h"
-+#include "basic-block.h"
-+#include "output.h"
-+#include "function.h"
-+#include "expr.h"
-+#include "except.h"
-+#include "ggc.h"
-+#include "params.h"
-+#include "cselib.h"
-+
-+#include "obstack.h"
-+
-+/* Propagate flow information through back edges and thus enable PRE's
-+ moving loop invariant calculations out of loops.
-+
-+ Originally this tended to create worse overall code, but several
-+ improvements during the development of PRE seem to have made following
-+ back edges generally a win.
-+
-+ Note much of the loop invariant code motion done here would normally
-+ be done by loop.c, which has more heuristics for when to move invariants
-+ out of loops. At some point we might need to move some of those
-+ heuristics into gcse.c. */
-+
-+/* We support GCSE via Partial Redundancy Elimination. PRE optimizations
-+ are a superset of those done by GCSE.
-+
-+ We perform the following steps:
-+
-+ 1) Compute basic block information.
-+
-+ 2) Compute table of places where registers are set.
-+
-+ 3) Perform copy/constant propagation.
-+
-+ 4) Perform global cse.
-+
-+ 5) Perform another pass of copy/constant propagation.
-+
-+ Two passes of copy/constant propagation are done because the first one
-+ enables more GCSE and the second one helps to clean up the copies that
-+ GCSE creates. This is needed more for PRE than for Classic because Classic
-+ GCSE will try to use an existing register containing the common
-+ subexpression rather than create a new one. This is harder to do for PRE
-+ because of the code motion (which Classic GCSE doesn't do).
-+
-+ Expressions we are interested in GCSE-ing are of the form
-+ (set (pseudo-reg) (expression)).
-+ Function want_to_gcse_p says what these are.
-+
-+ PRE handles moving invariant expressions out of loops (by treating them as
-+ partially redundant).
-+
-+ Eventually it would be nice to replace cse.c/gcse.c with SSA (static single
-+ assignment) based GVN (global value numbering). L. T. Simpson's paper
-+ (Rice University) on value numbering is a useful reference for this.
-+
-+ **********************
-+
-+ We used to support multiple passes but there are diminishing returns in
-+ doing so. The first pass usually makes 90% of the changes that are doable.
-+ A second pass can make a few more changes made possible by the first pass.
-+ Experiments show any further passes don't make enough changes to justify
-+ the expense.
-+
-+ A study of spec92 using an unlimited number of passes:
-+ [1 pass] = 1208 substitutions, [2] = 577, [3] = 202, [4] = 192, [5] = 83,
-+ [6] = 34, [7] = 17, [8] = 9, [9] = 4, [10] = 4, [11] = 2,
-+ [12] = 2, [13] = 1, [15] = 1, [16] = 2, [41] = 1
-+
-+ It was found doing copy propagation between each pass enables further
-+ substitutions.
-+
-+ PRE is quite expensive in complicated functions because the DFA can take
-+ awhile to converge. Hence we only perform one pass. The parameter max-gcse-passes can
-+ be modified if one wants to experiment.
-+
-+ **********************
-+
-+ The steps for PRE are:
-+
-+ 1) Build the hash table of expressions we wish to GCSE (expr_hash_table).
-+
-+ 2) Perform the data flow analysis for PRE.
-+
-+ 3) Delete the redundant instructions
-+
-+ 4) Insert the required copies [if any] that make the partially
-+ redundant instructions fully redundant.
-+
-+ 5) For other reaching expressions, insert an instruction to copy the value
-+ to a newly created pseudo that will reach the redundant instruction.
-+
-+ The deletion is done first so that when we do insertions we
-+ know which pseudo reg to use.
-+
-+ Various papers have argued that PRE DFA is expensive (O(n^2)) and others
-+ argue it is not. The number of iterations for the algorithm to converge
-+ is typically 2-4 so I don't view it as that expensive (relatively speaking).
-+
-+ PRE GCSE depends heavily on the second CSE pass to clean up the copies
-+ we create. To make an expression reach the place where it's redundant,
-+ the result of the expression is copied to a new register, and the redundant
-+ expression is deleted by replacing it with this new register. Classic GCSE
-+ doesn't have this problem as much as it computes the reaching defs of
-+ each register in each block and thus can try to use an existing register.
-+
-+ **********************
-+
-+ A fair bit of simplicity is created by creating small functions for simple
-+ tasks, even when the function is only called in one place. This may
-+ measurably slow things down [or may not] by creating more function call
-+ overhead than is necessary. The source is laid out so that it's trivial
-+ to make the affected functions inline so that one can measure what speed
-+ up, if any, can be achieved, and maybe later when things settle things can
-+ be rearranged.
-+
-+ Help stamp out big monolithic functions! */
-+\f
-+/* GCSE global vars. */
-+
-+/* -dG dump file. */
-+static FILE *gcse_file;
-+
-+/* Note whether or not we should run jump optimization after gcse. We
-+ want to do this for two cases.
-+
-+ * If we changed any jumps via cprop.
-+
-+ * If we added any labels via edge splitting. */
-+
-+static int run_jump_opt_after_gcse;
-+
-+/* Bitmaps are normally not included in debugging dumps.
-+ However it's useful to be able to print them from GDB.
-+ We could create special functions for this, but it's simpler to
-+ just allow passing stderr to the dump_foo fns. Since stderr can
-+ be a macro, we store a copy here. */
-+static FILE *debug_stderr;
-+
-+/* An obstack for our working variables. */
-+static struct obstack gcse_obstack;
-+
-+/* Nonzero for each mode that supports (set (reg) (reg)).
-+ This is trivially true for integer and floating point values.
-+ It may or may not be true for condition codes. */
-+static char can_copy_p[(int) NUM_MACHINE_MODES];
-+
-+/* Nonzero if can_copy_p has been initialized. */
-+static int can_copy_init_p;
-+
-+struct reg_use {rtx reg_rtx; };
-+
-+/* Hash table of expressions. */
-+
-+struct expr
-+{
-+ /* The expression (SET_SRC for expressions, PATTERN for assignments). */
-+ rtx expr;
-+ /* Index in the available expression bitmaps. */
-+ int bitmap_index;
-+ /* Next entry with the same hash. */
-+ struct expr *next_same_hash;
-+ /* List of anticipatable occurrences in basic blocks in the function.
-+ An "anticipatable occurrence" is one that is the first occurrence in the
-+ basic block, the operands are not modified in the basic block prior
-+ to the occurrence and the output is not used between the start of
-+ the block and the occurrence. */
-+ struct occr *antic_occr;
-+ /* List of available occurrence in basic blocks in the function.
-+ An "available occurrence" is one that is the last occurrence in the
-+ basic block and the operands are not modified by following statements in
-+ the basic block [including this insn]. */
-+ struct occr *avail_occr;
-+ /* Non-null if the computation is PRE redundant.
-+ The value is the newly created pseudo-reg to record a copy of the
-+ expression in all the places that reach the redundant copy. */
-+ rtx reaching_reg;
-+};
-+
-+/* Occurrence of an expression.
-+ There is one per basic block. If a pattern appears more than once the
-+ last appearance is used [or first for anticipatable expressions]. */
-+
-+struct occr
-+{
-+ /* Next occurrence of this expression. */
-+ struct occr *next;
-+ /* The insn that computes the expression. */
-+ rtx insn;
-+ /* Nonzero if this [anticipatable] occurrence has been deleted. */
-+ char deleted_p;
-+ /* Nonzero if this [available] occurrence has been copied to
-+ reaching_reg. */
-+ /* ??? This is mutually exclusive with deleted_p, so they could share
-+ the same byte. */
-+ char copied_p;
-+};
-+
-+/* Expression and copy propagation hash tables.
-+ Each hash table is an array of buckets.
-+ ??? It is known that if it were an array of entries, structure elements
-+ `next_same_hash' and `bitmap_index' wouldn't be necessary. However, it is
-+ not clear whether in the final analysis a sufficient amount of memory would
-+ be saved as the size of the available expression bitmaps would be larger
-+ [one could build a mapping table without holes afterwards though].
-+ Someday I'll perform the computation and figure it out. */
-+
-+struct hash_table
-+{
-+ /* The table itself.
-+ This is an array of `expr_hash_table_size' elements. */
-+ struct expr **table;
-+
-+ /* Size of the hash table, in elements. */
-+ unsigned int size;
-+
-+ /* Number of hash table elements. */
-+ unsigned int n_elems;
-+
-+ /* Whether the table is expression of copy propagation one. */
-+ int set_p;
-+};
-+
-+/* Expression hash table. */
-+static struct hash_table expr_hash_table;
-+
-+/* Copy propagation hash table. */
-+static struct hash_table set_hash_table;
-+
-+/* Mapping of uids to cuids.
-+ Only real insns get cuids. */
-+static int *uid_cuid;
-+
-+/* Highest UID in UID_CUID. */
-+static int max_uid;
-+
-+/* Get the cuid of an insn. */
-+#ifdef ENABLE_CHECKING
-+#define INSN_CUID(INSN) (INSN_UID (INSN) > max_uid ? (abort (), 0) : uid_cuid[INSN_UID (INSN)])
-+#else
-+#define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
-+#endif
-+
-+/* Number of cuids. */
-+static int max_cuid;
-+
-+/* Mapping of cuids to insns. */
-+static rtx *cuid_insn;
-+
-+/* Get insn from cuid. */
-+#define CUID_INSN(CUID) (cuid_insn[CUID])
-+
-+/* Maximum register number in function prior to doing gcse + 1.
-+ Registers created during this pass have regno >= max_gcse_regno.
-+ This is named with "gcse" to not collide with global of same name. */
-+static unsigned int max_gcse_regno;
-+
-+/* Table of registers that are modified.
-+
-+ For each register, each element is a list of places where the pseudo-reg
-+ is set.
-+
-+ For simplicity, GCSE is done on sets of pseudo-regs only. PRE GCSE only
-+ requires knowledge of which blocks kill which regs [and thus could use
-+ a bitmap instead of the lists `reg_set_table' uses].
-+
-+ `reg_set_table' and could be turned into an array of bitmaps (num-bbs x
-+ num-regs) [however perhaps it may be useful to keep the data as is]. One
-+ advantage of recording things this way is that `reg_set_table' is fairly
-+ sparse with respect to pseudo regs but for hard regs could be fairly dense
-+ [relatively speaking]. And recording sets of pseudo-regs in lists speeds
-+ up functions like compute_transp since in the case of pseudo-regs we only
-+ need to iterate over the number of times a pseudo-reg is set, not over the
-+ number of basic blocks [clearly there is a bit of a slow down in the cases
-+ where a pseudo is set more than once in a block, however it is believed
-+ that the net effect is to speed things up]. This isn't done for hard-regs
-+ because recording call-clobbered hard-regs in `reg_set_table' at each
-+ function call can consume a fair bit of memory, and iterating over
-+ hard-regs stored this way in compute_transp will be more expensive. */
-+
-+typedef struct reg_set
-+{
-+ /* The next setting of this register. */
-+ struct reg_set *next;
-+ /* The insn where it was set. */
-+ rtx insn;
-+} reg_set;
-+
-+static reg_set **reg_set_table;
-+
-+/* Size of `reg_set_table'.
-+ The table starts out at max_gcse_regno + slop, and is enlarged as
-+ necessary. */
-+static int reg_set_table_size;
-+
-+/* Amount to grow `reg_set_table' by when it's full. */
-+#define REG_SET_TABLE_SLOP 100
-+
-+/* This is a list of expressions which are MEMs and will be used by load
-+ or store motion.
-+ Load motion tracks MEMs which aren't killed by
-+ anything except itself. (ie, loads and stores to a single location).
-+ We can then allow movement of these MEM refs with a little special
-+ allowance. (all stores copy the same value to the reaching reg used
-+ for the loads). This means all values used to store into memory must have
-+ no side effects so we can re-issue the setter value.
-+ Store Motion uses this structure as an expression table to track stores
-+ which look interesting, and might be moveable towards the exit block. */
-+
-+struct ls_expr
-+{
-+ struct expr * expr; /* Gcse expression reference for LM. */
-+ rtx pattern; /* Pattern of this mem. */
-+ rtx loads; /* INSN list of loads seen. */
-+ rtx stores; /* INSN list of stores seen. */
-+ struct ls_expr * next; /* Next in the list. */
-+ int invalid; /* Invalid for some reason. */
-+ int index; /* If it maps to a bitmap index. */
-+ int hash_index; /* Index when in a hash table. */
-+ rtx reaching_reg; /* Register to use when re-writing. */
-+};
-+
-+/* Head of the list of load/store memory refs. */
-+static struct ls_expr * pre_ldst_mems = NULL;
-+
-+/* Bitmap containing one bit for each register in the program.
-+ Used when performing GCSE to track which registers have been set since
-+ the start of the basic block. */
-+static regset reg_set_bitmap;
-+
-+/* For each block, a bitmap of registers set in the block.
-+ This is used by expr_killed_p and compute_transp.
-+ It is computed during hash table computation and not by compute_sets
-+ as it includes registers added since the last pass (or between cprop and
-+ gcse) and it's currently not easy to realloc sbitmap vectors. */
-+static sbitmap *reg_set_in_block;
-+
-+/* Array, indexed by basic block number for a list of insns which modify
-+ memory within that block. */
-+static rtx * modify_mem_list;
-+bitmap modify_mem_list_set;
-+
-+/* This array parallels modify_mem_list, but is kept canonicalized. */
-+static rtx * canon_modify_mem_list;
-+bitmap canon_modify_mem_list_set;
-+/* Various variables for statistics gathering. */
-+
-+/* Memory used in a pass.
-+ This isn't intended to be absolutely precise. Its intent is only
-+ to keep an eye on memory usage. */
-+static int bytes_used;
-+
-+/* GCSE substitutions made. */
-+static int gcse_subst_count;
-+/* Number of copy instructions created. */
-+static int gcse_create_count;
-+/* Number of constants propagated. */
-+static int const_prop_count;
-+/* Number of copys propagated. */
-+static int copy_prop_count;
-+\f
-+/* These variables are used by classic GCSE.
-+ Normally they'd be defined a bit later, but `rd_gen' needs to
-+ be declared sooner. */
-+
-+/* Each block has a bitmap of each type.
-+ The length of each blocks bitmap is:
-+
-+ max_cuid - for reaching definitions
-+ n_exprs - for available expressions
-+
-+ Thus we view the bitmaps as 2 dimensional arrays. i.e.
-+ rd_kill[block_num][cuid_num]
-+ ae_kill[block_num][expr_num] */
-+
-+/* For reaching defs */
-+static sbitmap *rd_kill, *rd_gen, *reaching_defs, *rd_out;
-+
-+/* for available exprs */
-+static sbitmap *ae_kill, *ae_gen, *ae_in, *ae_out;
-+
-+/* Objects of this type are passed around by the null-pointer check
-+ removal routines. */
-+struct null_pointer_info
-+{
-+ /* The basic block being processed. */
-+ basic_block current_block;
-+ /* The first register to be handled in this pass. */
-+ unsigned int min_reg;
-+ /* One greater than the last register to be handled in this pass. */
-+ unsigned int max_reg;
-+ sbitmap *nonnull_local;
-+ sbitmap *nonnull_killed;
-+};
-+\f
-+static void compute_can_copy PARAMS ((void));
-+static char *gmalloc PARAMS ((unsigned int));
-+static char *grealloc PARAMS ((char *, unsigned int));
-+static char *gcse_alloc PARAMS ((unsigned long));
-+static void alloc_gcse_mem PARAMS ((rtx));
-+static void free_gcse_mem PARAMS ((void));
-+static void alloc_reg_set_mem PARAMS ((int));
-+static void free_reg_set_mem PARAMS ((void));
-+static int get_bitmap_width PARAMS ((int, int, int));
-+static void record_one_set PARAMS ((int, rtx));
-+static void record_set_info PARAMS ((rtx, rtx, void *));
-+static void compute_sets PARAMS ((rtx));
-+static void hash_scan_insn PARAMS ((rtx, struct hash_table *, int));
-+static void hash_scan_set PARAMS ((rtx, rtx, struct hash_table *));
-+static void hash_scan_clobber PARAMS ((rtx, rtx, struct hash_table *));
-+static void hash_scan_call PARAMS ((rtx, rtx, struct hash_table *));
-+static int want_to_gcse_p PARAMS ((rtx));
-+static int oprs_unchanged_p PARAMS ((rtx, rtx, int));
-+static int oprs_anticipatable_p PARAMS ((rtx, rtx));
-+static int oprs_available_p PARAMS ((rtx, rtx));
-+static void insert_expr_in_table PARAMS ((rtx, enum machine_mode, rtx,
-+ int, int, struct hash_table *));
-+static void insert_set_in_table PARAMS ((rtx, rtx, struct hash_table *));
-+static unsigned int hash_expr PARAMS ((rtx, enum machine_mode, int *, int));
-+static unsigned int hash_expr_1 PARAMS ((rtx, enum machine_mode, int *));
-+static unsigned int hash_string_1 PARAMS ((const char *));
-+static unsigned int hash_set PARAMS ((int, int));
-+static int expr_equiv_p PARAMS ((rtx, rtx));
-+static void record_last_reg_set_info PARAMS ((rtx, int));
-+static void record_last_mem_set_info PARAMS ((rtx));
-+static void record_last_set_info PARAMS ((rtx, rtx, void *));
-+static void compute_hash_table PARAMS ((struct hash_table *));
-+static void alloc_hash_table PARAMS ((int, struct hash_table *, int));
-+static void free_hash_table PARAMS ((struct hash_table *));
-+static void compute_hash_table_work PARAMS ((struct hash_table *));
-+static void dump_hash_table PARAMS ((FILE *, const char *,
-+ struct hash_table *));
-+static struct expr *lookup_expr PARAMS ((rtx, struct hash_table *));
-+static struct expr *lookup_set PARAMS ((unsigned int, rtx, struct hash_table *));
-+static struct expr *next_set PARAMS ((unsigned int, struct expr *));
-+static void reset_opr_set_tables PARAMS ((void));
-+static int oprs_not_set_p PARAMS ((rtx, rtx));
-+static void mark_call PARAMS ((rtx));
-+static void mark_set PARAMS ((rtx, rtx));
-+static void mark_clobber PARAMS ((rtx, rtx));
-+static void mark_oprs_set PARAMS ((rtx));
-+static void alloc_cprop_mem PARAMS ((int, int));
-+static void free_cprop_mem PARAMS ((void));
-+static void compute_transp PARAMS ((rtx, int, sbitmap *, int));
-+static void compute_transpout PARAMS ((void));
-+static void compute_local_properties PARAMS ((sbitmap *, sbitmap *, sbitmap *,
-+ struct hash_table *));
-+static void compute_cprop_data PARAMS ((void));
-+static void find_used_regs PARAMS ((rtx *, void *));
-+static int try_replace_reg PARAMS ((rtx, rtx, rtx));
-+static struct expr *find_avail_set PARAMS ((int, rtx));
-+static int cprop_jump PARAMS ((basic_block, rtx, rtx, rtx, rtx));
-+static void mems_conflict_for_gcse_p PARAMS ((rtx, rtx, void *));
-+static int load_killed_in_block_p PARAMS ((basic_block, int, rtx, int));
-+static void canon_list_insert PARAMS ((rtx, rtx, void *));
-+static int cprop_insn PARAMS ((rtx, int));
-+static int cprop PARAMS ((int));
-+static int one_cprop_pass PARAMS ((int, int));
-+static bool constprop_register PARAMS ((rtx, rtx, rtx, int));
-+static struct expr *find_bypass_set PARAMS ((int, int));
-+static bool reg_killed_on_edge PARAMS ((rtx, edge));
-+static int bypass_block PARAMS ((basic_block, rtx, rtx));
-+static int bypass_conditional_jumps PARAMS ((void));
-+static void alloc_pre_mem PARAMS ((int, int));
-+static void free_pre_mem PARAMS ((void));
-+static void compute_pre_data PARAMS ((void));
-+static int pre_expr_reaches_here_p PARAMS ((basic_block, struct expr *,
-+ basic_block));
-+static void insert_insn_end_bb PARAMS ((struct expr *, basic_block, int));
-+static void pre_insert_copy_insn PARAMS ((struct expr *, rtx));
-+static void pre_insert_copies PARAMS ((void));
-+static int pre_delete PARAMS ((void));
-+static int pre_gcse PARAMS ((void));
-+static int one_pre_gcse_pass PARAMS ((int));
-+static void add_label_notes PARAMS ((rtx, rtx));
-+static void alloc_code_hoist_mem PARAMS ((int, int));
-+static void free_code_hoist_mem PARAMS ((void));
-+static void compute_code_hoist_vbeinout PARAMS ((void));
-+static void compute_code_hoist_data PARAMS ((void));
-+static int hoist_expr_reaches_here_p PARAMS ((basic_block, int, basic_block,
-+ char *));
-+static void hoist_code PARAMS ((void));
-+static int one_code_hoisting_pass PARAMS ((void));
-+static void alloc_rd_mem PARAMS ((int, int));
-+static void free_rd_mem PARAMS ((void));
-+static void handle_rd_kill_set PARAMS ((rtx, int, basic_block));
-+static void compute_kill_rd PARAMS ((void));
-+static void compute_rd PARAMS ((void));
-+static void alloc_avail_expr_mem PARAMS ((int, int));
-+static void free_avail_expr_mem PARAMS ((void));
-+static void compute_ae_gen PARAMS ((struct hash_table *));
-+static int expr_killed_p PARAMS ((rtx, basic_block));
-+static void compute_ae_kill PARAMS ((sbitmap *, sbitmap *, struct hash_table *));
-+static int expr_reaches_here_p PARAMS ((struct occr *, struct expr *,
-+ basic_block, int));
-+static rtx computing_insn PARAMS ((struct expr *, rtx));
-+static int def_reaches_here_p PARAMS ((rtx, rtx));
-+static int can_disregard_other_sets PARAMS ((struct reg_set **, rtx, int));
-+static int handle_avail_expr PARAMS ((rtx, struct expr *));
-+static int classic_gcse PARAMS ((void));
-+static int one_classic_gcse_pass PARAMS ((int));
-+static void invalidate_nonnull_info PARAMS ((rtx, rtx, void *));
-+static int delete_null_pointer_checks_1 PARAMS ((unsigned int *,
-+ sbitmap *, sbitmap *,
-+ struct null_pointer_info *));
-+static rtx process_insert_insn PARAMS ((struct expr *));
-+static int pre_edge_insert PARAMS ((struct edge_list *, struct expr **));
-+static int expr_reaches_here_p_work PARAMS ((struct occr *, struct expr *,
-+ basic_block, int, char *));
-+static int pre_expr_reaches_here_p_work PARAMS ((basic_block, struct expr *,
-+ basic_block, char *));
-+static struct ls_expr * ldst_entry PARAMS ((rtx));
-+static void free_ldst_entry PARAMS ((struct ls_expr *));
-+static void free_ldst_mems PARAMS ((void));
-+static void print_ldst_list PARAMS ((FILE *));
-+static struct ls_expr * find_rtx_in_ldst PARAMS ((rtx));
-+static int enumerate_ldsts PARAMS ((void));
-+static inline struct ls_expr * first_ls_expr PARAMS ((void));
-+static inline struct ls_expr * next_ls_expr PARAMS ((struct ls_expr *));
-+static int simple_mem PARAMS ((rtx));
-+static void invalidate_any_buried_refs PARAMS ((rtx));
-+static void compute_ld_motion_mems PARAMS ((void));
-+static void trim_ld_motion_mems PARAMS ((void));
-+static void update_ld_motion_stores PARAMS ((struct expr *));
-+static void reg_set_info PARAMS ((rtx, rtx, void *));
-+static int store_ops_ok PARAMS ((rtx, basic_block));
-+static void find_moveable_store PARAMS ((rtx));
-+static int compute_store_table PARAMS ((void));
-+static int load_kills_store PARAMS ((rtx, rtx));
-+static int find_loads PARAMS ((rtx, rtx));
-+static int store_killed_in_insn PARAMS ((rtx, rtx));
-+static int store_killed_after PARAMS ((rtx, rtx, basic_block));
-+static int store_killed_before PARAMS ((rtx, rtx, basic_block));
-+static void build_store_vectors PARAMS ((void));
-+static void insert_insn_start_bb PARAMS ((rtx, basic_block));
-+static int insert_store PARAMS ((struct ls_expr *, edge));
-+static void replace_store_insn PARAMS ((rtx, rtx, basic_block));
-+static void delete_store PARAMS ((struct ls_expr *,
-+ basic_block));
-+static void free_store_memory PARAMS ((void));
-+static void store_motion PARAMS ((void));
-+static void free_insn_expr_list_list PARAMS ((rtx *));
-+static void clear_modify_mem_tables PARAMS ((void));
-+static void free_modify_mem_tables PARAMS ((void));
-+static rtx gcse_emit_move_after PARAMS ((rtx, rtx, rtx));
-+static void local_cprop_find_used_regs PARAMS ((rtx *, void *));
-+static bool do_local_cprop PARAMS ((rtx, rtx, int, rtx*));
-+static bool adjust_libcall_notes PARAMS ((rtx, rtx, rtx, rtx*));
-+static void local_cprop_pass PARAMS ((int));
-+\f
-+/* Entry point for global common subexpression elimination.
-+ F is the first instruction in the function. */
-+
-+int
-+gcse_main (f, file)
-+ rtx f;
-+ FILE *file;
-+{
-+ int changed, pass;
-+ /* Bytes used at start of pass. */
-+ int initial_bytes_used;
-+ /* Maximum number of bytes used by a pass. */
-+ int max_pass_bytes;
-+ /* Point to release obstack data from for each pass. */
-+ char *gcse_obstack_bottom;
-+
-+ /* Insertion of instructions on edges can create new basic blocks; we
-+ need the original basic block count so that we can properly deallocate
-+ arrays sized on the number of basic blocks originally in the cfg. */
-+ int orig_bb_count;
-+ /* We do not construct an accurate cfg in functions which call
-+ setjmp, so just punt to be safe. */
-+ if (current_function_calls_setjmp)
-+ return 0;
-+
-+ /* Assume that we do not need to run jump optimizations after gcse. */
-+ run_jump_opt_after_gcse = 0;
-+
-+ /* For calling dump_foo fns from gdb. */
-+ debug_stderr = stderr;
-+ gcse_file = file;
-+
-+ /* Identify the basic block information for this function, including
-+ successors and predecessors. */
-+ max_gcse_regno = max_reg_num ();
-+
-+ if (file)
-+ dump_flow_info (file);
-+
-+ orig_bb_count = n_basic_blocks;
-+ /* Return if there's nothing to do. */
-+ if (n_basic_blocks <= 1)
-+ return 0;
-+
-+ /* Trying to perform global optimizations on flow graphs which have
-+ a high connectivity will take a long time and is unlikely to be
-+ particularly useful.
-+
-+ In normal circumstances a cfg should have about twice as many edges
-+ as blocks. But we do not want to punish small functions which have
-+ a couple switch statements. So we require a relatively large number
-+ of basic blocks and the ratio of edges to blocks to be high. */
-+ if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
-+ {
-+ if (warn_disabled_optimization)
-+ warning ("GCSE disabled: %d > 1000 basic blocks and %d >= 20 edges/basic block",
-+ n_basic_blocks, n_edges / n_basic_blocks);
-+ return 0;
-+ }
-+
-+ /* If allocating memory for the cprop bitmap would take up too much
-+ storage it's better just to disable the optimization. */
-+ if ((n_basic_blocks
-+ * SBITMAP_SET_SIZE (max_gcse_regno)
-+ * sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY)
-+ {
-+ if (warn_disabled_optimization)
-+ warning ("GCSE disabled: %d basic blocks and %d registers",
-+ n_basic_blocks, max_gcse_regno);
-+
-+ return 0;
-+ }
-+
-+ /* See what modes support reg/reg copy operations. */
-+ if (! can_copy_init_p)
-+ {
-+ compute_can_copy ();
-+ can_copy_init_p = 1;
-+ }
-+
-+ gcc_obstack_init (&gcse_obstack);
-+ bytes_used = 0;
-+
-+ /* We need alias. */
-+ init_alias_analysis ();
-+ /* Record where pseudo-registers are set. This data is kept accurate
-+ during each pass. ??? We could also record hard-reg information here
-+ [since it's unchanging], however it is currently done during hash table
-+ computation.
-+
-+ It may be tempting to compute MEM set information here too, but MEM sets
-+ will be subject to code motion one day and thus we need to compute
-+ information about memory sets when we build the hash tables. */
-+
-+ alloc_reg_set_mem (max_gcse_regno);
-+ compute_sets (f);
-+
-+ pass = 0;
-+ initial_bytes_used = bytes_used;
-+ max_pass_bytes = 0;
-+ gcse_obstack_bottom = gcse_alloc (1);
-+ changed = 1;
-+ while (changed && pass < MAX_GCSE_PASSES)
-+ {
-+ changed = 0;
-+ if (file)
-+ fprintf (file, "GCSE pass %d\n\n", pass + 1);
-+
-+ /* Initialize bytes_used to the space for the pred/succ lists,
-+ and the reg_set_table data. */
-+ bytes_used = initial_bytes_used;
-+
-+ /* Each pass may create new registers, so recalculate each time. */
-+ max_gcse_regno = max_reg_num ();
-+
-+ alloc_gcse_mem (f);
-+
-+ /* Don't allow constant propagation to modify jumps
-+ during this pass. */
-+ changed = one_cprop_pass (pass + 1, 0);
-+
-+ if (optimize_size)
-+ changed |= one_classic_gcse_pass (pass + 1);
-+ else
-+ {
-+ changed |= one_pre_gcse_pass (pass + 1);
-+ /* We may have just created new basic blocks. Release and
-+ recompute various things which are sized on the number of
-+ basic blocks. */
-+ if (changed)
-+ {
-+ free_modify_mem_tables ();
-+ modify_mem_list
-+ = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
-+ canon_modify_mem_list
-+ = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
-+ memset ((char *) modify_mem_list, 0, last_basic_block * sizeof (rtx));
-+ memset ((char *) canon_modify_mem_list, 0, last_basic_block * sizeof (rtx));
-+ orig_bb_count = n_basic_blocks;
-+ }
-+ free_reg_set_mem ();
-+ alloc_reg_set_mem (max_reg_num ());
-+ compute_sets (f);
-+ run_jump_opt_after_gcse = 1;
-+ }
-+
-+ if (max_pass_bytes < bytes_used)
-+ max_pass_bytes = bytes_used;
-+
-+ /* Free up memory, then reallocate for code hoisting. We can
-+ not re-use the existing allocated memory because the tables
-+ will not have info for the insns or registers created by
-+ partial redundancy elimination. */
-+ free_gcse_mem ();
-+
-+ /* It does not make sense to run code hoisting unless we optimizing
-+ for code size -- it rarely makes programs faster, and can make
-+ them bigger if we did partial redundancy elimination (when optimizing
-+ for space, we use a classic gcse algorithm instead of partial
-+ redundancy algorithms). */
-+ if (optimize_size)
-+ {
-+ max_gcse_regno = max_reg_num ();
-+ alloc_gcse_mem (f);
-+ changed |= one_code_hoisting_pass ();
-+ free_gcse_mem ();
-+
-+ if (max_pass_bytes < bytes_used)
-+ max_pass_bytes = bytes_used;
-+ }
-+
-+ if (file)
-+ {
-+ fprintf (file, "\n");
-+ fflush (file);
-+ }
-+
-+ obstack_free (&gcse_obstack, gcse_obstack_bottom);
-+ pass++;
-+ }
-+
-+ /* Do one last pass of copy propagation, including cprop into
-+ conditional jumps. */
-+
-+ max_gcse_regno = max_reg_num ();
-+ alloc_gcse_mem (f);
-+ /* This time, go ahead and allow cprop to alter jumps. */
-+ one_cprop_pass (pass + 1, 1);
-+ free_gcse_mem ();
-+
-+ if (file)
-+ {
-+ fprintf (file, "GCSE of %s: %d basic blocks, ",
-+ current_function_name, n_basic_blocks);
-+ fprintf (file, "%d pass%s, %d bytes\n\n",
-+ pass, pass > 1 ? "es" : "", max_pass_bytes);
-+ }
-+
-+ obstack_free (&gcse_obstack, NULL);
-+ free_reg_set_mem ();
-+ /* We are finished with alias. */
-+ end_alias_analysis ();
-+ allocate_reg_info (max_reg_num (), FALSE, FALSE);
-+
-+ /* Store motion disabled until it is fixed. */
-+ if (0 && !optimize_size && flag_gcse_sm)
-+ store_motion ();
-+ /* Record where pseudo-registers are set. */
-+ return run_jump_opt_after_gcse;
-+}
-+\f
-+/* Misc. utilities. */
-+
-+/* Compute which modes support reg/reg copy operations. */
-+
-+static void
-+compute_can_copy ()
-+{
-+ int i;
-+#ifndef AVOID_CCMODE_COPIES
-+ rtx reg, insn;
-+#endif
-+ memset (can_copy_p, 0, NUM_MACHINE_MODES);
-+
-+ start_sequence ();
-+ for (i = 0; i < NUM_MACHINE_MODES; i++)
-+ if (GET_MODE_CLASS (i) == MODE_CC)
-+ {
-+#ifdef AVOID_CCMODE_COPIES
-+ can_copy_p[i] = 0;
-+#else
-+ reg = gen_rtx_REG ((enum machine_mode) i, LAST_VIRTUAL_REGISTER + 1);
-+ insn = emit_insn (gen_rtx_SET (VOIDmode, reg, reg));
-+ if (recog (PATTERN (insn), insn, NULL) >= 0)
-+ can_copy_p[i] = 1;
-+#endif
-+ }
-+ else
-+ can_copy_p[i] = 1;
-+
-+ end_sequence ();
-+}
-+\f
-+/* Cover function to xmalloc to record bytes allocated. */
-+
-+static char *
-+gmalloc (size)
-+ unsigned int size;
-+{
-+ bytes_used += size;
-+ return xmalloc (size);
-+}
-+
-+/* Cover function to xrealloc.
-+ We don't record the additional size since we don't know it.
-+ It won't affect memory usage stats much anyway. */
-+
-+static char *
-+grealloc (ptr, size)
-+ char *ptr;
-+ unsigned int size;
-+{
-+ return xrealloc (ptr, size);
-+}
-+
-+/* Cover function to obstack_alloc. */
-+
-+static char *
-+gcse_alloc (size)
-+ unsigned long size;
-+{
-+ bytes_used += size;
-+ return (char *) obstack_alloc (&gcse_obstack, size);
-+}
-+
-+/* Allocate memory for the cuid mapping array,
-+ and reg/memory set tracking tables.
-+
-+ This is called at the start of each pass. */
-+
-+static void
-+alloc_gcse_mem (f)
-+ rtx f;
-+{
-+ int i, n;
-+ rtx insn;
-+
-+ /* Find the largest UID and create a mapping from UIDs to CUIDs.
-+ CUIDs are like UIDs except they increase monotonically, have no gaps,
-+ and only apply to real insns. */
-+
-+ max_uid = get_max_uid ();
-+ n = (max_uid + 1) * sizeof (int);
-+ uid_cuid = (int *) gmalloc (n);
-+ memset ((char *) uid_cuid, 0, n);
-+ for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
-+ {
-+ if (INSN_P (insn))
-+ uid_cuid[INSN_UID (insn)] = i++;
-+ else
-+ uid_cuid[INSN_UID (insn)] = i;
-+ }
-+
-+ /* Create a table mapping cuids to insns. */
-+
-+ max_cuid = i;
-+ n = (max_cuid + 1) * sizeof (rtx);
-+ cuid_insn = (rtx *) gmalloc (n);
-+ memset ((char *) cuid_insn, 0, n);
-+ for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
-+ if (INSN_P (insn))
-+ CUID_INSN (i++) = insn;
-+
-+ /* Allocate vars to track sets of regs. */
-+ reg_set_bitmap = BITMAP_XMALLOC ();
-+
-+ /* Allocate vars to track sets of regs, memory per block. */
-+ reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (last_basic_block,
-+ max_gcse_regno);
-+ /* Allocate array to keep a list of insns which modify memory in each
-+ basic block. */
-+ modify_mem_list = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
-+ canon_modify_mem_list = (rtx *) gmalloc (last_basic_block * sizeof (rtx));
-+ memset ((char *) modify_mem_list, 0, last_basic_block * sizeof (rtx));
-+ memset ((char *) canon_modify_mem_list, 0, last_basic_block * sizeof (rtx));
-+ modify_mem_list_set = BITMAP_XMALLOC ();
-+ canon_modify_mem_list_set = BITMAP_XMALLOC ();
-+}
-+
-+/* Free memory allocated by alloc_gcse_mem. */
-+
-+static void
-+free_gcse_mem ()
-+{
-+ free (uid_cuid);
-+ free (cuid_insn);
-+
-+ BITMAP_XFREE (reg_set_bitmap);
-+
-+ sbitmap_vector_free (reg_set_in_block);
-+ free_modify_mem_tables ();
-+ BITMAP_XFREE (modify_mem_list_set);
-+ BITMAP_XFREE (canon_modify_mem_list_set);
-+}
-+
-+/* Many of the global optimization algorithms work by solving dataflow
-+ equations for various expressions. Initially, some local value is
-+ computed for each expression in each block. Then, the values across the
-+ various blocks are combined (by following flow graph edges) to arrive at
-+ global values. Conceptually, each set of equations is independent. We
-+ may therefore solve all the equations in parallel, solve them one at a
-+ time, or pick any intermediate approach.
-+
-+ When you're going to need N two-dimensional bitmaps, each X (say, the
-+ number of blocks) by Y (say, the number of expressions), call this
-+ function. It's not important what X and Y represent; only that Y
-+ correspond to the things that can be done in parallel. This function will
-+ return an appropriate chunking factor C; you should solve C sets of
-+ equations in parallel. By going through this function, we can easily
-+ trade space against time; by solving fewer equations in parallel we use
-+ less space. */
-+
-+static int
-+get_bitmap_width (n, x, y)
-+ int n;
-+ int x;
-+ int y;
-+{
-+ /* It's not really worth figuring out *exactly* how much memory will
-+ be used by a particular choice. The important thing is to get
-+ something approximately right. */
-+ size_t max_bitmap_memory = 10 * 1024 * 1024;
-+
-+ /* The number of bytes we'd use for a single column of minimum
-+ width. */
-+ size_t column_size = n * x * sizeof (SBITMAP_ELT_TYPE);
-+
-+ /* Often, it's reasonable just to solve all the equations in
-+ parallel. */
-+ if (column_size * SBITMAP_SET_SIZE (y) <= max_bitmap_memory)
-+ return y;
-+
-+ /* Otherwise, pick the largest width we can, without going over the
-+ limit. */
-+ return SBITMAP_ELT_BITS * ((max_bitmap_memory + column_size - 1)
-+ / column_size);
-+}
-+\f
-+/* Compute the local properties of each recorded expression.
-+
-+ Local properties are those that are defined by the block, irrespective of
-+ other blocks.
-+
-+ An expression is transparent in a block if its operands are not modified
-+ in the block.
-+
-+ An expression is computed (locally available) in a block if it is computed
-+ at least once and expression would contain the same value if the
-+ computation was moved to the end of the block.
-+
-+ An expression is locally anticipatable in a block if it is computed at
-+ least once and expression would contain the same value if the computation
-+ was moved to the beginning of the block.
-+
-+ We call this routine for cprop, pre and code hoisting. They all compute
-+ basically the same information and thus can easily share this code.
-+
-+ TRANSP, COMP, and ANTLOC are destination sbitmaps for recording local
-+ properties. If NULL, then it is not necessary to compute or record that
-+ particular property.
-+
-+ TABLE controls which hash table to look at. If it is set hash table,
-+ additionally, TRANSP is computed as ~TRANSP, since this is really cprop's
-+ ABSALTERED. */
-+
-+static void
-+compute_local_properties (transp, comp, antloc, table)
-+ sbitmap *transp;
-+ sbitmap *comp;
-+ sbitmap *antloc;
-+ struct hash_table *table;
-+{
-+ unsigned int i;
-+
-+ /* Initialize any bitmaps that were passed in. */
-+ if (transp)
-+ {
-+ if (table->set_p)
-+ sbitmap_vector_zero (transp, last_basic_block);
-+ else
-+ sbitmap_vector_ones (transp, last_basic_block);
-+ }
-+
-+ if (comp)
-+ sbitmap_vector_zero (comp, last_basic_block);
-+ if (antloc)
-+ sbitmap_vector_zero (antloc, last_basic_block);
-+
-+ for (i = 0; i < table->size; i++)
-+ {
-+ struct expr *expr;
-+
-+ for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
-+ {
-+ int indx = expr->bitmap_index;
-+ struct occr *occr;
-+
-+ /* The expression is transparent in this block if it is not killed.
-+ We start by assuming all are transparent [none are killed], and
-+ then reset the bits for those that are. */
-+ if (transp)
-+ compute_transp (expr->expr, indx, transp, table->set_p);
-+
-+ /* The occurrences recorded in antic_occr are exactly those that
-+ we want to set to nonzero in ANTLOC. */
-+ if (antloc)
-+ for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
-+ {
-+ SET_BIT (antloc[BLOCK_NUM (occr->insn)], indx);
-+
-+ /* While we're scanning the table, this is a good place to
-+ initialize this. */
-+ occr->deleted_p = 0;
-+ }
-+
-+ /* The occurrences recorded in avail_occr are exactly those that
-+ we want to set to nonzero in COMP. */
-+ if (comp)
-+ for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
-+ {
-+ SET_BIT (comp[BLOCK_NUM (occr->insn)], indx);
-+
-+ /* While we're scanning the table, this is a good place to
-+ initialize this. */
-+ occr->copied_p = 0;
-+ }
-+
-+ /* While we're scanning the table, this is a good place to
-+ initialize this. */
-+ expr->reaching_reg = 0;
-+ }
-+ }
-+}
-+\f
-+/* Register set information.
-+
-+ `reg_set_table' records where each register is set or otherwise
-+ modified. */
-+
-+static struct obstack reg_set_obstack;
-+
-+static void
-+alloc_reg_set_mem (n_regs)
-+ int n_regs;
-+{
-+ unsigned int n;
-+
-+ reg_set_table_size = n_regs + REG_SET_TABLE_SLOP;
-+ n = reg_set_table_size * sizeof (struct reg_set *);
-+ reg_set_table = (struct reg_set **) gmalloc (n);
-+ memset ((char *) reg_set_table, 0, n);
-+
-+ gcc_obstack_init (®_set_obstack);
-+}
-+
-+static void
-+free_reg_set_mem ()
-+{
-+ free (reg_set_table);
-+ obstack_free (®_set_obstack, NULL);
-+}
-+
-+/* Record REGNO in the reg_set table. */
-+
-+static void
-+record_one_set (regno, insn)
-+ int regno;
-+ rtx insn;
-+{
-+ /* Allocate a new reg_set element and link it onto the list. */
-+ struct reg_set *new_reg_info;
-+
-+ /* If the table isn't big enough, enlarge it. */
-+ if (regno >= reg_set_table_size)
-+ {
-+ int new_size = regno + REG_SET_TABLE_SLOP;
-+
-+ reg_set_table
-+ = (struct reg_set **) grealloc ((char *) reg_set_table,
-+ new_size * sizeof (struct reg_set *));
-+ memset ((char *) (reg_set_table + reg_set_table_size), 0,
-+ (new_size - reg_set_table_size) * sizeof (struct reg_set *));
-+ reg_set_table_size = new_size;
-+ }
-+
-+ new_reg_info = (struct reg_set *) obstack_alloc (®_set_obstack,
-+ sizeof (struct reg_set));
-+ bytes_used += sizeof (struct reg_set);
-+ new_reg_info->insn = insn;
-+ new_reg_info->next = reg_set_table[regno];
-+ reg_set_table[regno] = new_reg_info;
-+}
-+
-+/* Called from compute_sets via note_stores to handle one SET or CLOBBER in
-+ an insn. The DATA is really the instruction in which the SET is
-+ occurring. */
-+
-+static void
-+record_set_info (dest, setter, data)
-+ rtx dest, setter ATTRIBUTE_UNUSED;
-+ void *data;
-+{
-+ rtx record_set_insn = (rtx) data;
-+
-+ if (GET_CODE (dest) == REG && REGNO (dest) >= FIRST_PSEUDO_REGISTER)
-+ record_one_set (REGNO (dest), record_set_insn);
-+}
-+
-+/* Scan the function and record each set of each pseudo-register.
-+
-+ This is called once, at the start of the gcse pass. See the comments for
-+ `reg_set_table' for further documenation. */
-+
-+static void
-+compute_sets (f)
-+ rtx f;
-+{
-+ rtx insn;
-+
-+ for (insn = f; insn != 0; insn = NEXT_INSN (insn))
-+ if (INSN_P (insn))
-+ note_stores (PATTERN (insn), record_set_info, insn);
-+}
-+\f
-+/* Hash table support. */
-+
-+struct reg_avail_info
-+{
-+ basic_block last_bb;
-+ int first_set;
-+ int last_set;
-+};
-+
-+static struct reg_avail_info *reg_avail_info;
-+static basic_block current_bb;
-+
-+
-+/* See whether X, the source of a set, is something we want to consider for
-+ GCSE. */
-+
-+static GTY(()) rtx test_insn;
-+static int
-+want_to_gcse_p (x)
-+ rtx x;
-+{
-+ int num_clobbers = 0;
-+ int icode;
-+
-+ switch (GET_CODE (x))
-+ {
-+ case REG:
-+ case SUBREG:
-+ case CONST_INT:
-+ case CONST_DOUBLE:
-+ case CONST_VECTOR:
-+ case CALL:
-+ return 0;
-+
-+ default:
-+ break;
-+ }
-+
-+ /* If this is a valid operand, we are OK. If it's VOIDmode, we aren't. */
-+ if (general_operand (x, GET_MODE (x)))
-+ return 1;
-+ else if (GET_MODE (x) == VOIDmode)
-+ return 0;
-+
-+ /* Otherwise, check if we can make a valid insn from it. First initialize
-+ our test insn if we haven't already. */
-+ if (test_insn == 0)
-+ {
-+ test_insn
-+ = make_insn_raw (gen_rtx_SET (VOIDmode,
-+ gen_rtx_REG (word_mode,
-+ FIRST_PSEUDO_REGISTER * 2),
-+ const0_rtx));
-+ NEXT_INSN (test_insn) = PREV_INSN (test_insn) = 0;
-+ }
-+
-+ /* Now make an insn like the one we would make when GCSE'ing and see if
-+ valid. */
-+ PUT_MODE (SET_DEST (PATTERN (test_insn)), GET_MODE (x));
-+ SET_SRC (PATTERN (test_insn)) = x;
-+ return ((icode = recog (PATTERN (test_insn), test_insn, &num_clobbers)) >= 0
-+ && (num_clobbers == 0 || ! added_clobbers_hard_reg_p (icode)));
-+}
-+
-+/* Return nonzero if the operands of expression X are unchanged from the
-+ start of INSN's basic block up to but not including INSN (if AVAIL_P == 0),
-+ or from INSN to the end of INSN's basic block (if AVAIL_P != 0). */
-+
-+static int
-+oprs_unchanged_p (x, insn, avail_p)
-+ rtx x, insn;
-+ int avail_p;
-+{
-+ int i, j;
-+ enum rtx_code code;
-+ const char *fmt;
-+
-+ if (x == 0)
-+ return 1;
-+
-+ code = GET_CODE (x);
-+ switch (code)
-+ {
-+ case REG:
-+ {
-+ struct reg_avail_info *info = ®_avail_info[REGNO (x)];
-+
-+ if (info->last_bb != current_bb)
-+ return 1;
-+ if (avail_p)
-+ return info->last_set < INSN_CUID (insn);
-+ else
-+ return info->first_set >= INSN_CUID (insn);
-+ }
-+
-+ case MEM:
-+ if (load_killed_in_block_p (current_bb, INSN_CUID (insn),
-+ x, avail_p))
-+ return 0;
-+ else
-+ return oprs_unchanged_p (XEXP (x, 0), insn, avail_p);
-+
-+ case PRE_DEC:
-+ case PRE_INC:
-+ case POST_DEC:
-+ case POST_INC:
-+ case PRE_MODIFY:
-+ case POST_MODIFY:
-+ return 0;
-+
-+ case PC:
-+ case CC0: /*FIXME*/
-+ case CONST:
-+ case CONST_INT:
-+ case CONST_DOUBLE:
-+ case CONST_VECTOR:
-+ case SYMBOL_REF:
-+ case LABEL_REF:
-+ case ADDR_VEC:
-+ case ADDR_DIFF_VEC:
-+ return 1;
-+
-+ default:
-+ break;
-+ }
-+
-+ for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ {
-+ /* If we are about to do the last recursive call needed at this
-+ level, change it into iteration. This function is called enough
-+ to be worth it. */
-+ if (i == 0)
-+ return oprs_unchanged_p (XEXP (x, i), insn, avail_p);
-+
-+ else if (! oprs_unchanged_p (XEXP (x, i), insn, avail_p))
-+ return 0;
-+ }
-+ else if (fmt[i] == 'E')
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ if (! oprs_unchanged_p (XVECEXP (x, i, j), insn, avail_p))
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+/* Used for communication between mems_conflict_for_gcse_p and
-+ load_killed_in_block_p. Nonzero if mems_conflict_for_gcse_p finds a
-+ conflict between two memory references. */
-+static int gcse_mems_conflict_p;
-+
-+/* Used for communication between mems_conflict_for_gcse_p and
-+ load_killed_in_block_p. A memory reference for a load instruction,
-+ mems_conflict_for_gcse_p will see if a memory store conflicts with
-+ this memory load. */
-+static rtx gcse_mem_operand;
-+
-+/* DEST is the output of an instruction. If it is a memory reference, and
-+ possibly conflicts with the load found in gcse_mem_operand, then set
-+ gcse_mems_conflict_p to a nonzero value. */
-+
-+static void
-+mems_conflict_for_gcse_p (dest, setter, data)
-+ rtx dest, setter ATTRIBUTE_UNUSED;
-+ void *data ATTRIBUTE_UNUSED;
-+{
-+ while (GET_CODE (dest) == SUBREG
-+ || GET_CODE (dest) == ZERO_EXTRACT
-+ || GET_CODE (dest) == SIGN_EXTRACT
-+ || GET_CODE (dest) == STRICT_LOW_PART)
-+ dest = XEXP (dest, 0);
-+
-+ /* If DEST is not a MEM, then it will not conflict with the load. Note
-+ that function calls are assumed to clobber memory, but are handled
-+ elsewhere. */
-+ if (GET_CODE (dest) != MEM)
-+ return;
-+
-+ /* If we are setting a MEM in our list of specially recognized MEMs,
-+ don't mark as killed this time. */
-+
-+ if (dest == gcse_mem_operand && pre_ldst_mems != NULL)
-+ {
-+ if (!find_rtx_in_ldst (dest))
-+ gcse_mems_conflict_p = 1;
-+ return;
-+ }
-+
-+ if (true_dependence (dest, GET_MODE (dest), gcse_mem_operand,
-+ rtx_addr_varies_p))
-+ gcse_mems_conflict_p = 1;
-+}
-+
-+/* Return nonzero if the expression in X (a memory reference) is killed
-+ in block BB before or after the insn with the CUID in UID_LIMIT.
-+ AVAIL_P is nonzero for kills after UID_LIMIT, and zero for kills
-+ before UID_LIMIT.
-+
-+ To check the entire block, set UID_LIMIT to max_uid + 1 and
-+ AVAIL_P to 0. */
-+
-+static int
-+load_killed_in_block_p (bb, uid_limit, x, avail_p)
-+ basic_block bb;
-+ int uid_limit;
-+ rtx x;
-+ int avail_p;
-+{
-+ rtx list_entry = modify_mem_list[bb->index];
-+ while (list_entry)
-+ {
-+ rtx setter;
-+ /* Ignore entries in the list that do not apply. */
-+ if ((avail_p
-+ && INSN_CUID (XEXP (list_entry, 0)) < uid_limit)
-+ || (! avail_p
-+ && INSN_CUID (XEXP (list_entry, 0)) > uid_limit))
-+ {
-+ list_entry = XEXP (list_entry, 1);
-+ continue;
-+ }
-+
-+ setter = XEXP (list_entry, 0);
-+
-+ /* If SETTER is a call everything is clobbered. Note that calls
-+ to pure functions are never put on the list, so we need not
-+ worry about them. */
-+ if (GET_CODE (setter) == CALL_INSN)
-+ return 1;
-+
-+ /* SETTER must be an INSN of some kind that sets memory. Call
-+ note_stores to examine each hunk of memory that is modified.
-+
-+ The note_stores interface is pretty limited, so we have to
-+ communicate via global variables. Yuk. */
-+ gcse_mem_operand = x;
-+ gcse_mems_conflict_p = 0;
-+ note_stores (PATTERN (setter), mems_conflict_for_gcse_p, NULL);
-+ if (gcse_mems_conflict_p)
-+ return 1;
-+ list_entry = XEXP (list_entry, 1);
-+ }
-+ return 0;
-+}
-+
-+/* Return nonzero if the operands of expression X are unchanged from
-+ the start of INSN's basic block up to but not including INSN. */
-+
-+static int
-+oprs_anticipatable_p (x, insn)
-+ rtx x, insn;
-+{
-+ return oprs_unchanged_p (x, insn, 0);
-+}
-+
-+/* Return nonzero if the operands of expression X are unchanged from
-+ INSN to the end of INSN's basic block. */
-+
-+static int
-+oprs_available_p (x, insn)
-+ rtx x, insn;
-+{
-+ return oprs_unchanged_p (x, insn, 1);
-+}
-+
-+/* Hash expression X.
-+
-+ MODE is only used if X is a CONST_INT. DO_NOT_RECORD_P is a boolean
-+ indicating if a volatile operand is found or if the expression contains
-+ something we don't want to insert in the table.
-+
-+ ??? One might want to merge this with canon_hash. Later. */
-+
-+static unsigned int
-+hash_expr (x, mode, do_not_record_p, hash_table_size)
-+ rtx x;
-+ enum machine_mode mode;
-+ int *do_not_record_p;
-+ int hash_table_size;
-+{
-+ unsigned int hash;
-+
-+ *do_not_record_p = 0;
-+
-+ hash = hash_expr_1 (x, mode, do_not_record_p);
-+ return hash % hash_table_size;
-+}
-+
-+/* Hash a string. Just add its bytes up. */
-+
-+static inline unsigned
-+hash_string_1 (ps)
-+ const char *ps;
-+{
-+ unsigned hash = 0;
-+ const unsigned char *p = (const unsigned char *) ps;
-+
-+ if (p)
-+ while (*p)
-+ hash += *p++;
-+
-+ return hash;
-+}
-+
-+/* Subroutine of hash_expr to do the actual work. */
-+
-+static unsigned int
-+hash_expr_1 (x, mode, do_not_record_p)
-+ rtx x;
-+ enum machine_mode mode;
-+ int *do_not_record_p;
-+{
-+ int i, j;
-+ unsigned hash = 0;
-+ enum rtx_code code;
-+ const char *fmt;
-+
-+ /* Used to turn recursion into iteration. We can't rely on GCC's
-+ tail-recursion eliminatio since we need to keep accumulating values
-+ in HASH. */
-+
-+ if (x == 0)
-+ return hash;
-+
-+ repeat:
-+ code = GET_CODE (x);
-+ switch (code)
-+ {
-+ case REG:
-+ hash += ((unsigned int) REG << 7) + REGNO (x);
-+ return hash;
-+
-+ case CONST_INT:
-+ hash += (((unsigned int) CONST_INT << 7) + (unsigned int) mode
-+ + (unsigned int) INTVAL (x));
-+ return hash;
-+
-+ case CONST_DOUBLE:
-+ /* This is like the general case, except that it only counts
-+ the integers representing the constant. */
-+ hash += (unsigned int) code + (unsigned int) GET_MODE (x);
-+ if (GET_MODE (x) != VOIDmode)
-+ for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++)
-+ hash += (unsigned int) XWINT (x, i);
-+ else
-+ hash += ((unsigned int) CONST_DOUBLE_LOW (x)
-+ + (unsigned int) CONST_DOUBLE_HIGH (x));
-+ return hash;
-+
-+ case CONST_VECTOR:
-+ {
-+ int units;
-+ rtx elt;
-+
-+ units = CONST_VECTOR_NUNITS (x);
-+
-+ for (i = 0; i < units; ++i)
-+ {
-+ elt = CONST_VECTOR_ELT (x, i);
-+ hash += hash_expr_1 (elt, GET_MODE (elt), do_not_record_p);
-+ }
-+
-+ return hash;
-+ }
-+
-+ /* Assume there is only one rtx object for any given label. */
-+ case LABEL_REF:
-+ /* We don't hash on the address of the CODE_LABEL to avoid bootstrap
-+ differences and differences between each stage's debugging dumps. */
-+ hash += (((unsigned int) LABEL_REF << 7)
-+ + CODE_LABEL_NUMBER (XEXP (x, 0)));
-+ return hash;
-+
-+ case SYMBOL_REF:
-+ {
-+ /* Don't hash on the symbol's address to avoid bootstrap differences.
-+ Different hash values may cause expressions to be recorded in
-+ different orders and thus different registers to be used in the
-+ final assembler. This also avoids differences in the dump files
-+ between various stages. */
-+ unsigned int h = 0;
-+ const unsigned char *p = (const unsigned char *) XSTR (x, 0);
-+
-+ while (*p)
-+ h += (h << 7) + *p++; /* ??? revisit */
-+
-+ hash += ((unsigned int) SYMBOL_REF << 7) + h;
-+ return hash;
-+ }
-+
-+ case MEM:
-+ if (MEM_VOLATILE_P (x))
-+ {
-+ *do_not_record_p = 1;
-+ return 0;
-+ }
-+
-+ hash += (unsigned int) MEM;
-+ /* We used alias set for hashing, but this is not good, since the alias
-+ set may differ in -fprofile-arcs and -fbranch-probabilities compilation
-+ causing the profiles to fail to match. */
-+ x = XEXP (x, 0);
-+ goto repeat;
-+
-+ case PRE_DEC:
-+ case PRE_INC:
-+ case POST_DEC:
-+ case POST_INC:
-+ case PC:
-+ case CC0:
-+ case CALL:
-+ case UNSPEC_VOLATILE:
-+ *do_not_record_p = 1;
-+ return 0;
-+
-+ case ASM_OPERANDS:
-+ if (MEM_VOLATILE_P (x))
-+ {
-+ *do_not_record_p = 1;
-+ return 0;
-+ }
-+ else
-+ {
-+ /* We don't want to take the filename and line into account. */
-+ hash += (unsigned) code + (unsigned) GET_MODE (x)
-+ + hash_string_1 (ASM_OPERANDS_TEMPLATE (x))
-+ + hash_string_1 (ASM_OPERANDS_OUTPUT_CONSTRAINT (x))
-+ + (unsigned) ASM_OPERANDS_OUTPUT_IDX (x);
-+
-+ if (ASM_OPERANDS_INPUT_LENGTH (x))
-+ {
-+ for (i = 1; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
-+ {
-+ hash += (hash_expr_1 (ASM_OPERANDS_INPUT (x, i),
-+ GET_MODE (ASM_OPERANDS_INPUT (x, i)),
-+ do_not_record_p)
-+ + hash_string_1 (ASM_OPERANDS_INPUT_CONSTRAINT
-+ (x, i)));
-+ }
-+
-+ hash += hash_string_1 (ASM_OPERANDS_INPUT_CONSTRAINT (x, 0));
-+ x = ASM_OPERANDS_INPUT (x, 0);
-+ mode = GET_MODE (x);
-+ goto repeat;
-+ }
-+ return hash;
-+ }
-+
-+ default:
-+ break;
-+ }
-+
-+ hash += (unsigned) code + (unsigned) GET_MODE (x);
-+ for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ {
-+ /* If we are about to do the last recursive call
-+ needed at this level, change it into iteration.
-+ This function is called enough to be worth it. */
-+ if (i == 0)
-+ {
-+ x = XEXP (x, i);
-+ goto repeat;
-+ }
-+
-+ hash += hash_expr_1 (XEXP (x, i), 0, do_not_record_p);
-+ if (*do_not_record_p)
-+ return 0;
-+ }
-+
-+ else if (fmt[i] == 'E')
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ {
-+ hash += hash_expr_1 (XVECEXP (x, i, j), 0, do_not_record_p);
-+ if (*do_not_record_p)
-+ return 0;
-+ }
-+
-+ else if (fmt[i] == 's')
-+ hash += hash_string_1 (XSTR (x, i));
-+ else if (fmt[i] == 'i')
-+ hash += (unsigned int) XINT (x, i);
-+ else
-+ abort ();
-+ }
-+
-+ return hash;
-+}
-+
-+/* Hash a set of register REGNO.
-+
-+ Sets are hashed on the register that is set. This simplifies the PRE copy
-+ propagation code.
-+
-+ ??? May need to make things more elaborate. Later, as necessary. */
-+
-+static unsigned int
-+hash_set (regno, hash_table_size)
-+ int regno;
-+ int hash_table_size;
-+{
-+ unsigned int hash;
-+
-+ hash = regno;
-+ return hash % hash_table_size;
-+}
-+
-+/* Return nonzero if exp1 is equivalent to exp2.
-+ ??? Borrowed from cse.c. Might want to remerge with cse.c. Later. */
-+
-+static int
-+expr_equiv_p (x, y)
-+ rtx x, y;
-+{
-+ int i, j;
-+ enum rtx_code code;
-+ const char *fmt;
-+
-+ if (x == y)
-+ return 1;
-+
-+ if (x == 0 || y == 0)
-+ return x == y;
-+
-+ code = GET_CODE (x);
-+ if (code != GET_CODE (y))
-+ return 0;
-+
-+ /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */
-+ if (GET_MODE (x) != GET_MODE (y))
-+ return 0;
-+
-+ switch (code)
-+ {
-+ case PC:
-+ case CC0:
-+ return x == y;
-+
-+ case CONST_INT:
-+ return INTVAL (x) == INTVAL (y);
-+
-+ case LABEL_REF:
-+ return XEXP (x, 0) == XEXP (y, 0);
-+
-+ case SYMBOL_REF:
-+ return XSTR (x, 0) == XSTR (y, 0);
-+
-+ case REG:
-+ return REGNO (x) == REGNO (y);
-+
-+ case MEM:
-+ /* Can't merge two expressions in different alias sets, since we can
-+ decide that the expression is transparent in a block when it isn't,
-+ due to it being set with the different alias set. */
-+ if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
-+ return 0;
-+ break;
-+
-+ /* For commutative operations, check both orders. */
-+ case PLUS:
-+ case MULT:
-+ case AND:
-+ case IOR:
-+ case XOR:
-+ case NE:
-+ case EQ:
-+ return ((expr_equiv_p (XEXP (x, 0), XEXP (y, 0))
-+ && expr_equiv_p (XEXP (x, 1), XEXP (y, 1)))
-+ || (expr_equiv_p (XEXP (x, 0), XEXP (y, 1))
-+ && expr_equiv_p (XEXP (x, 1), XEXP (y, 0))));
-+
-+ case ASM_OPERANDS:
-+ /* We don't use the generic code below because we want to
-+ disregard filename and line numbers. */
-+
-+ /* A volatile asm isn't equivalent to any other. */
-+ if (MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
-+ return 0;
-+
-+ if (GET_MODE (x) != GET_MODE (y)
-+ || strcmp (ASM_OPERANDS_TEMPLATE (x), ASM_OPERANDS_TEMPLATE (y))
-+ || strcmp (ASM_OPERANDS_OUTPUT_CONSTRAINT (x),
-+ ASM_OPERANDS_OUTPUT_CONSTRAINT (y))
-+ || ASM_OPERANDS_OUTPUT_IDX (x) != ASM_OPERANDS_OUTPUT_IDX (y)
-+ || ASM_OPERANDS_INPUT_LENGTH (x) != ASM_OPERANDS_INPUT_LENGTH (y))
-+ return 0;
-+
-+ if (ASM_OPERANDS_INPUT_LENGTH (x))
-+ {
-+ for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
-+ if (! expr_equiv_p (ASM_OPERANDS_INPUT (x, i),
-+ ASM_OPERANDS_INPUT (y, i))
-+ || strcmp (ASM_OPERANDS_INPUT_CONSTRAINT (x, i),
-+ ASM_OPERANDS_INPUT_CONSTRAINT (y, i)))
-+ return 0;
-+ }
-+
-+ return 1;
-+
-+ default:
-+ break;
-+ }
-+
-+ /* Compare the elements. If any pair of corresponding elements
-+ fail to match, return 0 for the whole thing. */
-+
-+ fmt = GET_RTX_FORMAT (code);
-+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-+ {
-+ switch (fmt[i])
-+ {
-+ case 'e':
-+ if (! expr_equiv_p (XEXP (x, i), XEXP (y, i)))
-+ return 0;
-+ break;
-+
-+ case 'E':
-+ if (XVECLEN (x, i) != XVECLEN (y, i))
-+ return 0;
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ if (! expr_equiv_p (XVECEXP (x, i, j), XVECEXP (y, i, j)))
-+ return 0;
-+ break;
-+
-+ case 's':
-+ if (strcmp (XSTR (x, i), XSTR (y, i)))
-+ return 0;
-+ break;
-+
-+ case 'i':
-+ if (XINT (x, i) != XINT (y, i))
-+ return 0;
-+ break;
-+
-+ case 'w':
-+ if (XWINT (x, i) != XWINT (y, i))
-+ return 0;
-+ break;
-+
-+ case '0':
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+/* Insert expression X in INSN in the hash TABLE.
-+ If it is already present, record it as the last occurrence in INSN's
-+ basic block.
-+
-+ MODE is the mode of the value X is being stored into.
-+ It is only used if X is a CONST_INT.
-+
-+ ANTIC_P is nonzero if X is an anticipatable expression.
-+ AVAIL_P is nonzero if X is an available expression. */
-+
-+static void
-+insert_expr_in_table (x, mode, insn, antic_p, avail_p, table)
-+ rtx x;
-+ enum machine_mode mode;
-+ rtx insn;
-+ int antic_p, avail_p;
-+ struct hash_table *table;
-+{
-+ int found, do_not_record_p;
-+ unsigned int hash;
-+ struct expr *cur_expr, *last_expr = NULL;
-+ struct occr *antic_occr, *avail_occr;
-+ struct occr *last_occr = NULL;
-+
-+ hash = hash_expr (x, mode, &do_not_record_p, table->size);
-+
-+ /* Do not insert expression in table if it contains volatile operands,
-+ or if hash_expr determines the expression is something we don't want
-+ to or can't handle. */
-+ if (do_not_record_p)
-+ return;
-+
-+ cur_expr = table->table[hash];
-+ found = 0;
-+
-+ while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
-+ {
-+ /* If the expression isn't found, save a pointer to the end of
-+ the list. */
-+ last_expr = cur_expr;
-+ cur_expr = cur_expr->next_same_hash;
-+ }
-+
-+ if (! found)
-+ {
-+ cur_expr = (struct expr *) gcse_alloc (sizeof (struct expr));
-+ bytes_used += sizeof (struct expr);
-+ if (table->table[hash] == NULL)
-+ /* This is the first pattern that hashed to this index. */
-+ table->table[hash] = cur_expr;
-+ else
-+ /* Add EXPR to end of this hash chain. */
-+ last_expr->next_same_hash = cur_expr;
-+
-+ /* Set the fields of the expr element. */
-+ cur_expr->expr = x;
-+ cur_expr->bitmap_index = table->n_elems++;
-+ cur_expr->next_same_hash = NULL;
-+ cur_expr->antic_occr = NULL;
-+ cur_expr->avail_occr = NULL;
-+ }
-+
-+ /* Now record the occurrence(s). */
-+ if (antic_p)
-+ {
-+ antic_occr = cur_expr->antic_occr;
-+
-+ /* Search for another occurrence in the same basic block. */
-+ while (antic_occr && BLOCK_NUM (antic_occr->insn) != BLOCK_NUM (insn))
-+ {
-+ /* If an occurrence isn't found, save a pointer to the end of
-+ the list. */
-+ last_occr = antic_occr;
-+ antic_occr = antic_occr->next;
-+ }
-+
-+ if (antic_occr)
-+ /* Found another instance of the expression in the same basic block.
-+ Prefer the currently recorded one. We want the first one in the
-+ block and the block is scanned from start to end. */
-+ ; /* nothing to do */
-+ else
-+ {
-+ /* First occurrence of this expression in this basic block. */
-+ antic_occr = (struct occr *) gcse_alloc (sizeof (struct occr));
-+ bytes_used += sizeof (struct occr);
-+ /* First occurrence of this expression in any block? */
-+ if (cur_expr->antic_occr == NULL)
-+ cur_expr->antic_occr = antic_occr;
-+ else
-+ last_occr->next = antic_occr;
-+
-+ antic_occr->insn = insn;
-+ antic_occr->next = NULL;
-+ }
-+ }
-+
-+ if (avail_p)
-+ {
-+ avail_occr = cur_expr->avail_occr;
-+
-+ /* Search for another occurrence in the same basic block. */
-+ while (avail_occr && BLOCK_NUM (avail_occr->insn) != BLOCK_NUM (insn))
-+ {
-+ /* If an occurrence isn't found, save a pointer to the end of
-+ the list. */
-+ last_occr = avail_occr;
-+ avail_occr = avail_occr->next;
-+ }
-+
-+ if (avail_occr)
-+ /* Found another instance of the expression in the same basic block.
-+ Prefer this occurrence to the currently recorded one. We want
-+ the last one in the block and the block is scanned from start
-+ to end. */
-+ avail_occr->insn = insn;
-+ else
-+ {
-+ /* First occurrence of this expression in this basic block. */
-+ avail_occr = (struct occr *) gcse_alloc (sizeof (struct occr));
-+ bytes_used += sizeof (struct occr);
-+
-+ /* First occurrence of this expression in any block? */
-+ if (cur_expr->avail_occr == NULL)
-+ cur_expr->avail_occr = avail_occr;
-+ else
-+ last_occr->next = avail_occr;
-+
-+ avail_occr->insn = insn;
-+ avail_occr->next = NULL;
-+ }
-+ }
-+}
-+
-+/* Insert pattern X in INSN in the hash table.
-+ X is a SET of a reg to either another reg or a constant.
-+ If it is already present, record it as the last occurrence in INSN's
-+ basic block. */
-+
-+static void
-+insert_set_in_table (x, insn, table)
-+ rtx x;
-+ rtx insn;
-+ struct hash_table *table;
-+{
-+ int found;
-+ unsigned int hash;
-+ struct expr *cur_expr, *last_expr = NULL;
-+ struct occr *cur_occr, *last_occr = NULL;
-+
-+ if (GET_CODE (x) != SET
-+ || GET_CODE (SET_DEST (x)) != REG)
-+ abort ();
-+
-+ hash = hash_set (REGNO (SET_DEST (x)), table->size);
-+
-+ cur_expr = table->table[hash];
-+ found = 0;
-+
-+ while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x)))
-+ {
-+ /* If the expression isn't found, save a pointer to the end of
-+ the list. */
-+ last_expr = cur_expr;
-+ cur_expr = cur_expr->next_same_hash;
-+ }
-+
-+ if (! found)
-+ {
-+ cur_expr = (struct expr *) gcse_alloc (sizeof (struct expr));
-+ bytes_used += sizeof (struct expr);
-+ if (table->table[hash] == NULL)
-+ /* This is the first pattern that hashed to this index. */
-+ table->table[hash] = cur_expr;
-+ else
-+ /* Add EXPR to end of this hash chain. */
-+ last_expr->next_same_hash = cur_expr;
-+
-+ /* Set the fields of the expr element.
-+ We must copy X because it can be modified when copy propagation is
-+ performed on its operands. */
-+ cur_expr->expr = copy_rtx (x);
-+ cur_expr->bitmap_index = table->n_elems++;
-+ cur_expr->next_same_hash = NULL;
-+ cur_expr->antic_occr = NULL;
-+ cur_expr->avail_occr = NULL;
-+ }
-+
-+ /* Now record the occurrence. */
-+ cur_occr = cur_expr->avail_occr;
-+
-+ /* Search for another occurrence in the same basic block. */
-+ while (cur_occr && BLOCK_NUM (cur_occr->insn) != BLOCK_NUM (insn))
-+ {
-+ /* If an occurrence isn't found, save a pointer to the end of
-+ the list. */
-+ last_occr = cur_occr;
-+ cur_occr = cur_occr->next;
-+ }
-+
-+ if (cur_occr)
-+ /* Found another instance of the expression in the same basic block.
-+ Prefer this occurrence to the currently recorded one. We want the
-+ last one in the block and the block is scanned from start to end. */
-+ cur_occr->insn = insn;
-+ else
-+ {
-+ /* First occurrence of this expression in this basic block. */
-+ cur_occr = (struct occr *) gcse_alloc (sizeof (struct occr));
-+ bytes_used += sizeof (struct occr);
-+
-+ /* First occurrence of this expression in any block? */
-+ if (cur_expr->avail_occr == NULL)
-+ cur_expr->avail_occr = cur_occr;
-+ else
-+ last_occr->next = cur_occr;
-+
-+ cur_occr->insn = insn;
-+ cur_occr->next = NULL;
-+ }
-+}
-+
-+/* Scan pattern PAT of INSN and add an entry to the hash TABLE (set or
-+ expression one). */
-+
-+static void
-+hash_scan_set (pat, insn, table)
-+ rtx pat, insn;
-+ struct hash_table *table;
-+{
-+ rtx src = SET_SRC (pat);
-+ rtx dest = SET_DEST (pat);
-+ rtx note;
-+
-+ if (GET_CODE (src) == CALL)
-+ hash_scan_call (src, insn, table);
-+
-+ else if (GET_CODE (dest) == REG)
-+ {
-+ unsigned int regno = REGNO (dest);
-+ rtx tmp;
-+
-+ /* If this is a single set and we are doing constant propagation,
-+ see if a REG_NOTE shows this equivalent to a constant. */
-+ if (table->set_p && (note = find_reg_equal_equiv_note (insn)) != 0
-+ && CONSTANT_P (XEXP (note, 0)))
-+ src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src);
-+
-+ /* Only record sets of pseudo-regs in the hash table. */
-+ if (! table->set_p
-+ && regno >= FIRST_PSEUDO_REGISTER
-+ /* Don't GCSE something if we can't do a reg/reg copy. */
-+ && can_copy_p [GET_MODE (dest)]
-+ /* GCSE commonly inserts instruction after the insn. We can't
-+ do that easily for EH_REGION notes so disable GCSE on these
-+ for now. */
-+ && !find_reg_note (insn, REG_EH_REGION, NULL_RTX)
-+ /* Is SET_SRC something we want to gcse? */
-+ && want_to_gcse_p (src)
-+ /* Don't CSE a nop. */
-+ && ! set_noop_p (pat)
-+ /* Don't GCSE if it has attached REG_EQUIV note.
-+ At this point this only function parameters should have
-+ REG_EQUIV notes and if the argument slot is used somewhere
-+ explicitly, it means address of parameter has been taken,
-+ so we should not extend the lifetime of the pseudo. */
-+ && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
-+ || GET_CODE (XEXP (note, 0)) != MEM))
-+ {
-+ /* An expression is not anticipatable if its operands are
-+ modified before this insn or if this is not the only SET in
-+ this insn. */
-+ int antic_p = oprs_anticipatable_p (src, insn) && single_set (insn);
-+ /* An expression is not available if its operands are
-+ subsequently modified, including this insn. It's also not
-+ available if this is a branch, because we can't insert
-+ a set after the branch. */
-+ int avail_p = (oprs_available_p (src, insn)
-+ && ! JUMP_P (insn));
-+
-+ insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p, table);
-+ }
-+
-+ /* Record sets for constant/copy propagation. */
-+ else if (table->set_p
-+ && regno >= FIRST_PSEUDO_REGISTER
-+ && ((GET_CODE (src) == REG
-+ && REGNO (src) >= FIRST_PSEUDO_REGISTER
-+ && can_copy_p [GET_MODE (dest)]
-+ && REGNO (src) != regno)
-+ || CONSTANT_P (src))
-+ /* A copy is not available if its src or dest is subsequently
-+ modified. Here we want to search from INSN+1 on, but
-+ oprs_available_p searches from INSN on. */
-+ && (insn == BLOCK_END (BLOCK_NUM (insn))
-+ || ((tmp = next_nonnote_insn (insn)) != NULL_RTX
-+ && oprs_available_p (pat, tmp))))
-+ insert_set_in_table (pat, insn, table);
-+ }
-+}
-+
-+static void
-+hash_scan_clobber (x, insn, table)
-+ rtx x ATTRIBUTE_UNUSED, insn ATTRIBUTE_UNUSED;
-+ struct hash_table *table ATTRIBUTE_UNUSED;
-+{
-+ /* Currently nothing to do. */
-+}
-+
-+static void
-+hash_scan_call (x, insn, table)
-+ rtx x ATTRIBUTE_UNUSED, insn ATTRIBUTE_UNUSED;
-+ struct hash_table *table ATTRIBUTE_UNUSED;
-+{
-+ /* Currently nothing to do. */
-+}
-+
-+/* Process INSN and add hash table entries as appropriate.
-+
-+ Only available expressions that set a single pseudo-reg are recorded.
-+
-+ Single sets in a PARALLEL could be handled, but it's an extra complication
-+ that isn't dealt with right now. The trick is handling the CLOBBERs that
-+ are also in the PARALLEL. Later.
-+
-+ If SET_P is nonzero, this is for the assignment hash table,
-+ otherwise it is for the expression hash table.
-+ If IN_LIBCALL_BLOCK nonzero, we are in a libcall block, and should
-+ not record any expressions. */
-+
-+static void
-+hash_scan_insn (insn, table, in_libcall_block)
-+ rtx insn;
-+ struct hash_table *table;
-+ int in_libcall_block;
-+{
-+ rtx pat = PATTERN (insn);
-+ int i;
-+
-+ if (in_libcall_block)
-+ return;
-+
-+ /* Pick out the sets of INSN and for other forms of instructions record
-+ what's been modified. */
-+
-+ if (GET_CODE (pat) == SET)
-+ hash_scan_set (pat, insn, table);
-+ else if (GET_CODE (pat) == PARALLEL)
-+ for (i = 0; i < XVECLEN (pat, 0); i++)
-+ {
-+ rtx x = XVECEXP (pat, 0, i);
-+
-+ if (GET_CODE (x) == SET)
-+ hash_scan_set (x, insn, table);
-+ else if (GET_CODE (x) == CLOBBER)
-+ hash_scan_clobber (x, insn, table);
-+ else if (GET_CODE (x) == CALL)
-+ hash_scan_call (x, insn, table);
-+ }
-+
-+ else if (GET_CODE (pat) == CLOBBER)
-+ hash_scan_clobber (pat, insn, table);
-+ else if (GET_CODE (pat) == CALL)
-+ hash_scan_call (pat, insn, table);
-+}
-+
-+static void
-+dump_hash_table (file, name, table)
-+ FILE *file;
-+ const char *name;
-+ struct hash_table *table;
-+{
-+ int i;
-+ /* Flattened out table, so it's printed in proper order. */
-+ struct expr **flat_table;
-+ unsigned int *hash_val;
-+ struct expr *expr;
-+
-+ flat_table
-+ = (struct expr **) xcalloc (table->n_elems, sizeof (struct expr *));
-+ hash_val = (unsigned int *) xmalloc (table->n_elems * sizeof (unsigned int));
-+
-+ for (i = 0; i < (int) table->size; i++)
-+ for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
-+ {
-+ flat_table[expr->bitmap_index] = expr;
-+ hash_val[expr->bitmap_index] = i;
-+ }
-+
-+ fprintf (file, "%s hash table (%d buckets, %d entries)\n",
-+ name, table->size, table->n_elems);
-+
-+ for (i = 0; i < (int) table->n_elems; i++)
-+ if (flat_table[i] != 0)
-+ {
-+ expr = flat_table[i];
-+ fprintf (file, "Index %d (hash value %d)\n ",
-+ expr->bitmap_index, hash_val[i]);
-+ print_rtl (file, expr->expr);
-+ fprintf (file, "\n");
-+ }
-+
-+ fprintf (file, "\n");
-+
-+ free (flat_table);
-+ free (hash_val);
-+}
-+
-+/* Record register first/last/block set information for REGNO in INSN.
-+
-+ first_set records the first place in the block where the register
-+ is set and is used to compute "anticipatability".
-+
-+ last_set records the last place in the block where the register
-+ is set and is used to compute "availability".
-+
-+ last_bb records the block for which first_set and last_set are
-+ valid, as a quick test to invalidate them.
-+
-+ reg_set_in_block records whether the register is set in the block
-+ and is used to compute "transparency". */
-+
-+static void
-+record_last_reg_set_info (insn, regno)
-+ rtx insn;
-+ int regno;
-+{
-+ struct reg_avail_info *info = ®_avail_info[regno];
-+ int cuid = INSN_CUID (insn);
-+
-+ info->last_set = cuid;
-+ if (info->last_bb != current_bb)
-+ {
-+ info->last_bb = current_bb;
-+ info->first_set = cuid;
-+ SET_BIT (reg_set_in_block[current_bb->index], regno);
-+ }
-+}
-+
-+
-+/* Record all of the canonicalized MEMs of record_last_mem_set_info's insn.
-+ Note we store a pair of elements in the list, so they have to be
-+ taken off pairwise. */
-+
-+static void
-+canon_list_insert (dest, unused1, v_insn)
-+ rtx dest ATTRIBUTE_UNUSED;
-+ rtx unused1 ATTRIBUTE_UNUSED;
-+ void * v_insn;
-+{
-+ rtx dest_addr, insn;
-+ int bb;
-+
-+ while (GET_CODE (dest) == SUBREG
-+ || GET_CODE (dest) == ZERO_EXTRACT
-+ || GET_CODE (dest) == SIGN_EXTRACT
-+ || GET_CODE (dest) == STRICT_LOW_PART)
-+ dest = XEXP (dest, 0);
-+
-+ /* If DEST is not a MEM, then it will not conflict with a load. Note
-+ that function calls are assumed to clobber memory, but are handled
-+ elsewhere. */
-+
-+ if (GET_CODE (dest) != MEM)
-+ return;
-+
-+ dest_addr = get_addr (XEXP (dest, 0));
-+ dest_addr = canon_rtx (dest_addr);
-+ insn = (rtx) v_insn;
-+ bb = BLOCK_NUM (insn);
-+
-+ canon_modify_mem_list[bb] =
-+ alloc_EXPR_LIST (VOIDmode, dest_addr, canon_modify_mem_list[bb]);
-+ canon_modify_mem_list[bb] =
-+ alloc_EXPR_LIST (VOIDmode, dest, canon_modify_mem_list[bb]);
-+ bitmap_set_bit (canon_modify_mem_list_set, bb);
-+}
-+
-+/* Record memory modification information for INSN. We do not actually care
-+ about the memory location(s) that are set, or even how they are set (consider
-+ a CALL_INSN). We merely need to record which insns modify memory. */
-+
-+static void
-+record_last_mem_set_info (insn)
-+ rtx insn;
-+{
-+ int bb = BLOCK_NUM (insn);
-+
-+ /* load_killed_in_block_p will handle the case of calls clobbering
-+ everything. */
-+ modify_mem_list[bb] = alloc_INSN_LIST (insn, modify_mem_list[bb]);
-+ bitmap_set_bit (modify_mem_list_set, bb);
-+
-+ if (GET_CODE (insn) == CALL_INSN)
-+ {
-+ /* Note that traversals of this loop (other than for free-ing)
-+ will break after encountering a CALL_INSN. So, there's no
-+ need to insert a pair of items, as canon_list_insert does. */
-+ canon_modify_mem_list[bb] =
-+ alloc_INSN_LIST (insn, canon_modify_mem_list[bb]);
-+ bitmap_set_bit (canon_modify_mem_list_set, bb);
-+ }
-+ else
-+ note_stores (PATTERN (insn), canon_list_insert, (void*) insn);
-+}
-+
-+/* Called from compute_hash_table via note_stores to handle one
-+ SET or CLOBBER in an insn. DATA is really the instruction in which
-+ the SET is taking place. */
-+
-+static void
-+record_last_set_info (dest, setter, data)
-+ rtx dest, setter ATTRIBUTE_UNUSED;
-+ void *data;
-+{
-+ rtx last_set_insn = (rtx) data;
-+
-+ if (GET_CODE (dest) == SUBREG)
-+ dest = SUBREG_REG (dest);
-+
-+ if (GET_CODE (dest) == REG)
-+ record_last_reg_set_info (last_set_insn, REGNO (dest));
-+ else if (GET_CODE (dest) == MEM
-+ /* Ignore pushes, they clobber nothing. */
-+ && ! push_operand (dest, GET_MODE (dest)))
-+ record_last_mem_set_info (last_set_insn);
-+}
-+
-+/* Top level function to create an expression or assignment hash table.
-+
-+ Expression entries are placed in the hash table if
-+ - they are of the form (set (pseudo-reg) src),
-+ - src is something we want to perform GCSE on,
-+ - none of the operands are subsequently modified in the block
-+
-+ Assignment entries are placed in the hash table if
-+ - they are of the form (set (pseudo-reg) src),
-+ - src is something we want to perform const/copy propagation on,
-+ - none of the operands or target are subsequently modified in the block
-+
-+ Currently src must be a pseudo-reg or a const_int.
-+
-+ F is the first insn.
-+ TABLE is the table computed. */
-+
-+static void
-+compute_hash_table_work (table)
-+ struct hash_table *table;
-+{
-+ unsigned int i;
-+
-+ /* While we compute the hash table we also compute a bit array of which
-+ registers are set in which blocks.
-+ ??? This isn't needed during const/copy propagation, but it's cheap to
-+ compute. Later. */
-+ sbitmap_vector_zero (reg_set_in_block, last_basic_block);
-+
-+ /* re-Cache any INSN_LIST nodes we have allocated. */
-+ clear_modify_mem_tables ();
-+ /* Some working arrays used to track first and last set in each block. */
-+ reg_avail_info = (struct reg_avail_info*)
-+ gmalloc (max_gcse_regno * sizeof (struct reg_avail_info));
-+
-+ for (i = 0; i < max_gcse_regno; ++i)
-+ reg_avail_info[i].last_bb = NULL;
-+
-+ FOR_EACH_BB (current_bb)
-+ {
-+ rtx insn;
-+ unsigned int regno;
-+ int in_libcall_block;
-+
-+ /* First pass over the instructions records information used to
-+ determine when registers and memory are first and last set.
-+ ??? hard-reg reg_set_in_block computation
-+ could be moved to compute_sets since they currently don't change. */
-+
-+ for (insn = current_bb->head;
-+ insn && insn != NEXT_INSN (current_bb->end);
-+ insn = NEXT_INSN (insn))
-+ {
-+ if (! INSN_P (insn))
-+ continue;
-+
-+ if (GET_CODE (insn) == CALL_INSN)
-+ {
-+ bool clobbers_all = false;
-+#ifdef NON_SAVING_SETJMP
-+ if (NON_SAVING_SETJMP
-+ && find_reg_note (insn, REG_SETJMP, NULL_RTX))
-+ clobbers_all = true;
-+#endif
-+
-+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-+ if (clobbers_all
-+ || TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
-+ record_last_reg_set_info (insn, regno);
-+
-+ mark_call (insn);
-+ }
-+
-+ note_stores (PATTERN (insn), record_last_set_info, insn);
-+ }
-+
-+ /* The next pass builds the hash table. */
-+
-+ for (insn = current_bb->head, in_libcall_block = 0;
-+ insn && insn != NEXT_INSN (current_bb->end);
-+ insn = NEXT_INSN (insn))
-+ if (INSN_P (insn))
-+ {
-+ if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
-+ in_libcall_block = 1;
-+ else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
-+ in_libcall_block = 0;
-+ hash_scan_insn (insn, table, in_libcall_block);
-+ if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX))
-+ in_libcall_block = 0;
-+ }
-+ }
-+
-+ free (reg_avail_info);
-+ reg_avail_info = NULL;
-+}
-+
-+/* Allocate space for the set/expr hash TABLE.
-+ N_INSNS is the number of instructions in the function.
-+ It is used to determine the number of buckets to use.
-+ SET_P determines whether set or expression table will
-+ be created. */
-+
-+static void
-+alloc_hash_table (n_insns, table, set_p)
-+ int n_insns;
-+ struct hash_table *table;
-+ int set_p;
-+{
-+ int n;
-+
-+ table->size = n_insns / 4;
-+ if (table->size < 11)
-+ table->size = 11;
-+
-+ /* Attempt to maintain efficient use of hash table.
-+ Making it an odd number is simplest for now.
-+ ??? Later take some measurements. */
-+ table->size |= 1;
-+ n = table->size * sizeof (struct expr *);
-+ table->table = (struct expr **) gmalloc (n);
-+ table->set_p = set_p;
-+}
-+
-+/* Free things allocated by alloc_hash_table. */
-+
-+static void
-+free_hash_table (table)
-+ struct hash_table *table;
-+{
-+ free (table->table);
-+}
-+
-+/* Compute the hash TABLE for doing copy/const propagation or
-+ expression hash table. */
-+
-+static void
-+compute_hash_table (table)
-+ struct hash_table *table;
-+{
-+ /* Initialize count of number of entries in hash table. */
-+ table->n_elems = 0;
-+ memset ((char *) table->table, 0,
-+ table->size * sizeof (struct expr *));
-+
-+ compute_hash_table_work (table);
-+}
-+\f
-+/* Expression tracking support. */
-+
-+/* Lookup pattern PAT in the expression TABLE.
-+ The result is a pointer to the table entry, or NULL if not found. */
-+
-+static struct expr *
-+lookup_expr (pat, table)
-+ rtx pat;
-+ struct hash_table *table;
-+{
-+ int do_not_record_p;
-+ unsigned int hash = hash_expr (pat, GET_MODE (pat), &do_not_record_p,
-+ table->size);
-+ struct expr *expr;
-+
-+ if (do_not_record_p)
-+ return NULL;
-+
-+ expr = table->table[hash];
-+
-+ while (expr && ! expr_equiv_p (expr->expr, pat))
-+ expr = expr->next_same_hash;
-+
-+ return expr;
-+}
-+
-+/* Lookup REGNO in the set TABLE. If PAT is non-NULL look for the entry that
-+ matches it, otherwise return the first entry for REGNO. The result is a
-+ pointer to the table entry, or NULL if not found. */
-+
-+static struct expr *
-+lookup_set (regno, pat, table)
-+ unsigned int regno;
-+ rtx pat;
-+ struct hash_table *table;
-+{
-+ unsigned int hash = hash_set (regno, table->size);
-+ struct expr *expr;
-+
-+ expr = table->table[hash];
-+
-+ if (pat)
-+ {
-+ while (expr && ! expr_equiv_p (expr->expr, pat))
-+ expr = expr->next_same_hash;
-+ }
-+ else
-+ {
-+ while (expr && REGNO (SET_DEST (expr->expr)) != regno)
-+ expr = expr->next_same_hash;
-+ }
-+
-+ return expr;
-+}
-+
-+/* Return the next entry for REGNO in list EXPR. */
-+
-+static struct expr *
-+next_set (regno, expr)
-+ unsigned int regno;
-+ struct expr *expr;
-+{
-+ do
-+ expr = expr->next_same_hash;
-+ while (expr && REGNO (SET_DEST (expr->expr)) != regno);
-+
-+ return expr;
-+}
-+
-+/* Like free_INSN_LIST_list or free_EXPR_LIST_list, except that the node
-+ types may be mixed. */
-+
-+static void
-+free_insn_expr_list_list (listp)
-+ rtx *listp;
-+{
-+ rtx list, next;
-+
-+ for (list = *listp; list ; list = next)
-+ {
-+ next = XEXP (list, 1);
-+ if (GET_CODE (list) == EXPR_LIST)
-+ free_EXPR_LIST_node (list);
-+ else
-+ free_INSN_LIST_node (list);
-+ }
-+
-+ *listp = NULL;
-+}
-+
-+/* Clear canon_modify_mem_list and modify_mem_list tables. */
-+static void
-+clear_modify_mem_tables ()
-+{
-+ int i;
-+
-+ EXECUTE_IF_SET_IN_BITMAP
-+ (modify_mem_list_set, 0, i, free_INSN_LIST_list (modify_mem_list + i));
-+ bitmap_clear (modify_mem_list_set);
-+
-+ EXECUTE_IF_SET_IN_BITMAP
-+ (canon_modify_mem_list_set, 0, i,
-+ free_insn_expr_list_list (canon_modify_mem_list + i));
-+ bitmap_clear (canon_modify_mem_list_set);
-+}
-+
-+/* Release memory used by modify_mem_list_set and canon_modify_mem_list_set. */
-+
-+static void
-+free_modify_mem_tables ()
-+{
-+ clear_modify_mem_tables ();
-+ free (modify_mem_list);
-+ free (canon_modify_mem_list);
-+ modify_mem_list = 0;
-+ canon_modify_mem_list = 0;
-+}
-+
-+/* Reset tables used to keep track of what's still available [since the
-+ start of the block]. */
-+
-+static void
-+reset_opr_set_tables ()
-+{
-+ /* Maintain a bitmap of which regs have been set since beginning of
-+ the block. */
-+ CLEAR_REG_SET (reg_set_bitmap);
-+
-+ /* Also keep a record of the last instruction to modify memory.
-+ For now this is very trivial, we only record whether any memory
-+ location has been modified. */
-+ clear_modify_mem_tables ();
-+}
-+
-+/* Return nonzero if the operands of X are not set before INSN in
-+ INSN's basic block. */
-+
-+static int
-+oprs_not_set_p (x, insn)
-+ rtx x, insn;
-+{
-+ int i, j;
-+ enum rtx_code code;
-+ const char *fmt;
-+
-+ if (x == 0)
-+ return 1;
-+
-+ code = GET_CODE (x);
-+ switch (code)
-+ {
-+ case PC:
-+ case CC0:
-+ case CONST:
-+ case CONST_INT:
-+ case CONST_DOUBLE:
-+ case CONST_VECTOR:
-+ case SYMBOL_REF:
-+ case LABEL_REF:
-+ case ADDR_VEC:
-+ case ADDR_DIFF_VEC:
-+ return 1;
-+
-+ case MEM:
-+ if (load_killed_in_block_p (BLOCK_FOR_INSN (insn),
-+ INSN_CUID (insn), x, 0))
-+ return 0;
-+ else
-+ return oprs_not_set_p (XEXP (x, 0), insn);
-+
-+ case REG:
-+ return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x));
-+
-+ default:
-+ break;
-+ }
-+
-+ for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ {
-+ /* If we are about to do the last recursive call
-+ needed at this level, change it into iteration.
-+ This function is called enough to be worth it. */
-+ if (i == 0)
-+ return oprs_not_set_p (XEXP (x, i), insn);
-+
-+ if (! oprs_not_set_p (XEXP (x, i), insn))
-+ return 0;
-+ }
-+ else if (fmt[i] == 'E')
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ if (! oprs_not_set_p (XVECEXP (x, i, j), insn))
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-+
-+/* Mark things set by a CALL. */
-+
-+static void
-+mark_call (insn)
-+ rtx insn;
-+{
-+ if (! CONST_OR_PURE_CALL_P (insn))
-+ record_last_mem_set_info (insn);
-+}
-+
-+/* Mark things set by a SET. */
-+
-+static void
-+mark_set (pat, insn)
-+ rtx pat, insn;
-+{
-+ rtx dest = SET_DEST (pat);
-+
-+ while (GET_CODE (dest) == SUBREG
-+ || GET_CODE (dest) == ZERO_EXTRACT
-+ || GET_CODE (dest) == SIGN_EXTRACT
-+ || GET_CODE (dest) == STRICT_LOW_PART)
-+ dest = XEXP (dest, 0);
-+
-+ if (GET_CODE (dest) == REG)
-+ SET_REGNO_REG_SET (reg_set_bitmap, REGNO (dest));
-+ else if (GET_CODE (dest) == MEM)
-+ record_last_mem_set_info (insn);
-+
-+ if (GET_CODE (SET_SRC (pat)) == CALL)
-+ mark_call (insn);
-+}
-+
-+/* Record things set by a CLOBBER. */
-+
-+static void
-+mark_clobber (pat, insn)
-+ rtx pat, insn;
-+{
-+ rtx clob = XEXP (pat, 0);
-+
-+ while (GET_CODE (clob) == SUBREG || GET_CODE (clob) == STRICT_LOW_PART)
-+ clob = XEXP (clob, 0);
-+
-+ if (GET_CODE (clob) == REG)
-+ SET_REGNO_REG_SET (reg_set_bitmap, REGNO (clob));
-+ else
-+ record_last_mem_set_info (insn);
-+}
-+
-+/* Record things set by INSN.
-+ This data is used by oprs_not_set_p. */
-+
-+static void
-+mark_oprs_set (insn)
-+ rtx insn;
-+{
-+ rtx pat = PATTERN (insn);
-+ int i;
-+
-+ if (GET_CODE (pat) == SET)
-+ mark_set (pat, insn);
-+ else if (GET_CODE (pat) == PARALLEL)
-+ for (i = 0; i < XVECLEN (pat, 0); i++)
-+ {
-+ rtx x = XVECEXP (pat, 0, i);
-+
-+ if (GET_CODE (x) == SET)
-+ mark_set (x, insn);
-+ else if (GET_CODE (x) == CLOBBER)
-+ mark_clobber (x, insn);
-+ else if (GET_CODE (x) == CALL)
-+ mark_call (insn);
-+ }
-+
-+ else if (GET_CODE (pat) == CLOBBER)
-+ mark_clobber (pat, insn);
-+ else if (GET_CODE (pat) == CALL)
-+ mark_call (insn);
-+}
-+
-+\f
-+/* Classic GCSE reaching definition support. */
-+
-+/* Allocate reaching def variables. */
-+
-+static void
-+alloc_rd_mem (n_blocks, n_insns)
-+ int n_blocks, n_insns;
-+{
-+ rd_kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
-+ sbitmap_vector_zero (rd_kill, n_blocks);
-+
-+ rd_gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
-+ sbitmap_vector_zero (rd_gen, n_blocks);
-+
-+ reaching_defs = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
-+ sbitmap_vector_zero (reaching_defs, n_blocks);
-+
-+ rd_out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_insns);
-+ sbitmap_vector_zero (rd_out, n_blocks);
-+}
-+
-+/* Free reaching def variables. */
-+
-+static void
-+free_rd_mem ()
-+{
-+ sbitmap_vector_free (rd_kill);
-+ sbitmap_vector_free (rd_gen);
-+ sbitmap_vector_free (reaching_defs);
-+ sbitmap_vector_free (rd_out);
-+}
-+
-+/* Add INSN to the kills of BB. REGNO, set in BB, is killed by INSN. */
-+
-+static void
-+handle_rd_kill_set (insn, regno, bb)
-+ rtx insn;
-+ int regno;
-+ basic_block bb;
-+{
-+ struct reg_set *this_reg;
-+
-+ for (this_reg = reg_set_table[regno]; this_reg; this_reg = this_reg ->next)
-+ if (BLOCK_NUM (this_reg->insn) != BLOCK_NUM (insn))
-+ SET_BIT (rd_kill[bb->index], INSN_CUID (this_reg->insn));
-+}
-+
-+/* Compute the set of kill's for reaching definitions. */
-+
-+static void
-+compute_kill_rd ()
-+{
-+ int cuid;
-+ unsigned int regno;
-+ int i;
-+ basic_block bb;
-+
-+ /* For each block
-+ For each set bit in `gen' of the block (i.e each insn which
-+ generates a definition in the block)
-+ Call the reg set by the insn corresponding to that bit regx
-+ Look at the linked list starting at reg_set_table[regx]
-+ For each setting of regx in the linked list, which is not in
-+ this block
-+ Set the bit in `kill' corresponding to that insn. */
-+ FOR_EACH_BB (bb)
-+ for (cuid = 0; cuid < max_cuid; cuid++)
-+ if (TEST_BIT (rd_gen[bb->index], cuid))
-+ {
-+ rtx insn = CUID_INSN (cuid);
-+ rtx pat = PATTERN (insn);
-+
-+ if (GET_CODE (insn) == CALL_INSN)
-+ {
-+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-+ if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
-+ handle_rd_kill_set (insn, regno, bb);
-+ }
-+
-+ if (GET_CODE (pat) == PARALLEL)
-+ {
-+ for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
-+ {
-+ enum rtx_code code = GET_CODE (XVECEXP (pat, 0, i));
-+
-+ if ((code == SET || code == CLOBBER)
-+ && GET_CODE (XEXP (XVECEXP (pat, 0, i), 0)) == REG)
-+ handle_rd_kill_set (insn,
-+ REGNO (XEXP (XVECEXP (pat, 0, i), 0)),
-+ bb);
-+ }
-+ }
-+ else if (GET_CODE (pat) == SET && GET_CODE (SET_DEST (pat)) == REG)
-+ /* Each setting of this register outside of this block
-+ must be marked in the set of kills in this block. */
-+ handle_rd_kill_set (insn, REGNO (SET_DEST (pat)), bb);
-+ }
-+}
-+
-+/* Compute the reaching definitions as in
-+ Compilers Principles, Techniques, and Tools. Aho, Sethi, Ullman,
-+ Chapter 10. It is the same algorithm as used for computing available
-+ expressions but applied to the gens and kills of reaching definitions. */
-+
-+static void
-+compute_rd ()
-+{
-+ int changed, passes;
-+ basic_block bb;
-+
-+ FOR_EACH_BB (bb)
-+ sbitmap_copy (rd_out[bb->index] /*dst*/, rd_gen[bb->index] /*src*/);
-+
-+ passes = 0;
-+ changed = 1;
-+ while (changed)
-+ {
-+ changed = 0;
-+ FOR_EACH_BB (bb)
-+ {
-+ sbitmap_union_of_preds (reaching_defs[bb->index], rd_out, bb->index);
-+ changed |= sbitmap_union_of_diff_cg (rd_out[bb->index], rd_gen[bb->index],
-+ reaching_defs[bb->index], rd_kill[bb->index]);
-+ }
-+ passes++;
-+ }
-+
-+ if (gcse_file)
-+ fprintf (gcse_file, "reaching def computation: %d passes\n", passes);
-+}
-+\f
-+/* Classic GCSE available expression support. */
-+
-+/* Allocate memory for available expression computation. */
-+
-+static void
-+alloc_avail_expr_mem (n_blocks, n_exprs)
-+ int n_blocks, n_exprs;
-+{
-+ ae_kill = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
-+ sbitmap_vector_zero (ae_kill, n_blocks);
-+
-+ ae_gen = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
-+ sbitmap_vector_zero (ae_gen, n_blocks);
-+
-+ ae_in = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
-+ sbitmap_vector_zero (ae_in, n_blocks);
-+
-+ ae_out = (sbitmap *) sbitmap_vector_alloc (n_blocks, n_exprs);
-+ sbitmap_vector_zero (ae_out, n_blocks);
-+}
-+
-+static void
-+free_avail_expr_mem ()
-+{
-+ sbitmap_vector_free (ae_kill);
-+ sbitmap_vector_free (ae_gen);
-+ sbitmap_vector_free (ae_in);
-+ sbitmap_vector_free (ae_out);
-+}
-+
-+/* Compute the set of available expressions generated in each basic block. */
-+
-+static void
-+compute_ae_gen (expr_hash_table)
-+ struct hash_table *expr_hash_table;
-+{
-+ unsigned int i;
-+ struct expr *expr;
-+ struct occr *occr;
-+
-+ /* For each recorded occurrence of each expression, set ae_gen[bb][expr].
-+ This is all we have to do because an expression is not recorded if it
-+ is not available, and the only expressions we want to work with are the
-+ ones that are recorded. */
-+ for (i = 0; i < expr_hash_table->size; i++)
-+ for (expr = expr_hash_table->table[i]; expr != 0; expr = expr->next_same_hash)
-+ for (occr = expr->avail_occr; occr != 0; occr = occr->next)
-+ SET_BIT (ae_gen[BLOCK_NUM (occr->insn)], expr->bitmap_index);
-+}
-+
-+/* Return nonzero if expression X is killed in BB. */
-+
-+static int
-+expr_killed_p (x, bb)
-+ rtx x;
-+ basic_block bb;
-+{
-+ int i, j;
-+ enum rtx_code code;
-+ const char *fmt;
-+
-+ if (x == 0)
-+ return 1;
-+
-+ code = GET_CODE (x);
-+ switch (code)
-+ {
-+ case REG:
-+ return TEST_BIT (reg_set_in_block[bb->index], REGNO (x));
-+
-+ case MEM:
-+ if (load_killed_in_block_p (bb, get_max_uid () + 1, x, 0))
-+ return 1;
-+ else
-+ return expr_killed_p (XEXP (x, 0), bb);
-+
-+ case PC:
-+ case CC0: /*FIXME*/
-+ case CONST:
-+ case CONST_INT:
-+ case CONST_DOUBLE:
-+ case CONST_VECTOR:
-+ case SYMBOL_REF:
-+ case LABEL_REF:
-+ case ADDR_VEC:
-+ case ADDR_DIFF_VEC:
-+ return 0;
-+
-+ default:
-+ break;
-+ }
-+
-+ for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ {
-+ /* If we are about to do the last recursive call
-+ needed at this level, change it into iteration.
-+ This function is called enough to be worth it. */
-+ if (i == 0)
-+ return expr_killed_p (XEXP (x, i), bb);
-+ else if (expr_killed_p (XEXP (x, i), bb))
-+ return 1;
-+ }
-+ else if (fmt[i] == 'E')
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ if (expr_killed_p (XVECEXP (x, i, j), bb))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Compute the set of available expressions killed in each basic block. */
-+
-+static void
-+compute_ae_kill (ae_gen, ae_kill, expr_hash_table)
-+ sbitmap *ae_gen, *ae_kill;
-+ struct hash_table *expr_hash_table;
-+{
-+ basic_block bb;
-+ unsigned int i;
-+ struct expr *expr;
-+
-+ FOR_EACH_BB (bb)
-+ for (i = 0; i < expr_hash_table->size; i++)
-+ for (expr = expr_hash_table->table[i]; expr; expr = expr->next_same_hash)
-+ {
-+ /* Skip EXPR if generated in this block. */
-+ if (TEST_BIT (ae_gen[bb->index], expr->bitmap_index))
-+ continue;
-+
-+ if (expr_killed_p (expr->expr, bb))
-+ SET_BIT (ae_kill[bb->index], expr->bitmap_index);
-+ }
-+}
-+\f
-+/* Actually perform the Classic GCSE optimizations. */
-+
-+/* Return nonzero if occurrence OCCR of expression EXPR reaches block BB.
-+
-+ CHECK_SELF_LOOP is nonzero if we should consider a block reaching itself
-+ as a positive reach. We want to do this when there are two computations
-+ of the expression in the block.
-+
-+ VISITED is a pointer to a working buffer for tracking which BB's have
-+ been visited. It is NULL for the top-level call.
-+
-+ We treat reaching expressions that go through blocks containing the same
-+ reaching expression as "not reaching". E.g. if EXPR is generated in blocks
-+ 2 and 3, INSN is in block 4, and 2->3->4, we treat the expression in block
-+ 2 as not reaching. The intent is to improve the probability of finding
-+ only one reaching expression and to reduce register lifetimes by picking
-+ the closest such expression. */
-+
-+static int
-+expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited)
-+ struct occr *occr;
-+ struct expr *expr;
-+ basic_block bb;
-+ int check_self_loop;
-+ char *visited;
-+{
-+ edge pred;
-+
-+ for (pred = bb->pred; pred != NULL; pred = pred->pred_next)
-+ {
-+ basic_block pred_bb = pred->src;
-+
-+ if (visited[pred_bb->index])
-+ /* This predecessor has already been visited. Nothing to do. */
-+ ;
-+ else if (pred_bb == bb)
-+ {
-+ /* BB loops on itself. */
-+ if (check_self_loop
-+ && TEST_BIT (ae_gen[pred_bb->index], expr->bitmap_index)
-+ && BLOCK_NUM (occr->insn) == pred_bb->index)
-+ return 1;
-+
-+ visited[pred_bb->index] = 1;
-+ }
-+
-+ /* Ignore this predecessor if it kills the expression. */
-+ else if (TEST_BIT (ae_kill[pred_bb->index], expr->bitmap_index))
-+ visited[pred_bb->index] = 1;
-+
-+ /* Does this predecessor generate this expression? */
-+ else if (TEST_BIT (ae_gen[pred_bb->index], expr->bitmap_index))
-+ {
-+ /* Is this the occurrence we're looking for?
-+ Note that there's only one generating occurrence per block
-+ so we just need to check the block number. */
-+ if (BLOCK_NUM (occr->insn) == pred_bb->index)
-+ return 1;
-+
-+ visited[pred_bb->index] = 1;
-+ }
-+
-+ /* Neither gen nor kill. */
-+ else
-+ {
-+ visited[pred_bb->index] = 1;
-+ if (expr_reaches_here_p_work (occr, expr, pred_bb, check_self_loop,
-+ visited))
-+
-+ return 1;
-+ }
-+ }
-+
-+ /* All paths have been checked. */
-+ return 0;
-+}
-+
-+/* This wrapper for expr_reaches_here_p_work() is to ensure that any
-+ memory allocated for that function is returned. */
-+
-+static int
-+expr_reaches_here_p (occr, expr, bb, check_self_loop)
-+ struct occr *occr;
-+ struct expr *expr;
-+ basic_block bb;
-+ int check_self_loop;
-+{
-+ int rval;
-+ char *visited = (char *) xcalloc (last_basic_block, 1);
-+
-+ rval = expr_reaches_here_p_work (occr, expr, bb, check_self_loop, visited);
-+
-+ free (visited);
-+ return rval;
-+}
-+
-+/* Return the instruction that computes EXPR that reaches INSN's basic block.
-+ If there is more than one such instruction, return NULL.
-+
-+ Called only by handle_avail_expr. */
-+
-+static rtx
-+computing_insn (expr, insn)
-+ struct expr *expr;
-+ rtx insn;
-+{
-+ basic_block bb = BLOCK_FOR_INSN (insn);
-+
-+ if (expr->avail_occr->next == NULL)
-+ {
-+ if (BLOCK_FOR_INSN (expr->avail_occr->insn) == bb)
-+ /* The available expression is actually itself
-+ (i.e. a loop in the flow graph) so do nothing. */
-+ return NULL;
-+
-+ /* (FIXME) Case that we found a pattern that was created by
-+ a substitution that took place. */
-+ return expr->avail_occr->insn;
-+ }
-+ else
-+ {
-+ /* Pattern is computed more than once.
-+ Search backwards from this insn to see how many of these
-+ computations actually reach this insn. */
-+ struct occr *occr;
-+ rtx insn_computes_expr = NULL;
-+ int can_reach = 0;
-+
-+ for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
-+ {
-+ if (BLOCK_FOR_INSN (occr->insn) == bb)
-+ {
-+ /* The expression is generated in this block.
-+ The only time we care about this is when the expression
-+ is generated later in the block [and thus there's a loop].
-+ We let the normal cse pass handle the other cases. */
-+ if (INSN_CUID (insn) < INSN_CUID (occr->insn)
-+ && expr_reaches_here_p (occr, expr, bb, 1))
-+ {
-+ can_reach++;
-+ if (can_reach > 1)
-+ return NULL;
-+
-+ insn_computes_expr = occr->insn;
-+ }
-+ }
-+ else if (expr_reaches_here_p (occr, expr, bb, 0))
-+ {
-+ can_reach++;
-+ if (can_reach > 1)
-+ return NULL;
-+
-+ insn_computes_expr = occr->insn;
-+ }
-+ }
-+
-+ if (insn_computes_expr == NULL)
-+ abort ();
-+
-+ return insn_computes_expr;
-+ }
-+}
-+
-+/* Return nonzero if the definition in DEF_INSN can reach INSN.
-+ Only called by can_disregard_other_sets. */
-+
-+static int
-+def_reaches_here_p (insn, def_insn)
-+ rtx insn, def_insn;
-+{
-+ rtx reg;
-+
-+ if (TEST_BIT (reaching_defs[BLOCK_NUM (insn)], INSN_CUID (def_insn)))
-+ return 1;
-+
-+ if (BLOCK_NUM (insn) == BLOCK_NUM (def_insn))
-+ {
-+ if (INSN_CUID (def_insn) < INSN_CUID (insn))
-+ {
-+ if (GET_CODE (PATTERN (def_insn)) == PARALLEL)
-+ return 1;
-+ else if (GET_CODE (PATTERN (def_insn)) == CLOBBER)
-+ reg = XEXP (PATTERN (def_insn), 0);
-+ else if (GET_CODE (PATTERN (def_insn)) == SET)
-+ reg = SET_DEST (PATTERN (def_insn));
-+ else
-+ abort ();
-+
-+ return ! reg_set_between_p (reg, NEXT_INSN (def_insn), insn);
-+ }
-+ else
-+ return 0;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Return nonzero if *ADDR_THIS_REG can only have one value at INSN. The
-+ value returned is the number of definitions that reach INSN. Returning a
-+ value of zero means that [maybe] more than one definition reaches INSN and
-+ the caller can't perform whatever optimization it is trying. i.e. it is
-+ always safe to return zero. */
-+
-+static int
-+can_disregard_other_sets (addr_this_reg, insn, for_combine)
-+ struct reg_set **addr_this_reg;
-+ rtx insn;
-+ int for_combine;
-+{
-+ int number_of_reaching_defs = 0;
-+ struct reg_set *this_reg;
-+
-+ for (this_reg = *addr_this_reg; this_reg != 0; this_reg = this_reg->next)
-+ if (def_reaches_here_p (insn, this_reg->insn))
-+ {
-+ number_of_reaching_defs++;
-+ /* Ignore parallels for now. */
-+ if (GET_CODE (PATTERN (this_reg->insn)) == PARALLEL)
-+ return 0;
-+
-+ if (!for_combine
-+ && (GET_CODE (PATTERN (this_reg->insn)) == CLOBBER
-+ || ! rtx_equal_p (SET_SRC (PATTERN (this_reg->insn)),
-+ SET_SRC (PATTERN (insn)))))
-+ /* A setting of the reg to a different value reaches INSN. */
-+ return 0;
-+
-+ if (number_of_reaching_defs > 1)
-+ {
-+ /* If in this setting the value the register is being set to is
-+ equal to the previous value the register was set to and this
-+ setting reaches the insn we are trying to do the substitution
-+ on then we are ok. */
-+ if (GET_CODE (PATTERN (this_reg->insn)) == CLOBBER)
-+ return 0;
-+ else if (! rtx_equal_p (SET_SRC (PATTERN (this_reg->insn)),
-+ SET_SRC (PATTERN (insn))))
-+ return 0;
-+ }
-+
-+ *addr_this_reg = this_reg;
-+ }
-+
-+ return number_of_reaching_defs;
-+}
-+
-+/* Expression computed by insn is available and the substitution is legal,
-+ so try to perform the substitution.
-+
-+ The result is nonzero if any changes were made. */
-+
-+static int
-+handle_avail_expr (insn, expr)
-+ rtx insn;
-+ struct expr *expr;
-+{
-+ rtx pat, insn_computes_expr, expr_set;
-+ rtx to;
-+ struct reg_set *this_reg;
-+ int found_setting, use_src;
-+ int changed = 0;
-+
-+ /* We only handle the case where one computation of the expression
-+ reaches this instruction. */
-+ insn_computes_expr = computing_insn (expr, insn);
-+ if (insn_computes_expr == NULL)
-+ return 0;
-+ expr_set = single_set (insn_computes_expr);
-+ if (!expr_set)
-+ abort ();
-+
-+ found_setting = 0;
-+ use_src = 0;
-+
-+ /* At this point we know only one computation of EXPR outside of this
-+ block reaches this insn. Now try to find a register that the
-+ expression is computed into. */
-+ if (GET_CODE (SET_SRC (expr_set)) == REG)
-+ {
-+ /* This is the case when the available expression that reaches
-+ here has already been handled as an available expression. */
-+ unsigned int regnum_for_replacing
-+ = REGNO (SET_SRC (expr_set));
-+
-+ /* If the register was created by GCSE we can't use `reg_set_table',
-+ however we know it's set only once. */
-+ if (regnum_for_replacing >= max_gcse_regno
-+ /* If the register the expression is computed into is set only once,
-+ or only one set reaches this insn, we can use it. */
-+ || (((this_reg = reg_set_table[regnum_for_replacing]),
-+ this_reg->next == NULL)
-+ || can_disregard_other_sets (&this_reg, insn, 0)))
-+ {
-+ use_src = 1;
-+ found_setting = 1;
-+ }
-+ }
-+
-+ if (!found_setting)
-+ {
-+ unsigned int regnum_for_replacing
-+ = REGNO (SET_DEST (expr_set));
-+
-+ /* This shouldn't happen. */
-+ if (regnum_for_replacing >= max_gcse_regno)
-+ abort ();
-+
-+ this_reg = reg_set_table[regnum_for_replacing];
-+
-+ /* If the register the expression is computed into is set only once,
-+ or only one set reaches this insn, use it. */
-+ if (this_reg->next == NULL
-+ || can_disregard_other_sets (&this_reg, insn, 0))
-+ found_setting = 1;
-+ }
-+
-+ if (found_setting)
-+ {
-+ pat = PATTERN (insn);
-+ if (use_src)
-+ to = SET_SRC (expr_set);
-+ else
-+ to = SET_DEST (expr_set);
-+ changed = validate_change (insn, &SET_SRC (pat), to, 0);
-+
-+ /* We should be able to ignore the return code from validate_change but
-+ to play it safe we check. */
-+ if (changed)
-+ {
-+ gcse_subst_count++;
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file, "GCSE: Replacing the source in insn %d with",
-+ INSN_UID (insn));
-+ fprintf (gcse_file, " reg %d %s insn %d\n",
-+ REGNO (to), use_src ? "from" : "set in",
-+ INSN_UID (insn_computes_expr));
-+ }
-+ }
-+ }
-+
-+ /* The register that the expr is computed into is set more than once. */
-+ else if (1 /*expensive_op(this_pattrn->op) && do_expensive_gcse)*/)
-+ {
-+ /* Insert an insn after insnx that copies the reg set in insnx
-+ into a new pseudo register call this new register REGN.
-+ From insnb until end of basic block or until REGB is set
-+ replace all uses of REGB with REGN. */
-+ rtx new_insn;
-+
-+ to = gen_reg_rtx (GET_MODE (SET_DEST (expr_set)));
-+
-+ /* Generate the new insn. */
-+ /* ??? If the change fails, we return 0, even though we created
-+ an insn. I think this is ok. */
-+ new_insn
-+ = emit_insn_after (gen_rtx_SET (VOIDmode, to,
-+ SET_DEST (expr_set)),
-+ insn_computes_expr);
-+
-+ /* Keep register set table up to date. */
-+ record_one_set (REGNO (to), new_insn);
-+
-+ gcse_create_count++;
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file, "GCSE: Creating insn %d to copy value of reg %d",
-+ INSN_UID (NEXT_INSN (insn_computes_expr)),
-+ REGNO (SET_SRC (PATTERN (NEXT_INSN (insn_computes_expr)))));
-+ fprintf (gcse_file, ", computed in insn %d,\n",
-+ INSN_UID (insn_computes_expr));
-+ fprintf (gcse_file, " into newly allocated reg %d\n",
-+ REGNO (to));
-+ }
-+
-+ pat = PATTERN (insn);
-+
-+ /* Do register replacement for INSN. */
-+ changed = validate_change (insn, &SET_SRC (pat),
-+ SET_DEST (PATTERN
-+ (NEXT_INSN (insn_computes_expr))),
-+ 0);
-+
-+ /* We should be able to ignore the return code from validate_change but
-+ to play it safe we check. */
-+ if (changed)
-+ {
-+ gcse_subst_count++;
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file,
-+ "GCSE: Replacing the source in insn %d with reg %d ",
-+ INSN_UID (insn),
-+ REGNO (SET_DEST (PATTERN (NEXT_INSN
-+ (insn_computes_expr)))));
-+ fprintf (gcse_file, "set in insn %d\n",
-+ INSN_UID (insn_computes_expr));
-+ }
-+ }
-+ }
-+
-+ return changed;
-+}
-+
-+/* Perform classic GCSE. This is called by one_classic_gcse_pass after all
-+ the dataflow analysis has been done.
-+
-+ The result is nonzero if a change was made. */
-+
-+static int
-+classic_gcse ()
-+{
-+ int changed;
-+ rtx insn;
-+ basic_block bb;
-+
-+ /* Note we start at block 1. */
-+
-+ if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
-+ return 0;
-+
-+ changed = 0;
-+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
-+ {
-+ /* Reset tables used to keep track of what's still valid [since the
-+ start of the block]. */
-+ reset_opr_set_tables ();
-+
-+ for (insn = bb->head;
-+ insn != NULL && insn != NEXT_INSN (bb->end);
-+ insn = NEXT_INSN (insn))
-+ {
-+ /* Is insn of form (set (pseudo-reg) ...)? */
-+ if (GET_CODE (insn) == INSN
-+ && GET_CODE (PATTERN (insn)) == SET
-+ && GET_CODE (SET_DEST (PATTERN (insn))) == REG
-+ && REGNO (SET_DEST (PATTERN (insn))) >= FIRST_PSEUDO_REGISTER)
-+ {
-+ rtx pat = PATTERN (insn);
-+ rtx src = SET_SRC (pat);
-+ struct expr *expr;
-+
-+ if (want_to_gcse_p (src)
-+ /* Is the expression recorded? */
-+ && ((expr = lookup_expr (src, &expr_hash_table)) != NULL)
-+ /* Is the expression available [at the start of the
-+ block]? */
-+ && TEST_BIT (ae_in[bb->index], expr->bitmap_index)
-+ /* Are the operands unchanged since the start of the
-+ block? */
-+ && oprs_not_set_p (src, insn))
-+ changed |= handle_avail_expr (insn, expr);
-+ }
-+
-+ /* Keep track of everything modified by this insn. */
-+ /* ??? Need to be careful w.r.t. mods done to INSN. */
-+ if (INSN_P (insn))
-+ mark_oprs_set (insn);
-+ }
-+ }
-+
-+ return changed;
-+}
-+
-+/* Top level routine to perform one classic GCSE pass.
-+
-+ Return nonzero if a change was made. */
-+
-+static int
-+one_classic_gcse_pass (pass)
-+ int pass;
-+{
-+ int changed = 0;
-+
-+ gcse_subst_count = 0;
-+ gcse_create_count = 0;
-+
-+ alloc_hash_table (max_cuid, &expr_hash_table, 0);
-+ alloc_rd_mem (last_basic_block, max_cuid);
-+ compute_hash_table (&expr_hash_table);
-+ if (gcse_file)
-+ dump_hash_table (gcse_file, "Expression", &expr_hash_table);
-+
-+ if (expr_hash_table.n_elems > 0)
-+ {
-+ compute_kill_rd ();
-+ compute_rd ();
-+ alloc_avail_expr_mem (last_basic_block, expr_hash_table.n_elems);
-+ compute_ae_gen (&expr_hash_table);
-+ compute_ae_kill (ae_gen, ae_kill, &expr_hash_table);
-+ compute_available (ae_gen, ae_kill, ae_out, ae_in);
-+ changed = classic_gcse ();
-+ free_avail_expr_mem ();
-+ }
-+
-+ free_rd_mem ();
-+ free_hash_table (&expr_hash_table);
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "\n");
-+ fprintf (gcse_file, "GCSE of %s, pass %d: %d bytes needed, %d substs,",
-+ current_function_name, pass, bytes_used, gcse_subst_count);
-+ fprintf (gcse_file, "%d insns created\n", gcse_create_count);
-+ }
-+
-+ return changed;
-+}
-+\f
-+/* Compute copy/constant propagation working variables. */
-+
-+/* Local properties of assignments. */
-+static sbitmap *cprop_pavloc;
-+static sbitmap *cprop_absaltered;
-+
-+/* Global properties of assignments (computed from the local properties). */
-+static sbitmap *cprop_avin;
-+static sbitmap *cprop_avout;
-+
-+/* Allocate vars used for copy/const propagation. N_BLOCKS is the number of
-+ basic blocks. N_SETS is the number of sets. */
-+
-+static void
-+alloc_cprop_mem (n_blocks, n_sets)
-+ int n_blocks, n_sets;
-+{
-+ cprop_pavloc = sbitmap_vector_alloc (n_blocks, n_sets);
-+ cprop_absaltered = sbitmap_vector_alloc (n_blocks, n_sets);
-+
-+ cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets);
-+ cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets);
-+}
-+
-+/* Free vars used by copy/const propagation. */
-+
-+static void
-+free_cprop_mem ()
-+{
-+ sbitmap_vector_free (cprop_pavloc);
-+ sbitmap_vector_free (cprop_absaltered);
-+ sbitmap_vector_free (cprop_avin);
-+ sbitmap_vector_free (cprop_avout);
-+}
-+
-+/* For each block, compute whether X is transparent. X is either an
-+ expression or an assignment [though we don't care which, for this context
-+ an assignment is treated as an expression]. For each block where an
-+ element of X is modified, set (SET_P == 1) or reset (SET_P == 0) the INDX
-+ bit in BMAP. */
-+
-+static void
-+compute_transp (x, indx, bmap, set_p)
-+ rtx x;
-+ int indx;
-+ sbitmap *bmap;
-+ int set_p;
-+{
-+ int i, j;
-+ basic_block bb;
-+ enum rtx_code code;
-+ reg_set *r;
-+ const char *fmt;
-+
-+ /* repeat is used to turn tail-recursion into iteration since GCC
-+ can't do it when there's no return value. */
-+ repeat:
-+
-+ if (x == 0)
-+ return;
-+
-+ code = GET_CODE (x);
-+ switch (code)
-+ {
-+ case REG:
-+ if (set_p)
-+ {
-+ if (REGNO (x) < FIRST_PSEUDO_REGISTER)
-+ {
-+ FOR_EACH_BB (bb)
-+ if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
-+ SET_BIT (bmap[bb->index], indx);
-+ }
-+ else
-+ {
-+ for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next)
-+ SET_BIT (bmap[BLOCK_NUM (r->insn)], indx);
-+ }
-+ }
-+ else
-+ {
-+ if (REGNO (x) < FIRST_PSEUDO_REGISTER)
-+ {
-+ FOR_EACH_BB (bb)
-+ if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x)))
-+ RESET_BIT (bmap[bb->index], indx);
-+ }
-+ else
-+ {
-+ for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next)
-+ RESET_BIT (bmap[BLOCK_NUM (r->insn)], indx);
-+ }
-+ }
-+
-+ return;
-+
-+ case MEM:
-+ FOR_EACH_BB (bb)
-+ {
-+ rtx list_entry = canon_modify_mem_list[bb->index];
-+
-+ while (list_entry)
-+ {
-+ rtx dest, dest_addr;
-+
-+ if (GET_CODE (XEXP (list_entry, 0)) == CALL_INSN)
-+ {
-+ if (set_p)
-+ SET_BIT (bmap[bb->index], indx);
-+ else
-+ RESET_BIT (bmap[bb->index], indx);
-+ break;
-+ }
-+ /* LIST_ENTRY must be an INSN of some kind that sets memory.
-+ Examine each hunk of memory that is modified. */
-+
-+ dest = XEXP (list_entry, 0);
-+ list_entry = XEXP (list_entry, 1);
-+ dest_addr = XEXP (list_entry, 0);
-+
-+ if (canon_true_dependence (dest, GET_MODE (dest), dest_addr,
-+ x, rtx_addr_varies_p))
-+ {
-+ if (set_p)
-+ SET_BIT (bmap[bb->index], indx);
-+ else
-+ RESET_BIT (bmap[bb->index], indx);
-+ break;
-+ }
-+ list_entry = XEXP (list_entry, 1);
-+ }
-+ }
-+
-+ x = XEXP (x, 0);
-+ goto repeat;
-+
-+ case PC:
-+ case CC0: /*FIXME*/
-+ case CONST:
-+ case CONST_INT:
-+ case CONST_DOUBLE:
-+ case CONST_VECTOR:
-+ case SYMBOL_REF:
-+ case LABEL_REF:
-+ case ADDR_VEC:
-+ case ADDR_DIFF_VEC:
-+ return;
-+
-+ default:
-+ break;
-+ }
-+
-+ for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ {
-+ /* If we are about to do the last recursive call
-+ needed at this level, change it into iteration.
-+ This function is called enough to be worth it. */
-+ if (i == 0)
-+ {
-+ x = XEXP (x, i);
-+ goto repeat;
-+ }
-+
-+ compute_transp (XEXP (x, i), indx, bmap, set_p);
-+ }
-+ else if (fmt[i] == 'E')
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ compute_transp (XVECEXP (x, i, j), indx, bmap, set_p);
-+ }
-+}
-+
-+/* Top level routine to do the dataflow analysis needed by copy/const
-+ propagation. */
-+
-+static void
-+compute_cprop_data ()
-+{
-+ compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, &set_hash_table);
-+ compute_available (cprop_pavloc, cprop_absaltered,
-+ cprop_avout, cprop_avin);
-+}
-+\f
-+/* Copy/constant propagation. */
-+
-+/* Maximum number of register uses in an insn that we handle. */
-+#define MAX_USES 8
-+
-+/* Table of uses found in an insn.
-+ Allocated statically to avoid alloc/free complexity and overhead. */
-+static struct reg_use reg_use_table[MAX_USES];
-+
-+/* Index into `reg_use_table' while building it. */
-+static int reg_use_count;
-+
-+/* Set up a list of register numbers used in INSN. The found uses are stored
-+ in `reg_use_table'. `reg_use_count' is initialized to zero before entry,
-+ and contains the number of uses in the table upon exit.
-+
-+ ??? If a register appears multiple times we will record it multiple times.
-+ This doesn't hurt anything but it will slow things down. */
-+
-+static void
-+find_used_regs (xptr, data)
-+ rtx *xptr;
-+ void *data ATTRIBUTE_UNUSED;
-+{
-+ int i, j;
-+ enum rtx_code code;
-+ const char *fmt;
-+ rtx x = *xptr;
-+
-+ /* repeat is used to turn tail-recursion into iteration since GCC
-+ can't do it when there's no return value. */
-+ repeat:
-+ if (x == 0)
-+ return;
-+
-+ code = GET_CODE (x);
-+ if (REG_P (x))
-+ {
-+ if (reg_use_count == MAX_USES)
-+ return;
-+
-+ reg_use_table[reg_use_count].reg_rtx = x;
-+ reg_use_count++;
-+ }
-+
-+ /* Recursively scan the operands of this expression. */
-+
-+ for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ {
-+ /* If we are about to do the last recursive call
-+ needed at this level, change it into iteration.
-+ This function is called enough to be worth it. */
-+ if (i == 0)
-+ {
-+ x = XEXP (x, 0);
-+ goto repeat;
-+ }
-+
-+ find_used_regs (&XEXP (x, i), data);
-+ }
-+ else if (fmt[i] == 'E')
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ find_used_regs (&XVECEXP (x, i, j), data);
-+ }
-+}
-+
-+/* Try to replace all non-SET_DEST occurrences of FROM in INSN with TO.
-+ Returns nonzero is successful. */
-+
-+static int
-+try_replace_reg (from, to, insn)
-+ rtx from, to, insn;
-+{
-+ rtx note = find_reg_equal_equiv_note (insn);
-+ rtx src = 0;
-+ int success = 0;
-+ rtx set = single_set (insn);
-+
-+ validate_replace_src_group (from, to, insn);
-+ if (num_changes_pending () && apply_change_group ())
-+ success = 1;
-+
-+ /* Try to simplify SET_SRC if we have substituted a constant. */
-+ if (success && set && CONSTANT_P (to))
-+ {
-+ src = simplify_rtx (SET_SRC (set));
-+
-+ if (src)
-+ validate_change (insn, &SET_SRC (set), src, 0);
-+ }
-+
-+ if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
-+ {
-+ /* If above failed and this is a single set, try to simplify the source of
-+ the set given our substitution. We could perhaps try this for multiple
-+ SETs, but it probably won't buy us anything. */
-+ src = simplify_replace_rtx (SET_SRC (set), from, to);
-+
-+ if (!rtx_equal_p (src, SET_SRC (set))
-+ && validate_change (insn, &SET_SRC (set), src, 0))
-+ success = 1;
-+
-+ /* If we've failed to do replacement, have a single SET, don't already
-+ have a note, and have no special SET, add a REG_EQUAL note to not
-+ lose information. */
-+ if (!success && note == 0 && set != 0
-+ && GET_CODE (XEXP (set, 0)) != ZERO_EXTRACT
-+ && GET_CODE (XEXP (set, 0)) != SIGN_EXTRACT)
-+ note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
-+ }
-+
-+ /* If there is already a NOTE, update the expression in it with our
-+ replacement. */
-+ else if (note != 0)
-+ XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), from, to);
-+
-+ /* REG_EQUAL may get simplified into register.
-+ We don't allow that. Remove that note. This code ought
-+ not to hapen, because previous code ought to syntetize
-+ reg-reg move, but be on the safe side. */
-+ if (note && REG_P (XEXP (note, 0)))
-+ remove_note (insn, note);
-+
-+ return success;
-+}
-+
-+/* Find a set of REGNOs that are available on entry to INSN's block. Returns
-+ NULL no such set is found. */
-+
-+static struct expr *
-+find_avail_set (regno, insn)
-+ int regno;
-+ rtx insn;
-+{
-+ /* SET1 contains the last set found that can be returned to the caller for
-+ use in a substitution. */
-+ struct expr *set1 = 0;
-+
-+ /* Loops are not possible here. To get a loop we would need two sets
-+ available at the start of the block containing INSN. ie we would
-+ need two sets like this available at the start of the block:
-+
-+ (set (reg X) (reg Y))
-+ (set (reg Y) (reg X))
-+
-+ This can not happen since the set of (reg Y) would have killed the
-+ set of (reg X) making it unavailable at the start of this block. */
-+ while (1)
-+ {
-+ rtx src;
-+ struct expr *set = lookup_set (regno, NULL_RTX, &set_hash_table);
-+
-+ /* Find a set that is available at the start of the block
-+ which contains INSN. */
-+ while (set)
-+ {
-+ if (TEST_BIT (cprop_avin[BLOCK_NUM (insn)], set->bitmap_index))
-+ break;
-+ set = next_set (regno, set);
-+ }
-+
-+ /* If no available set was found we've reached the end of the
-+ (possibly empty) copy chain. */
-+ if (set == 0)
-+ break;
-+
-+ if (GET_CODE (set->expr) != SET)
-+ abort ();
-+
-+ src = SET_SRC (set->expr);
-+
-+ /* We know the set is available.
-+ Now check that SRC is ANTLOC (i.e. none of the source operands
-+ have changed since the start of the block).
-+
-+ If the source operand changed, we may still use it for the next
-+ iteration of this loop, but we may not use it for substitutions. */
-+
-+ if (CONSTANT_P (src) || oprs_not_set_p (src, insn))
-+ set1 = set;
-+
-+ /* If the source of the set is anything except a register, then
-+ we have reached the end of the copy chain. */
-+ if (GET_CODE (src) != REG)
-+ break;
-+
-+ /* Follow the copy chain, ie start another iteration of the loop
-+ and see if we have an available copy into SRC. */
-+ regno = REGNO (src);
-+ }
-+
-+ /* SET1 holds the last set that was available and anticipatable at
-+ INSN. */
-+ return set1;
-+}
-+
-+/* Subroutine of cprop_insn that tries to propagate constants into
-+ JUMP_INSNS. JUMP must be a conditional jump. If SETCC is non-NULL
-+ it is the instruction that immediately preceeds JUMP, and must be a
-+ single SET of a register. FROM is what we will try to replace,
-+ SRC is the constant we will try to substitute for it. Returns nonzero
-+ if a change was made. */
-+
-+static int
-+cprop_jump (bb, setcc, jump, from, src)
-+ basic_block bb;
-+ rtx setcc;
-+ rtx jump;
-+ rtx from;
-+ rtx src;
-+{
-+ rtx new, new_set;
-+ rtx set = pc_set (jump);
-+
-+ /* First substitute in the INSN condition as the SET_SRC of the JUMP,
-+ then substitute that given values in this expanded JUMP. */
-+ if (setcc != NULL
-+ && !modified_between_p (from, setcc, jump)
-+ && !modified_between_p (src, setcc, jump))
-+ {
-+ rtx setcc_set = single_set (setcc);
-+ new_set = simplify_replace_rtx (SET_SRC (set),
-+ SET_DEST (setcc_set),
-+ SET_SRC (setcc_set));
-+ }
-+ else
-+ new_set = set;
-+
-+ new = simplify_replace_rtx (new_set, from, src);
-+
-+ /* If no simplification can be made, then try the next
-+ register. */
-+ if (rtx_equal_p (new, new_set) || rtx_equal_p (new, SET_SRC (set)))
-+ return 0;
-+
-+ /* If this is now a no-op delete it, otherwise this must be a valid insn. */
-+ if (new == pc_rtx)
-+ delete_insn (jump);
-+ else
-+ {
-+ /* Ensure the value computed inside the jump insn to be equivalent
-+ to one computed by setcc. */
-+ if (setcc
-+ && modified_in_p (new, setcc))
-+ return 0;
-+ if (! validate_change (jump, &SET_SRC (set), new, 0))
-+ return 0;
-+
-+ /* If this has turned into an unconditional jump,
-+ then put a barrier after it so that the unreachable
-+ code will be deleted. */
-+ if (GET_CODE (SET_SRC (set)) == LABEL_REF)
-+ emit_barrier_after (jump);
-+ }
-+
-+#ifdef HAVE_cc0
-+ /* Delete the cc0 setter. */
-+ if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
-+ delete_insn (setcc);
-+#endif
-+
-+ run_jump_opt_after_gcse = 1;
-+
-+ const_prop_count++;
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file,
-+ "CONST-PROP: Replacing reg %d in jump_insn %d with constant ",
-+ REGNO (from), INSN_UID (jump));
-+ print_rtl (gcse_file, src);
-+ fprintf (gcse_file, "\n");
-+ }
-+ purge_dead_edges (bb);
-+
-+ return 1;
-+}
-+
-+static bool
-+constprop_register (insn, from, to, alter_jumps)
-+ rtx insn;
-+ rtx from;
-+ rtx to;
-+ int alter_jumps;
-+{
-+ rtx sset;
-+
-+ /* Check for reg or cc0 setting instructions followed by
-+ conditional branch instructions first. */
-+ if (alter_jumps
-+ && (sset = single_set (insn)) != NULL
-+ && NEXT_INSN (insn)
-+ && any_condjump_p (NEXT_INSN (insn)) && onlyjump_p (NEXT_INSN (insn)))
-+ {
-+ rtx dest = SET_DEST (sset);
-+ if ((REG_P (dest) || CC0_P (dest))
-+ && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to))
-+ return 1;
-+ }
-+
-+ /* Handle normal insns next. */
-+ if (GET_CODE (insn) == INSN
-+ && try_replace_reg (from, to, insn))
-+ return 1;
-+
-+ /* Try to propagate a CONST_INT into a conditional jump.
-+ We're pretty specific about what we will handle in this
-+ code, we can extend this as necessary over time.
-+
-+ Right now the insn in question must look like
-+ (set (pc) (if_then_else ...)) */
-+ else if (alter_jumps && any_condjump_p (insn) && onlyjump_p (insn))
-+ return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to);
-+ return 0;
-+}
-+
-+/* Perform constant and copy propagation on INSN.
-+ The result is nonzero if a change was made. */
-+
-+static int
-+cprop_insn (insn, alter_jumps)
-+ rtx insn;
-+ int alter_jumps;
-+{
-+ struct reg_use *reg_used;
-+ int changed = 0;
-+ rtx note;
-+
-+ if (!INSN_P (insn))
-+ return 0;
-+
-+ reg_use_count = 0;
-+ note_uses (&PATTERN (insn), find_used_regs, NULL);
-+
-+ note = find_reg_equal_equiv_note (insn);
-+
-+ /* We may win even when propagating constants into notes. */
-+ if (note)
-+ find_used_regs (&XEXP (note, 0), NULL);
-+
-+ for (reg_used = ®_use_table[0]; reg_use_count > 0;
-+ reg_used++, reg_use_count--)
-+ {
-+ unsigned int regno = REGNO (reg_used->reg_rtx);
-+ rtx pat, src;
-+ struct expr *set;
-+
-+ /* Ignore registers created by GCSE.
-+ We do this because ... */
-+ if (regno >= max_gcse_regno)
-+ continue;
-+
-+ /* If the register has already been set in this block, there's
-+ nothing we can do. */
-+ if (! oprs_not_set_p (reg_used->reg_rtx, insn))
-+ continue;
-+
-+ /* Find an assignment that sets reg_used and is available
-+ at the start of the block. */
-+ set = find_avail_set (regno, insn);
-+ if (! set)
-+ continue;
-+
-+ pat = set->expr;
-+ /* ??? We might be able to handle PARALLELs. Later. */
-+ if (GET_CODE (pat) != SET)
-+ abort ();
-+
-+ src = SET_SRC (pat);
-+
-+ /* Constant propagation. */
-+ if (CONSTANT_P (src))
-+ {
-+ if (constprop_register (insn, reg_used->reg_rtx, src, alter_jumps))
-+ {
-+ changed = 1;
-+ const_prop_count++;
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file, "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
-+ fprintf (gcse_file, "insn %d with constant ", INSN_UID (insn));
-+ print_rtl (gcse_file, src);
-+ fprintf (gcse_file, "\n");
-+ }
-+ }
-+ }
-+ else if (GET_CODE (src) == REG
-+ && REGNO (src) >= FIRST_PSEUDO_REGISTER
-+ && REGNO (src) != regno)
-+ {
-+ if (try_replace_reg (reg_used->reg_rtx, src, insn))
-+ {
-+ changed = 1;
-+ copy_prop_count++;
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file, "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
-+ regno, INSN_UID (insn));
-+ fprintf (gcse_file, " with reg %d\n", REGNO (src));
-+ }
-+
-+ /* The original insn setting reg_used may or may not now be
-+ deletable. We leave the deletion to flow. */
-+ /* FIXME: If it turns out that the insn isn't deletable,
-+ then we may have unnecessarily extended register lifetimes
-+ and made things worse. */
-+ }
-+ }
-+ }
-+
-+ return changed;
-+}
-+
-+/* Like find_used_regs, but avoid recording uses that appear in
-+ input-output contexts such as zero_extract or pre_dec. This
-+ restricts the cases we consider to those for which local cprop
-+ can legitimately make replacements. */
-+
-+static void
-+local_cprop_find_used_regs (xptr, data)
-+ rtx *xptr;
-+ void *data;
-+{
-+ rtx x = *xptr;
-+
-+ if (x == 0)
-+ return;
-+
-+ switch (GET_CODE (x))
-+ {
-+ case ZERO_EXTRACT:
-+ case SIGN_EXTRACT:
-+ case STRICT_LOW_PART:
-+ return;
-+
-+ case PRE_DEC:
-+ case PRE_INC:
-+ case POST_DEC:
-+ case POST_INC:
-+ case PRE_MODIFY:
-+ case POST_MODIFY:
-+ /* Can only legitimately appear this early in the context of
-+ stack pushes for function arguments, but handle all of the
-+ codes nonetheless. */
-+ return;
-+
-+ case SUBREG:
-+ /* Setting a subreg of a register larger than word_mode leaves
-+ the non-written words unchanged. */
-+ if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) > BITS_PER_WORD)
-+ return;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ find_used_regs (xptr, data);
-+}
-+
-+/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
-+ their REG_EQUAL notes need updating. */
-+
-+static bool
-+do_local_cprop (x, insn, alter_jumps, libcall_sp)
-+ rtx x;
-+ rtx insn;
-+ int alter_jumps;
-+ rtx *libcall_sp;
-+{
-+ rtx newreg = NULL, newcnst = NULL;
-+
-+ /* Rule out USE instructions and ASM statements as we don't want to
-+ change the hard registers mentioned. */
-+ if (GET_CODE (x) == REG
-+ && (REGNO (x) >= FIRST_PSEUDO_REGISTER
-+ || (GET_CODE (PATTERN (insn)) != USE
-+ && asm_noperands (PATTERN (insn)) < 0)))
-+ {
-+ cselib_val *val = cselib_lookup (x, GET_MODE (x), 0);
-+ struct elt_loc_list *l;
-+
-+ if (!val)
-+ return false;
-+ for (l = val->locs; l; l = l->next)
-+ {
-+ rtx this_rtx = l->loc;
-+ rtx note;
-+
-+ if (l->in_libcall)
-+ continue;
-+
-+ if (CONSTANT_P (this_rtx))
-+ newcnst = this_rtx;
-+ if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
-+ /* Don't copy propagate if it has attached REG_EQUIV note.
-+ At this point this only function parameters should have
-+ REG_EQUIV notes and if the argument slot is used somewhere
-+ explicitly, it means address of parameter has been taken,
-+ so we should not extend the lifetime of the pseudo. */
-+ && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX))
-+ || GET_CODE (XEXP (note, 0)) != MEM))
-+ newreg = this_rtx;
-+ }
-+ if (newcnst && constprop_register (insn, x, newcnst, alter_jumps))
-+ {
-+ /* If we find a case where we can't fix the retval REG_EQUAL notes
-+ match the new register, we either have to abandom this replacement
-+ or fix delete_trivially_dead_insns to preserve the setting insn,
-+ or make it delete the REG_EUAQL note, and fix up all passes that
-+ require the REG_EQUAL note there. */
-+ if (!adjust_libcall_notes (x, newcnst, insn, libcall_sp))
-+ abort ();
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file, "LOCAL CONST-PROP: Replacing reg %d in ",
-+ REGNO (x));
-+ fprintf (gcse_file, "insn %d with constant ",
-+ INSN_UID (insn));
-+ print_rtl (gcse_file, newcnst);
-+ fprintf (gcse_file, "\n");
-+ }
-+ const_prop_count++;
-+ return true;
-+ }
-+ else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
-+ {
-+ adjust_libcall_notes (x, newreg, insn, libcall_sp);
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file,
-+ "LOCAL COPY-PROP: Replacing reg %d in insn %d",
-+ REGNO (x), INSN_UID (insn));
-+ fprintf (gcse_file, " with reg %d\n", REGNO (newreg));
-+ }
-+ copy_prop_count++;
-+ return true;
-+ }
-+ }
-+ return false;
-+}
-+
-+/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall;
-+ their REG_EQUAL notes need updating to reflect that OLDREG has been
-+ replaced with NEWVAL in INSN. Return true if all substitutions could
-+ be made. */
-+static bool
-+adjust_libcall_notes (oldreg, newval, insn, libcall_sp)
-+ rtx oldreg, newval, insn, *libcall_sp;
-+{
-+ rtx end;
-+
-+ while ((end = *libcall_sp++))
-+ {
-+ rtx note = find_reg_equal_equiv_note (end);
-+
-+ if (! note)
-+ continue;
-+
-+ if (REG_P (newval))
-+ {
-+ if (reg_set_between_p (newval, PREV_INSN (insn), end))
-+ {
-+ do
-+ {
-+ note = find_reg_equal_equiv_note (end);
-+ if (! note)
-+ continue;
-+ if (reg_mentioned_p (newval, XEXP (note, 0)))
-+ return false;
-+ }
-+ while ((end = *libcall_sp++));
-+ return true;
-+ }
-+ }
-+ XEXP (note, 0) = replace_rtx (XEXP (note, 0), oldreg, newval);
-+ insn = end;
-+ }
-+ return true;
-+}
-+
-+#define MAX_NESTED_LIBCALLS 9
-+
-+static void
-+local_cprop_pass (alter_jumps)
-+ int alter_jumps;
-+{
-+ rtx insn;
-+ struct reg_use *reg_used;
-+ rtx libcall_stack[MAX_NESTED_LIBCALLS + 1], *libcall_sp;
-+ bool changed = false;
-+
-+ cselib_init ();
-+ libcall_sp = &libcall_stack[MAX_NESTED_LIBCALLS];
-+ *libcall_sp = 0;
-+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-+ {
-+ if (INSN_P (insn))
-+ {
-+ rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
-+
-+ if (note)
-+ {
-+ if (libcall_sp == libcall_stack)
-+ abort ();
-+ *--libcall_sp = XEXP (note, 0);
-+ }
-+ note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
-+ if (note)
-+ libcall_sp++;
-+ note = find_reg_equal_equiv_note (insn);
-+ do
-+ {
-+ reg_use_count = 0;
-+ note_uses (&PATTERN (insn), local_cprop_find_used_regs, NULL);
-+ if (note)
-+ local_cprop_find_used_regs (&XEXP (note, 0), NULL);
-+
-+ for (reg_used = ®_use_table[0]; reg_use_count > 0;
-+ reg_used++, reg_use_count--)
-+ if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps,
-+ libcall_sp))
-+ {
-+ changed = true;
-+ break;
-+ }
-+ }
-+ while (reg_use_count);
-+ }
-+ cselib_process_insn (insn);
-+ }
-+ cselib_finish ();
-+ /* Global analysis may get into infinite loops for unreachable blocks. */
-+ if (changed && alter_jumps)
-+ {
-+ delete_unreachable_blocks ();
-+ free_reg_set_mem ();
-+ alloc_reg_set_mem (max_reg_num ());
-+ compute_sets (get_insns ());
-+ }
-+}
-+
-+/* Forward propagate copies. This includes copies and constants. Return
-+ nonzero if a change was made. */
-+
-+static int
-+cprop (alter_jumps)
-+ int alter_jumps;
-+{
-+ int changed;
-+ basic_block bb;
-+ rtx insn;
-+
-+ /* Note we start at block 1. */
-+ if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
-+ {
-+ if (gcse_file != NULL)
-+ fprintf (gcse_file, "\n");
-+ return 0;
-+ }
-+
-+ changed = 0;
-+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb)
-+ {
-+ /* Reset tables used to keep track of what's still valid [since the
-+ start of the block]. */
-+ reset_opr_set_tables ();
-+
-+ for (insn = bb->head;
-+ insn != NULL && insn != NEXT_INSN (bb->end);
-+ insn = NEXT_INSN (insn))
-+ if (INSN_P (insn))
-+ {
-+ changed |= cprop_insn (insn, alter_jumps);
-+
-+ /* Keep track of everything modified by this insn. */
-+ /* ??? Need to be careful w.r.t. mods done to INSN. Don't
-+ call mark_oprs_set if we turned the insn into a NOTE. */
-+ if (GET_CODE (insn) != NOTE)
-+ mark_oprs_set (insn);
-+ }
-+ }
-+
-+ if (gcse_file != NULL)
-+ fprintf (gcse_file, "\n");
-+
-+ return changed;
-+}
-+
-+/* Perform one copy/constant propagation pass.
-+ F is the first insn in the function.
-+ PASS is the pass count. */
-+
-+static int
-+one_cprop_pass (pass, alter_jumps)
-+ int pass;
-+ int alter_jumps;
-+{
-+ int changed = 0;
-+
-+ const_prop_count = 0;
-+ copy_prop_count = 0;
-+
-+ local_cprop_pass (alter_jumps);
-+
-+ alloc_hash_table (max_cuid, &set_hash_table, 1);
-+ compute_hash_table (&set_hash_table);
-+ if (gcse_file)
-+ dump_hash_table (gcse_file, "SET", &set_hash_table);
-+ if (set_hash_table.n_elems > 0)
-+ {
-+ alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
-+ compute_cprop_data ();
-+ changed = cprop (alter_jumps);
-+ if (alter_jumps)
-+ changed |= bypass_conditional_jumps ();
-+ free_cprop_mem ();
-+ }
-+
-+ free_hash_table (&set_hash_table);
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "CPROP of %s, pass %d: %d bytes needed, ",
-+ current_function_name, pass, bytes_used);
-+ fprintf (gcse_file, "%d const props, %d copy props\n\n",
-+ const_prop_count, copy_prop_count);
-+ }
-+ /* Global analysis may get into infinite loops for unreachable blocks. */
-+ if (changed && alter_jumps)
-+ delete_unreachable_blocks ();
-+
-+ return changed;
-+}
-+\f
-+/* Bypass conditional jumps. */
-+
-+/* Find a set of REGNO to a constant that is available at the end of basic
-+ block BB. Returns NULL if no such set is found. Based heavily upon
-+ find_avail_set. */
-+
-+static struct expr *
-+find_bypass_set (regno, bb)
-+ int regno;
-+ int bb;
-+{
-+ struct expr *result = 0;
-+
-+ for (;;)
-+ {
-+ rtx src;
-+ struct expr *set = lookup_set (regno, NULL_RTX, &set_hash_table);
-+
-+ while (set)
-+ {
-+ if (TEST_BIT (cprop_avout[bb], set->bitmap_index))
-+ break;
-+ set = next_set (regno, set);
-+ }
-+
-+ if (set == 0)
-+ break;
-+
-+ if (GET_CODE (set->expr) != SET)
-+ abort ();
-+
-+ src = SET_SRC (set->expr);
-+ if (CONSTANT_P (src))
-+ result = set;
-+
-+ if (GET_CODE (src) != REG)
-+ break;
-+
-+ regno = REGNO (src);
-+ }
-+ return result;
-+}
-+
-+
-+/* Subroutine of bypass_block that checks whether a pseudo is killed by
-+ any of the instructions inserted on an edge. Jump bypassing places
-+ condition code setters on CFG edges using insert_insn_on_edge. This
-+ function is required to check that our data flow analysis is still
-+ valid prior to commit_edge_insertions. */
-+
-+static bool
-+reg_killed_on_edge (reg, e)
-+ rtx reg;
-+ edge e;
-+{
-+ rtx insn;
-+
-+ for (insn = e->insns; insn; insn = NEXT_INSN (insn))
-+ if (INSN_P (insn) && reg_set_p (reg, insn))
-+ return true;
-+
-+ return false;
-+}
-+
-+/* Subroutine of bypass_conditional_jumps that attempts to bypass the given
-+ basic block BB which has more than one predecessor. If not NULL, SETCC
-+ is the first instruction of BB, which is immediately followed by JUMP_INSN
-+ JUMP. Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
-+ Returns nonzero if a change was made.
-+
-+ During the jump bypassing pass, we may place copies of SETCC instuctions
-+ on CFG edges. The following routine must be careful to pay attention to
-+ these inserted insns when performing its transformations. */
-+
-+static int
-+bypass_block (bb, setcc, jump)
-+ basic_block bb;
-+ rtx setcc, jump;
-+{
-+ rtx insn, note;
-+ edge e, enext, edest;
-+ int i, change;
-+
-+ insn = (setcc != NULL) ? setcc : jump;
-+
-+ /* Determine set of register uses in INSN. */
-+ reg_use_count = 0;
-+ note_uses (&PATTERN (insn), find_used_regs, NULL);
-+ note = find_reg_equal_equiv_note (insn);
-+ if (note)
-+ find_used_regs (&XEXP (note, 0), NULL);
-+
-+ change = 0;
-+ for (e = bb->pred; e; e = enext)
-+ {
-+ enext = e->pred_next;
-+ for (i = 0; i < reg_use_count; i++)
-+ {
-+ struct reg_use *reg_used = ®_use_table[i];
-+ unsigned int regno = REGNO (reg_used->reg_rtx);
-+ basic_block dest, old_dest;
-+ struct expr *set;
-+ rtx src, new;
-+
-+ if (regno >= max_gcse_regno)
-+ continue;
-+
-+ set = find_bypass_set (regno, e->src->index);
-+
-+ if (! set)
-+ continue;
-+
-+ /* Check the data flow is valid after edge insertions. */
-+ if (e->insns && reg_killed_on_edge (reg_used->reg_rtx, e))
-+ continue;
-+
-+ src = SET_SRC (pc_set (jump));
-+
-+ if (setcc != NULL)
-+ src = simplify_replace_rtx (src,
-+ SET_DEST (PATTERN (setcc)),
-+ SET_SRC (PATTERN (setcc)));
-+
-+ new = simplify_replace_rtx (src, reg_used->reg_rtx,
-+ SET_SRC (set->expr));
-+
-+ /* Jump bypassing may have already placed instructions on
-+ edges of the CFG. We can't bypass an outgoing edge that
-+ has instructions associated with it, as these insns won't
-+ get executed if the incoming edge is redirected. */
-+
-+ if (new == pc_rtx)
-+ {
-+ edest = FALLTHRU_EDGE (bb);
-+ dest = edest->insns ? NULL : edest->dest;
-+ }
-+ else if (GET_CODE (new) == LABEL_REF)
-+ {
-+ dest = BLOCK_FOR_INSN (XEXP (new, 0));
-+ /* Don't bypass edges containing instructions. */
-+ for (edest = bb->succ; edest; edest = edest->succ_next)
-+ if (edest->dest == dest && edest->insns)
-+ {
-+ dest = NULL;
-+ break;
-+ }
-+ }
-+ else
-+ dest = NULL;
-+
-+ /* Once basic block indices are stable, we should be able
-+ to use redirect_edge_and_branch_force instead. */
-+ old_dest = e->dest;
-+ if (dest != NULL && dest != old_dest
-+ && redirect_edge_and_branch (e, dest))
-+ {
-+ /* Copy the register setter to the redirected edge.
-+ Don't copy CC0 setters, as CC0 is dead after jump. */
-+ if (setcc)
-+ {
-+ rtx pat = PATTERN (setcc);
-+ if (!CC0_P (SET_DEST (pat)))
-+ insert_insn_on_edge (copy_insn (pat), e);
-+ }
-+
-+ if (gcse_file != NULL)
-+ {
-+ fprintf (gcse_file, "JUMP-BYPASS: Proved reg %d in jump_insn %d equals constant ",
-+ regno, INSN_UID (jump));
-+ print_rtl (gcse_file, SET_SRC (set->expr));
-+ fprintf (gcse_file, "\nBypass edge from %d->%d to %d\n",
-+ e->src->index, old_dest->index, dest->index);
-+ }
-+ change = 1;
-+ break;
-+ }
-+ }
-+ }
-+ return change;
-+}
-+
-+/* Find basic blocks with more than one predecessor that only contain a
-+ single conditional jump. If the result of the comparison is known at
-+ compile-time from any incoming edge, redirect that edge to the
-+ appropriate target. Returns nonzero if a change was made. */
-+
-+static int
-+bypass_conditional_jumps ()
-+{
-+ basic_block bb;
-+ int changed;
-+ rtx setcc;
-+ rtx insn;
-+ rtx dest;
-+
-+ /* Note we start at block 1. */
-+ if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
-+ return 0;
-+
-+ changed = 0;
-+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb,
-+ EXIT_BLOCK_PTR, next_bb)
-+ {
-+ /* Check for more than one predecessor. */
-+ if (bb->pred && bb->pred->pred_next)
-+ {
-+ setcc = NULL_RTX;
-+ for (insn = bb->head;
-+ insn != NULL && insn != NEXT_INSN (bb->end);
-+ insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) == INSN)
-+ {
-+ if (setcc)
-+ break;
-+ if (GET_CODE (PATTERN (insn)) != SET)
-+ break;
-+
-+ dest = SET_DEST (PATTERN (insn));
-+ if (REG_P (dest) || CC0_P (dest))
-+ setcc = insn;
-+ else
-+ break;
-+ }
-+ else if (GET_CODE (insn) == JUMP_INSN)
-+ {
-+ if (any_condjump_p (insn) && onlyjump_p (insn))
-+ changed |= bypass_block (bb, setcc, insn);
-+ break;
-+ }
-+ else if (INSN_P (insn))
-+ break;
-+ }
-+ }
-+
-+ /* If we bypassed any register setting insns, we inserted a
-+ copy on the redirected edge. These need to be commited. */
-+ if (changed)
-+ commit_edge_insertions();
-+
-+ return changed;
-+}
-+\f
-+/* Compute PRE+LCM working variables. */
-+
-+/* Local properties of expressions. */
-+/* Nonzero for expressions that are transparent in the block. */
-+static sbitmap *transp;
-+
-+/* Nonzero for expressions that are transparent at the end of the block.
-+ This is only zero for expressions killed by abnormal critical edge
-+ created by a calls. */
-+static sbitmap *transpout;
-+
-+/* Nonzero for expressions that are computed (available) in the block. */
-+static sbitmap *comp;
-+
-+/* Nonzero for expressions that are locally anticipatable in the block. */
-+static sbitmap *antloc;
-+
-+/* Nonzero for expressions where this block is an optimal computation
-+ point. */
-+static sbitmap *pre_optimal;
-+
-+/* Nonzero for expressions which are redundant in a particular block. */
-+static sbitmap *pre_redundant;
-+
-+/* Nonzero for expressions which should be inserted on a specific edge. */
-+static sbitmap *pre_insert_map;
-+
-+/* Nonzero for expressions which should be deleted in a specific block. */
-+static sbitmap *pre_delete_map;
-+
-+/* Contains the edge_list returned by pre_edge_lcm. */
-+static struct edge_list *edge_list;
-+
-+/* Redundant insns. */
-+static sbitmap pre_redundant_insns;
-+
-+/* Allocate vars used for PRE analysis. */
-+
-+static void
-+alloc_pre_mem (n_blocks, n_exprs)
-+ int n_blocks, n_exprs;
-+{
-+ transp = sbitmap_vector_alloc (n_blocks, n_exprs);
-+ comp = sbitmap_vector_alloc (n_blocks, n_exprs);
-+ antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
-+
-+ pre_optimal = NULL;
-+ pre_redundant = NULL;
-+ pre_insert_map = NULL;
-+ pre_delete_map = NULL;
-+ ae_in = NULL;
-+ ae_out = NULL;
-+ ae_kill = sbitmap_vector_alloc (n_blocks, n_exprs);
-+
-+ /* pre_insert and pre_delete are allocated later. */
-+}
-+
-+/* Free vars used for PRE analysis. */
-+
-+static void
-+free_pre_mem ()
-+{
-+ sbitmap_vector_free (transp);
-+ sbitmap_vector_free (comp);
-+
-+ /* ANTLOC and AE_KILL are freed just after pre_lcm finishes. */
-+
-+ if (pre_optimal)
-+ sbitmap_vector_free (pre_optimal);
-+ if (pre_redundant)
-+ sbitmap_vector_free (pre_redundant);
-+ if (pre_insert_map)
-+ sbitmap_vector_free (pre_insert_map);
-+ if (pre_delete_map)
-+ sbitmap_vector_free (pre_delete_map);
-+ if (ae_in)
-+ sbitmap_vector_free (ae_in);
-+ if (ae_out)
-+ sbitmap_vector_free (ae_out);
-+
-+ transp = comp = NULL;
-+ pre_optimal = pre_redundant = pre_insert_map = pre_delete_map = NULL;
-+ ae_in = ae_out = NULL;
-+}
-+
-+/* Top level routine to do the dataflow analysis needed by PRE. */
-+
-+static void
-+compute_pre_data ()
-+{
-+ sbitmap trapping_expr;
-+ basic_block bb;
-+ unsigned int ui;
-+
-+ compute_local_properties (transp, comp, antloc, &expr_hash_table);
-+ sbitmap_vector_zero (ae_kill, last_basic_block);
-+
-+ /* Collect expressions which might trap. */
-+ trapping_expr = sbitmap_alloc (expr_hash_table.n_elems);
-+ sbitmap_zero (trapping_expr);
-+ for (ui = 0; ui < expr_hash_table.size; ui++)
-+ {
-+ struct expr *e;
-+ for (e = expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash)
-+ if (may_trap_p (e->expr))
-+ SET_BIT (trapping_expr, e->bitmap_index);
-+ }
-+
-+ /* Compute ae_kill for each basic block using:
-+
-+ ~(TRANSP | COMP)
-+
-+ This is significantly faster than compute_ae_kill. */
-+
-+ FOR_EACH_BB (bb)
-+ {
-+ edge e;
-+
-+ /* If the current block is the destination of an abnormal edge, we
-+ kill all trapping expressions because we won't be able to properly
-+ place the instruction on the edge. So make them neither
-+ anticipatable nor transparent. This is fairly conservative. */
-+ for (e = bb->pred; e ; e = e->pred_next)
-+ if (e->flags & EDGE_ABNORMAL)
-+ {
-+ sbitmap_difference (antloc[bb->index], antloc[bb->index], trapping_expr);
-+ sbitmap_difference (transp[bb->index], transp[bb->index], trapping_expr);
-+ break;
-+ }
-+
-+ sbitmap_a_or_b (ae_kill[bb->index], transp[bb->index], comp[bb->index]);
-+ sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]);
-+ }
-+
-+ edge_list = pre_edge_lcm (gcse_file, expr_hash_table.n_elems, transp, comp, antloc,
-+ ae_kill, &pre_insert_map, &pre_delete_map);
-+ sbitmap_vector_free (antloc);
-+ antloc = NULL;
-+ sbitmap_vector_free (ae_kill);
-+ ae_kill = NULL;
-+ sbitmap_free (trapping_expr);
-+}
-+\f
-+/* PRE utilities */
-+
-+/* Return nonzero if an occurrence of expression EXPR in OCCR_BB would reach
-+ block BB.
-+
-+ VISITED is a pointer to a working buffer for tracking which BB's have
-+ been visited. It is NULL for the top-level call.
-+
-+ We treat reaching expressions that go through blocks containing the same
-+ reaching expression as "not reaching". E.g. if EXPR is generated in blocks
-+ 2 and 3, INSN is in block 4, and 2->3->4, we treat the expression in block
-+ 2 as not reaching. The intent is to improve the probability of finding
-+ only one reaching expression and to reduce register lifetimes by picking
-+ the closest such expression. */
-+
-+static int
-+pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited)
-+ basic_block occr_bb;
-+ struct expr *expr;
-+ basic_block bb;
-+ char *visited;
-+{
-+ edge pred;
-+
-+ for (pred = bb->pred; pred != NULL; pred = pred->pred_next)
-+ {
-+ basic_block pred_bb = pred->src;
-+
-+ if (pred->src == ENTRY_BLOCK_PTR
-+ /* Has predecessor has already been visited? */
-+ || visited[pred_bb->index])
-+ ;/* Nothing to do. */
-+
-+ /* Does this predecessor generate this expression? */
-+ else if (TEST_BIT (comp[pred_bb->index], expr->bitmap_index))
-+ {
-+ /* Is this the occurrence we're looking for?
-+ Note that there's only one generating occurrence per block
-+ so we just need to check the block number. */
-+ if (occr_bb == pred_bb)
-+ return 1;
-+
-+ visited[pred_bb->index] = 1;
-+ }
-+ /* Ignore this predecessor if it kills the expression. */
-+ else if (! TEST_BIT (transp[pred_bb->index], expr->bitmap_index))
-+ visited[pred_bb->index] = 1;
-+
-+ /* Neither gen nor kill. */
-+ else
-+ {
-+ visited[pred_bb->index] = 1;
-+ if (pre_expr_reaches_here_p_work (occr_bb, expr, pred_bb, visited))
-+ return 1;
-+ }
-+ }
-+
-+ /* All paths have been checked. */
-+ return 0;
-+}
-+
-+/* The wrapper for pre_expr_reaches_here_work that ensures that any
-+ memory allocated for that function is returned. */
-+
-+static int
-+pre_expr_reaches_here_p (occr_bb, expr, bb)
-+ basic_block occr_bb;
-+ struct expr *expr;
-+ basic_block bb;
-+{
-+ int rval;
-+ char *visited = (char *) xcalloc (last_basic_block, 1);
-+
-+ rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited);
-+
-+ free (visited);
-+ return rval;
-+}
-+\f
-+
-+/* Given an expr, generate RTL which we can insert at the end of a BB,
-+ or on an edge. Set the block number of any insns generated to
-+ the value of BB. */
-+
-+static rtx
-+process_insert_insn (expr)
-+ struct expr *expr;
-+{
-+ rtx reg = expr->reaching_reg;
-+ rtx exp = copy_rtx (expr->expr);
-+ rtx pat;
-+
-+ start_sequence ();
-+
-+ /* If the expression is something that's an operand, like a constant,
-+ just copy it to a register. */
-+ if (general_operand (exp, GET_MODE (reg)))
-+ emit_move_insn (reg, exp);
-+
-+ /* Otherwise, make a new insn to compute this expression and make sure the
-+ insn will be recognized (this also adds any needed CLOBBERs). Copy the
-+ expression to make sure we don't have any sharing issues. */
-+ else if (insn_invalid_p (emit_insn (gen_rtx_SET (VOIDmode, reg, exp))))
-+ abort ();
-+
-+ pat = get_insns ();
-+ end_sequence ();
-+
-+ return pat;
-+}
-+
-+/* Add EXPR to the end of basic block BB.
-+
-+ This is used by both the PRE and code hoisting.
-+
-+ For PRE, we want to verify that the expr is either transparent
-+ or locally anticipatable in the target block. This check makes
-+ no sense for code hoisting. */
-+
-+static void
-+insert_insn_end_bb (expr, bb, pre)
-+ struct expr *expr;
-+ basic_block bb;
-+ int pre;
-+{
-+ rtx insn = bb->end;
-+ rtx new_insn;
-+ rtx reg = expr->reaching_reg;
-+ int regno = REGNO (reg);
-+ rtx pat, pat_end;
-+
-+ pat = process_insert_insn (expr);
-+ if (pat == NULL_RTX || ! INSN_P (pat))
-+ abort ();
-+
-+ pat_end = pat;
-+ while (NEXT_INSN (pat_end) != NULL_RTX)
-+ pat_end = NEXT_INSN (pat_end);
-+
-+ /* If the last insn is a jump, insert EXPR in front [taking care to
-+ handle cc0, etc. properly]. Similary we need to care trapping
-+ instructions in presence of non-call exceptions. */
-+
-+ if (GET_CODE (insn) == JUMP_INSN
-+ || (GET_CODE (insn) == INSN
-+ && (bb->succ->succ_next || (bb->succ->flags & EDGE_ABNORMAL))))
-+ {
-+#ifdef HAVE_cc0
-+ rtx note;
-+#endif
-+ /* It should always be the case that we can put these instructions
-+ anywhere in the basic block with performing PRE optimizations.
-+ Check this. */
-+ if (GET_CODE (insn) == INSN && pre
-+ && !TEST_BIT (antloc[bb->index], expr->bitmap_index)
-+ && !TEST_BIT (transp[bb->index], expr->bitmap_index))
-+ abort ();
-+
-+ /* If this is a jump table, then we can't insert stuff here. Since
-+ we know the previous real insn must be the tablejump, we insert
-+ the new instruction just before the tablejump. */
-+ if (GET_CODE (PATTERN (insn)) == ADDR_VEC
-+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
-+ insn = prev_real_insn (insn);
-+
-+#ifdef HAVE_cc0
-+ /* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts
-+ if cc0 isn't set. */
-+ note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
-+ if (note)
-+ insn = XEXP (note, 0);
-+ else
-+ {
-+ rtx maybe_cc0_setter = prev_nonnote_insn (insn);
-+ if (maybe_cc0_setter
-+ && INSN_P (maybe_cc0_setter)
-+ && sets_cc0_p (PATTERN (maybe_cc0_setter)))
-+ insn = maybe_cc0_setter;
-+ }
-+#endif
-+ /* FIXME: What if something in cc0/jump uses value set in new insn? */
-+ new_insn = emit_insn_before (pat, insn);
-+ }
-+
-+ /* Likewise if the last insn is a call, as will happen in the presence
-+ of exception handling. */
-+ else if (GET_CODE (insn) == CALL_INSN
-+ && (bb->succ->succ_next || (bb->succ->flags & EDGE_ABNORMAL)))
-+ {
-+ /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
-+ we search backward and place the instructions before the first
-+ parameter is loaded. Do this for everyone for consistency and a
-+ presumtion that we'll get better code elsewhere as well.
-+
-+ It should always be the case that we can put these instructions
-+ anywhere in the basic block with performing PRE optimizations.
-+ Check this. */
-+
-+ if (pre
-+ && !TEST_BIT (antloc[bb->index], expr->bitmap_index)
-+ && !TEST_BIT (transp[bb->index], expr->bitmap_index))
-+ abort ();
-+
-+ /* Since different machines initialize their parameter registers
-+ in different orders, assume nothing. Collect the set of all
-+ parameter registers. */
-+ insn = find_first_parameter_load (insn, bb->head);
-+
-+ /* If we found all the parameter loads, then we want to insert
-+ before the first parameter load.
-+
-+ If we did not find all the parameter loads, then we might have
-+ stopped on the head of the block, which could be a CODE_LABEL.
-+ If we inserted before the CODE_LABEL, then we would be putting
-+ the insn in the wrong basic block. In that case, put the insn
-+ after the CODE_LABEL. Also, respect NOTE_INSN_BASIC_BLOCK. */
-+ while (GET_CODE (insn) == CODE_LABEL
-+ || NOTE_INSN_BASIC_BLOCK_P (insn))
-+ insn = NEXT_INSN (insn);
-+
-+ new_insn = emit_insn_before (pat, insn);
-+ }
-+ else
-+ new_insn = emit_insn_after (pat, insn);
-+
-+ while (1)
-+ {
-+ if (INSN_P (pat))
-+ {
-+ add_label_notes (PATTERN (pat), new_insn);
-+ note_stores (PATTERN (pat), record_set_info, pat);
-+ }
-+ if (pat == pat_end)
-+ break;
-+ pat = NEXT_INSN (pat);
-+ }
-+
-+ gcse_create_count++;
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "PRE/HOIST: end of bb %d, insn %d, ",
-+ bb->index, INSN_UID (new_insn));
-+ fprintf (gcse_file, "copying expression %d to reg %d\n",
-+ expr->bitmap_index, regno);
-+ }
-+}
-+
-+/* Insert partially redundant expressions on edges in the CFG to make
-+ the expressions fully redundant. */
-+
-+static int
-+pre_edge_insert (edge_list, index_map)
-+ struct edge_list *edge_list;
-+ struct expr **index_map;
-+{
-+ int e, i, j, num_edges, set_size, did_insert = 0;
-+ sbitmap *inserted;
-+
-+ /* Where PRE_INSERT_MAP is nonzero, we add the expression on that edge
-+ if it reaches any of the deleted expressions. */
-+
-+ set_size = pre_insert_map[0]->size;
-+ num_edges = NUM_EDGES (edge_list);
-+ inserted = sbitmap_vector_alloc (num_edges, expr_hash_table.n_elems);
-+ sbitmap_vector_zero (inserted, num_edges);
-+
-+ for (e = 0; e < num_edges; e++)
-+ {
-+ int indx;
-+ basic_block bb = INDEX_EDGE_PRED_BB (edge_list, e);
-+
-+ for (i = indx = 0; i < set_size; i++, indx += SBITMAP_ELT_BITS)
-+ {
-+ SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i];
-+
-+ for (j = indx; insert && j < (int) expr_hash_table.n_elems; j++, insert >>= 1)
-+ if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX)
-+ {
-+ struct expr *expr = index_map[j];
-+ struct occr *occr;
-+
-+ /* Now look at each deleted occurrence of this expression. */
-+ for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
-+ {
-+ if (! occr->deleted_p)
-+ continue;
-+
-+ /* Insert this expression on this edge if if it would
-+ reach the deleted occurrence in BB. */
-+ if (!TEST_BIT (inserted[e], j))
-+ {
-+ rtx insn;
-+ edge eg = INDEX_EDGE (edge_list, e);
-+
-+ /* We can't insert anything on an abnormal and
-+ critical edge, so we insert the insn at the end of
-+ the previous block. There are several alternatives
-+ detailed in Morgans book P277 (sec 10.5) for
-+ handling this situation. This one is easiest for
-+ now. */
-+
-+ if ((eg->flags & EDGE_ABNORMAL) == EDGE_ABNORMAL)
-+ insert_insn_end_bb (index_map[j], bb, 0);
-+ else
-+ {
-+ insn = process_insert_insn (index_map[j]);
-+ insert_insn_on_edge (insn, eg);
-+ }
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "PRE/HOIST: edge (%d,%d), ",
-+ bb->index,
-+ INDEX_EDGE_SUCC_BB (edge_list, e)->index);
-+ fprintf (gcse_file, "copy expression %d\n",
-+ expr->bitmap_index);
-+ }
-+
-+ update_ld_motion_stores (expr);
-+ SET_BIT (inserted[e], j);
-+ did_insert = 1;
-+ gcse_create_count++;
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ sbitmap_vector_free (inserted);
-+ return did_insert;
-+}
-+
-+/* Copy the result of INSN to REG. INDX is the expression number. */
-+
-+static void
-+pre_insert_copy_insn (expr, insn)
-+ struct expr *expr;
-+ rtx insn;
-+{
-+ rtx reg = expr->reaching_reg;
-+ int regno = REGNO (reg);
-+ int indx = expr->bitmap_index;
-+ rtx set = single_set (insn);
-+ rtx new_insn;
-+
-+ if (!set)
-+ abort ();
-+
-+ new_insn = emit_insn_after (gen_move_insn (reg, SET_DEST (set)), insn);
-+
-+ /* Keep register set table up to date. */
-+ record_one_set (regno, new_insn);
-+
-+ gcse_create_count++;
-+
-+ if (gcse_file)
-+ fprintf (gcse_file,
-+ "PRE: bb %d, insn %d, copy expression %d in insn %d to reg %d\n",
-+ BLOCK_NUM (insn), INSN_UID (new_insn), indx,
-+ INSN_UID (insn), regno);
-+ update_ld_motion_stores (expr);
-+}
-+
-+/* Copy available expressions that reach the redundant expression
-+ to `reaching_reg'. */
-+
-+static void
-+pre_insert_copies ()
-+{
-+ unsigned int i;
-+ struct expr *expr;
-+ struct occr *occr;
-+ struct occr *avail;
-+
-+ /* For each available expression in the table, copy the result to
-+ `reaching_reg' if the expression reaches a deleted one.
-+
-+ ??? The current algorithm is rather brute force.
-+ Need to do some profiling. */
-+
-+ for (i = 0; i < expr_hash_table.size; i++)
-+ for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
-+ {
-+ /* If the basic block isn't reachable, PPOUT will be TRUE. However,
-+ we don't want to insert a copy here because the expression may not
-+ really be redundant. So only insert an insn if the expression was
-+ deleted. This test also avoids further processing if the
-+ expression wasn't deleted anywhere. */
-+ if (expr->reaching_reg == NULL)
-+ continue;
-+
-+ for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
-+ {
-+ if (! occr->deleted_p)
-+ continue;
-+
-+ for (avail = expr->avail_occr; avail != NULL; avail = avail->next)
-+ {
-+ rtx insn = avail->insn;
-+
-+ /* No need to handle this one if handled already. */
-+ if (avail->copied_p)
-+ continue;
-+
-+ /* Don't handle this one if it's a redundant one. */
-+ if (TEST_BIT (pre_redundant_insns, INSN_CUID (insn)))
-+ continue;
-+
-+ /* Or if the expression doesn't reach the deleted one. */
-+ if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn),
-+ expr,
-+ BLOCK_FOR_INSN (occr->insn)))
-+ continue;
-+
-+ /* Copy the result of avail to reaching_reg. */
-+ pre_insert_copy_insn (expr, insn);
-+ avail->copied_p = 1;
-+ }
-+ }
-+ }
-+}
-+
-+/* Emit move from SRC to DEST noting the equivalence with expression computed
-+ in INSN. */
-+static rtx
-+gcse_emit_move_after (src, dest, insn)
-+ rtx src, dest, insn;
-+{
-+ rtx new;
-+ rtx set = single_set (insn), set2;
-+ rtx note;
-+ rtx eqv;
-+
-+ /* This should never fail since we're creating a reg->reg copy
-+ we've verified to be valid. */
-+
-+ new = emit_insn_after (gen_move_insn (dest, src), insn);
-+
-+ /* Note the equivalence for local CSE pass. */
-+ set2 = single_set (new);
-+ if (!set2 || !rtx_equal_p (SET_DEST (set2), dest))
-+ return new;
-+ if ((note = find_reg_equal_equiv_note (insn)))
-+ eqv = XEXP (note, 0);
-+ else
-+ eqv = SET_SRC (set);
-+
-+ set_unique_reg_note (new, REG_EQUAL, copy_insn_1 (eqv));
-+
-+ return new;
-+}
-+
-+/* Delete redundant computations.
-+ Deletion is done by changing the insn to copy the `reaching_reg' of
-+ the expression into the result of the SET. It is left to later passes
-+ (cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it.
-+
-+ Returns nonzero if a change is made. */
-+
-+static int
-+pre_delete ()
-+{
-+ unsigned int i;
-+ int changed;
-+ struct expr *expr;
-+ struct occr *occr;
-+
-+ changed = 0;
-+ for (i = 0; i < expr_hash_table.size; i++)
-+ for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
-+ {
-+ int indx = expr->bitmap_index;
-+
-+ /* We only need to search antic_occr since we require
-+ ANTLOC != 0. */
-+
-+ for (occr = expr->antic_occr; occr != NULL; occr = occr->next)
-+ {
-+ rtx insn = occr->insn;
-+ rtx set;
-+ basic_block bb = BLOCK_FOR_INSN (insn);
-+
-+ if (TEST_BIT (pre_delete_map[bb->index], indx))
-+ {
-+ set = single_set (insn);
-+ if (! set)
-+ abort ();
-+
-+ /* Create a pseudo-reg to store the result of reaching
-+ expressions into. Get the mode for the new pseudo from
-+ the mode of the original destination pseudo. */
-+ if (expr->reaching_reg == NULL)
-+ expr->reaching_reg
-+ = gen_reg_rtx (GET_MODE (SET_DEST (set)));
-+
-+ gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
-+ delete_insn (insn);
-+ occr->deleted_p = 1;
-+ SET_BIT (pre_redundant_insns, INSN_CUID (insn));
-+ changed = 1;
-+ gcse_subst_count++;
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file,
-+ "PRE: redundant insn %d (expression %d) in ",
-+ INSN_UID (insn), indx);
-+ fprintf (gcse_file, "bb %d, reaching reg is %d\n",
-+ bb->index, REGNO (expr->reaching_reg));
-+ }
-+ }
-+ }
-+ }
-+
-+ return changed;
-+}
-+
-+/* Perform GCSE optimizations using PRE.
-+ This is called by one_pre_gcse_pass after all the dataflow analysis
-+ has been done.
-+
-+ This is based on the original Morel-Renvoise paper Fred Chow's thesis, and
-+ lazy code motion from Knoop, Ruthing and Steffen as described in Advanced
-+ Compiler Design and Implementation.
-+
-+ ??? A new pseudo reg is created to hold the reaching expression. The nice
-+ thing about the classical approach is that it would try to use an existing
-+ reg. If the register can't be adequately optimized [i.e. we introduce
-+ reload problems], one could add a pass here to propagate the new register
-+ through the block.
-+
-+ ??? We don't handle single sets in PARALLELs because we're [currently] not
-+ able to copy the rest of the parallel when we insert copies to create full
-+ redundancies from partial redundancies. However, there's no reason why we
-+ can't handle PARALLELs in the cases where there are no partial
-+ redundancies. */
-+
-+static int
-+pre_gcse ()
-+{
-+ unsigned int i;
-+ int did_insert, changed;
-+ struct expr **index_map;
-+ struct expr *expr;
-+
-+ /* Compute a mapping from expression number (`bitmap_index') to
-+ hash table entry. */
-+
-+ index_map = (struct expr **) xcalloc (expr_hash_table.n_elems, sizeof (struct expr *));
-+ for (i = 0; i < expr_hash_table.size; i++)
-+ for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
-+ index_map[expr->bitmap_index] = expr;
-+
-+ /* Reset bitmap used to track which insns are redundant. */
-+ pre_redundant_insns = sbitmap_alloc (max_cuid);
-+ sbitmap_zero (pre_redundant_insns);
-+
-+ /* Delete the redundant insns first so that
-+ - we know what register to use for the new insns and for the other
-+ ones with reaching expressions
-+ - we know which insns are redundant when we go to create copies */
-+
-+ changed = pre_delete ();
-+
-+ did_insert = pre_edge_insert (edge_list, index_map);
-+
-+ /* In other places with reaching expressions, copy the expression to the
-+ specially allocated pseudo-reg that reaches the redundant expr. */
-+ pre_insert_copies ();
-+ if (did_insert)
-+ {
-+ commit_edge_insertions ();
-+ changed = 1;
-+ }
-+
-+ free (index_map);
-+ sbitmap_free (pre_redundant_insns);
-+ return changed;
-+}
-+
-+/* Top level routine to perform one PRE GCSE pass.
-+
-+ Return nonzero if a change was made. */
-+
-+static int
-+one_pre_gcse_pass (pass)
-+ int pass;
-+{
-+ int changed = 0;
-+
-+ gcse_subst_count = 0;
-+ gcse_create_count = 0;
-+
-+ alloc_hash_table (max_cuid, &expr_hash_table, 0);
-+ add_noreturn_fake_exit_edges ();
-+ if (flag_gcse_lm)
-+ compute_ld_motion_mems ();
-+
-+ compute_hash_table (&expr_hash_table);
-+ trim_ld_motion_mems ();
-+ if (gcse_file)
-+ dump_hash_table (gcse_file, "Expression", &expr_hash_table);
-+
-+ if (expr_hash_table.n_elems > 0)
-+ {
-+ alloc_pre_mem (last_basic_block, expr_hash_table.n_elems);
-+ compute_pre_data ();
-+ changed |= pre_gcse ();
-+ free_edge_list (edge_list);
-+ free_pre_mem ();
-+ }
-+
-+ free_ldst_mems ();
-+ remove_fake_edges ();
-+ free_hash_table (&expr_hash_table);
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "\nPRE GCSE of %s, pass %d: %d bytes needed, ",
-+ current_function_name, pass, bytes_used);
-+ fprintf (gcse_file, "%d substs, %d insns created\n",
-+ gcse_subst_count, gcse_create_count);
-+ }
-+
-+ return changed;
-+}
-+\f
-+/* If X contains any LABEL_REF's, add REG_LABEL notes for them to INSN.
-+ If notes are added to an insn which references a CODE_LABEL, the
-+ LABEL_NUSES count is incremented. We have to add REG_LABEL notes,
-+ because the following loop optimization pass requires them. */
-+
-+/* ??? This is very similar to the loop.c add_label_notes function. We
-+ could probably share code here. */
-+
-+/* ??? If there was a jump optimization pass after gcse and before loop,
-+ then we would not need to do this here, because jump would add the
-+ necessary REG_LABEL notes. */
-+
-+static void
-+add_label_notes (x, insn)
-+ rtx x;
-+ rtx insn;
-+{
-+ enum rtx_code code = GET_CODE (x);
-+ int i, j;
-+ const char *fmt;
-+
-+ if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x))
-+ {
-+ /* This code used to ignore labels that referred to dispatch tables to
-+ avoid flow generating (slighly) worse code.
-+
-+ We no longer ignore such label references (see LABEL_REF handling in
-+ mark_jump_label for additional information). */
-+
-+ REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
-+ REG_NOTES (insn));
-+ if (LABEL_P (XEXP (x, 0)))
-+ LABEL_NUSES (XEXP (x, 0))++;
-+ return;
-+ }
-+
-+ for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ add_label_notes (XEXP (x, i), insn);
-+ else if (fmt[i] == 'E')
-+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-+ add_label_notes (XVECEXP (x, i, j), insn);
-+ }
-+}
-+
-+/* Compute transparent outgoing information for each block.
-+
-+ An expression is transparent to an edge unless it is killed by
-+ the edge itself. This can only happen with abnormal control flow,
-+ when the edge is traversed through a call. This happens with
-+ non-local labels and exceptions.
-+
-+ This would not be necessary if we split the edge. While this is
-+ normally impossible for abnormal critical edges, with some effort
-+ it should be possible with exception handling, since we still have
-+ control over which handler should be invoked. But due to increased
-+ EH table sizes, this may not be worthwhile. */
-+
-+static void
-+compute_transpout ()
-+{
-+ basic_block bb;
-+ unsigned int i;
-+ struct expr *expr;
-+
-+ sbitmap_vector_ones (transpout, last_basic_block);
-+
-+ FOR_EACH_BB (bb)
-+ {
-+ /* Note that flow inserted a nop a the end of basic blocks that
-+ end in call instructions for reasons other than abnormal
-+ control flow. */
-+ if (GET_CODE (bb->end) != CALL_INSN)
-+ continue;
-+
-+ for (i = 0; i < expr_hash_table.size; i++)
-+ for (expr = expr_hash_table.table[i]; expr ; expr = expr->next_same_hash)
-+ if (GET_CODE (expr->expr) == MEM)
-+ {
-+ if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF
-+ && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0)))
-+ continue;
-+
-+ /* ??? Optimally, we would use interprocedural alias
-+ analysis to determine if this mem is actually killed
-+ by this call. */
-+ RESET_BIT (transpout[bb->index], expr->bitmap_index);
-+ }
-+ }
-+}
-+
-+/* Removal of useless null pointer checks */
-+
-+/* Called via note_stores. X is set by SETTER. If X is a register we must
-+ invalidate nonnull_local and set nonnull_killed. DATA is really a
-+ `null_pointer_info *'.
-+
-+ We ignore hard registers. */
-+
-+static void
-+invalidate_nonnull_info (x, setter, data)
-+ rtx x;
-+ rtx setter ATTRIBUTE_UNUSED;
-+ void *data;
-+{
-+ unsigned int regno;
-+ struct null_pointer_info *npi = (struct null_pointer_info *) data;
-+
-+ while (GET_CODE (x) == SUBREG)
-+ x = SUBREG_REG (x);
-+
-+ /* Ignore anything that is not a register or is a hard register. */
-+ if (GET_CODE (x) != REG
-+ || REGNO (x) < npi->min_reg
-+ || REGNO (x) >= npi->max_reg)
-+ return;
-+
-+ regno = REGNO (x) - npi->min_reg;
-+
-+ RESET_BIT (npi->nonnull_local[npi->current_block->index], regno);
-+ SET_BIT (npi->nonnull_killed[npi->current_block->index], regno);
-+}
-+
-+/* Do null-pointer check elimination for the registers indicated in
-+ NPI. NONNULL_AVIN and NONNULL_AVOUT are pre-allocated sbitmaps;
-+ they are not our responsibility to free. */
-+
-+static int
-+delete_null_pointer_checks_1 (block_reg, nonnull_avin,
-+ nonnull_avout, npi)
-+ unsigned int *block_reg;
-+ sbitmap *nonnull_avin;
-+ sbitmap *nonnull_avout;
-+ struct null_pointer_info *npi;
-+{
-+ basic_block bb, current_block;
-+ sbitmap *nonnull_local = npi->nonnull_local;
-+ sbitmap *nonnull_killed = npi->nonnull_killed;
-+ int something_changed = 0;
-+
-+ /* Compute local properties, nonnull and killed. A register will have
-+ the nonnull property if at the end of the current block its value is
-+ known to be nonnull. The killed property indicates that somewhere in
-+ the block any information we had about the register is killed.
-+
-+ Note that a register can have both properties in a single block. That
-+ indicates that it's killed, then later in the block a new value is
-+ computed. */
-+ sbitmap_vector_zero (nonnull_local, last_basic_block);
-+ sbitmap_vector_zero (nonnull_killed, last_basic_block);
-+
-+ FOR_EACH_BB (current_block)
-+ {
-+ rtx insn, stop_insn;
-+
-+ /* Set the current block for invalidate_nonnull_info. */
-+ npi->current_block = current_block;
-+
-+ /* Scan each insn in the basic block looking for memory references and
-+ register sets. */
-+ stop_insn = NEXT_INSN (current_block->end);
-+ for (insn = current_block->head;
-+ insn != stop_insn;
-+ insn = NEXT_INSN (insn))
-+ {
-+ rtx set;
-+ rtx reg;
-+
-+ /* Ignore anything that is not a normal insn. */
-+ if (! INSN_P (insn))
-+ continue;
-+
-+ /* Basically ignore anything that is not a simple SET. We do have
-+ to make sure to invalidate nonnull_local and set nonnull_killed
-+ for such insns though. */
-+ set = single_set (insn);
-+ if (!set)
-+ {
-+ note_stores (PATTERN (insn), invalidate_nonnull_info, npi);
-+ continue;
-+ }
-+
-+ /* See if we've got a usable memory load. We handle it first
-+ in case it uses its address register as a dest (which kills
-+ the nonnull property). */
-+ if (GET_CODE (SET_SRC (set)) == MEM
-+ && GET_CODE ((reg = XEXP (SET_SRC (set), 0))) == REG
-+ && REGNO (reg) >= npi->min_reg
-+ && REGNO (reg) < npi->max_reg)
-+ SET_BIT (nonnull_local[current_block->index],
-+ REGNO (reg) - npi->min_reg);
-+
-+ /* Now invalidate stuff clobbered by this insn. */
-+ note_stores (PATTERN (insn), invalidate_nonnull_info, npi);
-+
-+ /* And handle stores, we do these last since any sets in INSN can
-+ not kill the nonnull property if it is derived from a MEM
-+ appearing in a SET_DEST. */
-+ if (GET_CODE (SET_DEST (set)) == MEM
-+ && GET_CODE ((reg = XEXP (SET_DEST (set), 0))) == REG
-+ && REGNO (reg) >= npi->min_reg
-+ && REGNO (reg) < npi->max_reg)
-+ SET_BIT (nonnull_local[current_block->index],
-+ REGNO (reg) - npi->min_reg);
-+ }
-+ }
-+
-+ /* Now compute global properties based on the local properties. This
-+ is a classic global availablity algorithm. */
-+ compute_available (nonnull_local, nonnull_killed,
-+ nonnull_avout, nonnull_avin);
-+
-+ /* Now look at each bb and see if it ends with a compare of a value
-+ against zero. */
-+ FOR_EACH_BB (bb)
-+ {
-+ rtx last_insn = bb->end;
-+ rtx condition, earliest;
-+ int compare_and_branch;
-+
-+ /* Since MIN_REG is always at least FIRST_PSEUDO_REGISTER, and
-+ since BLOCK_REG[BB] is zero if this block did not end with a
-+ comparison against zero, this condition works. */
-+ if (block_reg[bb->index] < npi->min_reg
-+ || block_reg[bb->index] >= npi->max_reg)
-+ continue;
-+
-+ /* LAST_INSN is a conditional jump. Get its condition. */
-+ condition = get_condition (last_insn, &earliest);
-+
-+ /* If we can't determine the condition then skip. */
-+ if (! condition)
-+ continue;
-+
-+ /* Is the register known to have a nonzero value? */
-+ if (!TEST_BIT (nonnull_avout[bb->index], block_reg[bb->index] - npi->min_reg))
-+ continue;
-+
-+ /* Try to compute whether the compare/branch at the loop end is one or
-+ two instructions. */
-+ if (earliest == last_insn)
-+ compare_and_branch = 1;
-+ else if (earliest == prev_nonnote_insn (last_insn))
-+ compare_and_branch = 2;
-+ else
-+ continue;
-+
-+ /* We know the register in this comparison is nonnull at exit from
-+ this block. We can optimize this comparison. */
-+ if (GET_CODE (condition) == NE)
-+ {
-+ rtx new_jump;
-+
-+ new_jump = emit_jump_insn_after (gen_jump (JUMP_LABEL (last_insn)),
-+ last_insn);
-+ JUMP_LABEL (new_jump) = JUMP_LABEL (last_insn);
-+ LABEL_NUSES (JUMP_LABEL (new_jump))++;
-+ emit_barrier_after (new_jump);
-+ }
-+
-+ something_changed = 1;
-+ delete_insn (last_insn);
-+ if (compare_and_branch == 2)
-+ delete_insn (earliest);
-+ purge_dead_edges (bb);
-+
-+ /* Don't check this block again. (Note that BLOCK_END is
-+ invalid here; we deleted the last instruction in the
-+ block.) */
-+ block_reg[bb->index] = 0;
-+ }
-+
-+ return something_changed;
-+}
-+
-+/* Find EQ/NE comparisons against zero which can be (indirectly) evaluated
-+ at compile time.
-+
-+ This is conceptually similar to global constant/copy propagation and
-+ classic global CSE (it even uses the same dataflow equations as cprop).
-+
-+ If a register is used as memory address with the form (mem (reg)), then we
-+ know that REG can not be zero at that point in the program. Any instruction
-+ which sets REG "kills" this property.
-+
-+ So, if every path leading to a conditional branch has an available memory
-+ reference of that form, then we know the register can not have the value
-+ zero at the conditional branch.
-+
-+ So we merely need to compute the local properies and propagate that data
-+ around the cfg, then optimize where possible.
-+
-+ We run this pass two times. Once before CSE, then again after CSE. This
-+ has proven to be the most profitable approach. It is rare for new
-+ optimization opportunities of this nature to appear after the first CSE
-+ pass.
-+
-+ This could probably be integrated with global cprop with a little work. */
-+
-+int
-+delete_null_pointer_checks (f)
-+ rtx f ATTRIBUTE_UNUSED;
-+{
-+ sbitmap *nonnull_avin, *nonnull_avout;
-+ unsigned int *block_reg;
-+ basic_block bb;
-+ int reg;
-+ int regs_per_pass;
-+ int max_reg;
-+ struct null_pointer_info npi;
-+ int something_changed = 0;
-+
-+ /* If we have only a single block, then there's nothing to do. */
-+ if (n_basic_blocks <= 1)
-+ return 0;
-+
-+ /* Trying to perform global optimizations on flow graphs which have
-+ a high connectivity will take a long time and is unlikely to be
-+ particularly useful.
-+
-+ In normal circumstances a cfg should have about twice as many edges
-+ as blocks. But we do not want to punish small functions which have
-+ a couple switch statements. So we require a relatively large number
-+ of basic blocks and the ratio of edges to blocks to be high. */
-+ if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
-+ return 0;
-+
-+ /* We need four bitmaps, each with a bit for each register in each
-+ basic block. */
-+ max_reg = max_reg_num ();
-+ regs_per_pass = get_bitmap_width (4, last_basic_block, max_reg);
-+
-+ /* Allocate bitmaps to hold local and global properties. */
-+ npi.nonnull_local = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
-+ npi.nonnull_killed = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
-+ nonnull_avin = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
-+ nonnull_avout = sbitmap_vector_alloc (last_basic_block, regs_per_pass);
-+
-+ /* Go through the basic blocks, seeing whether or not each block
-+ ends with a conditional branch whose condition is a comparison
-+ against zero. Record the register compared in BLOCK_REG. */
-+ block_reg = (unsigned int *) xcalloc (last_basic_block, sizeof (int));
-+ FOR_EACH_BB (bb)
-+ {
-+ rtx last_insn = bb->end;
-+ rtx condition, earliest, reg;
-+
-+ /* We only want conditional branches. */
-+ if (GET_CODE (last_insn) != JUMP_INSN
-+ || !any_condjump_p (last_insn)
-+ || !onlyjump_p (last_insn))
-+ continue;
-+
-+ /* LAST_INSN is a conditional jump. Get its condition. */
-+ condition = get_condition (last_insn, &earliest);
-+
-+ /* If we were unable to get the condition, or it is not an equality
-+ comparison against zero then there's nothing we can do. */
-+ if (!condition
-+ || (GET_CODE (condition) != NE && GET_CODE (condition) != EQ)
-+ || GET_CODE (XEXP (condition, 1)) != CONST_INT
-+ || (XEXP (condition, 1)
-+ != CONST0_RTX (GET_MODE (XEXP (condition, 0)))))
-+ continue;
-+
-+ /* We must be checking a register against zero. */
-+ reg = XEXP (condition, 0);
-+ if (GET_CODE (reg) != REG)
-+ continue;
-+
-+ block_reg[bb->index] = REGNO (reg);
-+ }
-+
-+ /* Go through the algorithm for each block of registers. */
-+ for (reg = FIRST_PSEUDO_REGISTER; reg < max_reg; reg += regs_per_pass)
-+ {
-+ npi.min_reg = reg;
-+ npi.max_reg = MIN (reg + regs_per_pass, max_reg);
-+ something_changed |= delete_null_pointer_checks_1 (block_reg,
-+ nonnull_avin,
-+ nonnull_avout,
-+ &npi);
-+ }
-+
-+ /* Free the table of registers compared at the end of every block. */
-+ free (block_reg);
-+
-+ /* Free bitmaps. */
-+ sbitmap_vector_free (npi.nonnull_local);
-+ sbitmap_vector_free (npi.nonnull_killed);
-+ sbitmap_vector_free (nonnull_avin);
-+ sbitmap_vector_free (nonnull_avout);
-+
-+ return something_changed;
-+}
-+
-+/* Code Hoisting variables and subroutines. */
-+
-+/* Very busy expressions. */
-+static sbitmap *hoist_vbein;
-+static sbitmap *hoist_vbeout;
-+
-+/* Hoistable expressions. */
-+static sbitmap *hoist_exprs;
-+
-+/* Dominator bitmaps. */
-+dominance_info dominators;
-+
-+/* ??? We could compute post dominators and run this algorithm in
-+ reverse to perform tail merging, doing so would probably be
-+ more effective than the tail merging code in jump.c.
-+
-+ It's unclear if tail merging could be run in parallel with
-+ code hoisting. It would be nice. */
-+
-+/* Allocate vars used for code hoisting analysis. */
-+
-+static void
-+alloc_code_hoist_mem (n_blocks, n_exprs)
-+ int n_blocks, n_exprs;
-+{
-+ antloc = sbitmap_vector_alloc (n_blocks, n_exprs);
-+ transp = sbitmap_vector_alloc (n_blocks, n_exprs);
-+ comp = sbitmap_vector_alloc (n_blocks, n_exprs);
-+
-+ hoist_vbein = sbitmap_vector_alloc (n_blocks, n_exprs);
-+ hoist_vbeout = sbitmap_vector_alloc (n_blocks, n_exprs);
-+ hoist_exprs = sbitmap_vector_alloc (n_blocks, n_exprs);
-+ transpout = sbitmap_vector_alloc (n_blocks, n_exprs);
-+}
-+
-+/* Free vars used for code hoisting analysis. */
-+
-+static void
-+free_code_hoist_mem ()
-+{
-+ sbitmap_vector_free (antloc);
-+ sbitmap_vector_free (transp);
-+ sbitmap_vector_free (comp);
-+
-+ sbitmap_vector_free (hoist_vbein);
-+ sbitmap_vector_free (hoist_vbeout);
-+ sbitmap_vector_free (hoist_exprs);
-+ sbitmap_vector_free (transpout);
-+
-+ free_dominance_info (dominators);
-+}
-+
-+/* Compute the very busy expressions at entry/exit from each block.
-+
-+ An expression is very busy if all paths from a given point
-+ compute the expression. */
-+
-+static void
-+compute_code_hoist_vbeinout ()
-+{
-+ int changed, passes;
-+ basic_block bb;
-+
-+ sbitmap_vector_zero (hoist_vbeout, last_basic_block);
-+ sbitmap_vector_zero (hoist_vbein, last_basic_block);
-+
-+ passes = 0;
-+ changed = 1;
-+
-+ while (changed)
-+ {
-+ changed = 0;
-+
-+ /* We scan the blocks in the reverse order to speed up
-+ the convergence. */
-+ FOR_EACH_BB_REVERSE (bb)
-+ {
-+ changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index],
-+ hoist_vbeout[bb->index], transp[bb->index]);
-+ if (bb->next_bb != EXIT_BLOCK_PTR)
-+ sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index);
-+ }
-+
-+ passes++;
-+ }
-+
-+ if (gcse_file)
-+ fprintf (gcse_file, "hoisting vbeinout computation: %d passes\n", passes);
-+}
-+
-+/* Top level routine to do the dataflow analysis needed by code hoisting. */
-+
-+static void
-+compute_code_hoist_data ()
-+{
-+ compute_local_properties (transp, comp, antloc, &expr_hash_table);
-+ compute_transpout ();
-+ compute_code_hoist_vbeinout ();
-+ dominators = calculate_dominance_info (CDI_DOMINATORS);
-+ if (gcse_file)
-+ fprintf (gcse_file, "\n");
-+}
-+
-+/* Determine if the expression identified by EXPR_INDEX would
-+ reach BB unimpared if it was placed at the end of EXPR_BB.
-+
-+ It's unclear exactly what Muchnick meant by "unimpared". It seems
-+ to me that the expression must either be computed or transparent in
-+ *every* block in the path(s) from EXPR_BB to BB. Any other definition
-+ would allow the expression to be hoisted out of loops, even if
-+ the expression wasn't a loop invariant.
-+
-+ Contrast this to reachability for PRE where an expression is
-+ considered reachable if *any* path reaches instead of *all*
-+ paths. */
-+
-+static int
-+hoist_expr_reaches_here_p (expr_bb, expr_index, bb, visited)
-+ basic_block expr_bb;
-+ int expr_index;
-+ basic_block bb;
-+ char *visited;
-+{
-+ edge pred;
-+ int visited_allocated_locally = 0;
-+
-+
-+ if (visited == NULL)
-+ {
-+ visited_allocated_locally = 1;
-+ visited = xcalloc (last_basic_block, 1);
-+ }
-+
-+ for (pred = bb->pred; pred != NULL; pred = pred->pred_next)
-+ {
-+ basic_block pred_bb = pred->src;
-+
-+ if (pred->src == ENTRY_BLOCK_PTR)
-+ break;
-+ else if (pred_bb == expr_bb)
-+ continue;
-+ else if (visited[pred_bb->index])
-+ continue;
-+
-+ /* Does this predecessor generate this expression? */
-+ else if (TEST_BIT (comp[pred_bb->index], expr_index))
-+ break;
-+ else if (! TEST_BIT (transp[pred_bb->index], expr_index))
-+ break;
-+
-+ /* Not killed. */
-+ else
-+ {
-+ visited[pred_bb->index] = 1;
-+ if (! hoist_expr_reaches_here_p (expr_bb, expr_index,
-+ pred_bb, visited))
-+ break;
-+ }
-+ }
-+ if (visited_allocated_locally)
-+ free (visited);
-+
-+ return (pred == NULL);
-+}
-+\f
-+/* Actually perform code hoisting. */
-+
-+static void
-+hoist_code ()
-+{
-+ basic_block bb, dominated;
-+ basic_block *domby;
-+ unsigned int domby_len;
-+ unsigned int i,j;
-+ struct expr **index_map;
-+ struct expr *expr;
-+
-+ sbitmap_vector_zero (hoist_exprs, last_basic_block);
-+
-+ /* Compute a mapping from expression number (`bitmap_index') to
-+ hash table entry. */
-+
-+ index_map = (struct expr **) xcalloc (expr_hash_table.n_elems, sizeof (struct expr *));
-+ for (i = 0; i < expr_hash_table.size; i++)
-+ for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash)
-+ index_map[expr->bitmap_index] = expr;
-+
-+ /* Walk over each basic block looking for potentially hoistable
-+ expressions, nothing gets hoisted from the entry block. */
-+ FOR_EACH_BB (bb)
-+ {
-+ int found = 0;
-+ int insn_inserted_p;
-+
-+ domby_len = get_dominated_by (dominators, bb, &domby);
-+ /* Examine each expression that is very busy at the exit of this
-+ block. These are the potentially hoistable expressions. */
-+ for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++)
-+ {
-+ int hoistable = 0;
-+
-+ if (TEST_BIT (hoist_vbeout[bb->index], i)
-+ && TEST_BIT (transpout[bb->index], i))
-+ {
-+ /* We've found a potentially hoistable expression, now
-+ we look at every block BB dominates to see if it
-+ computes the expression. */
-+ for (j = 0; j < domby_len; j++)
-+ {
-+ dominated = domby[j];
-+ /* Ignore self dominance. */
-+ if (bb == dominated)
-+ continue;
-+ /* We've found a dominated block, now see if it computes
-+ the busy expression and whether or not moving that
-+ expression to the "beginning" of that block is safe. */
-+ if (!TEST_BIT (antloc[dominated->index], i))
-+ continue;
-+
-+ /* Note if the expression would reach the dominated block
-+ unimpared if it was placed at the end of BB.
-+
-+ Keep track of how many times this expression is hoistable
-+ from a dominated block into BB. */
-+ if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
-+ hoistable++;
-+ }
-+
-+ /* If we found more than one hoistable occurrence of this
-+ expression, then note it in the bitmap of expressions to
-+ hoist. It makes no sense to hoist things which are computed
-+ in only one BB, and doing so tends to pessimize register
-+ allocation. One could increase this value to try harder
-+ to avoid any possible code expansion due to register
-+ allocation issues; however experiments have shown that
-+ the vast majority of hoistable expressions are only movable
-+ from two successors, so raising this threshhold is likely
-+ to nullify any benefit we get from code hoisting. */
-+ if (hoistable > 1)
-+ {
-+ SET_BIT (hoist_exprs[bb->index], i);
-+ found = 1;
-+ }
-+ }
-+ }
-+ /* If we found nothing to hoist, then quit now. */
-+ if (! found)
-+ {
-+ free (domby);
-+ continue;
-+ }
-+
-+ /* Loop over all the hoistable expressions. */
-+ for (i = 0; i < hoist_exprs[bb->index]->n_bits; i++)
-+ {
-+ /* We want to insert the expression into BB only once, so
-+ note when we've inserted it. */
-+ insn_inserted_p = 0;
-+
-+ /* These tests should be the same as the tests above. */
-+ if (TEST_BIT (hoist_vbeout[bb->index], i))
-+ {
-+ /* We've found a potentially hoistable expression, now
-+ we look at every block BB dominates to see if it
-+ computes the expression. */
-+ for (j = 0; j < domby_len; j++)
-+ {
-+ dominated = domby[j];
-+ /* Ignore self dominance. */
-+ if (bb == dominated)
-+ continue;
-+
-+ /* We've found a dominated block, now see if it computes
-+ the busy expression and whether or not moving that
-+ expression to the "beginning" of that block is safe. */
-+ if (!TEST_BIT (antloc[dominated->index], i))
-+ continue;
-+
-+ /* The expression is computed in the dominated block and
-+ it would be safe to compute it at the start of the
-+ dominated block. Now we have to determine if the
-+ expression would reach the dominated block if it was
-+ placed at the end of BB. */
-+ if (hoist_expr_reaches_here_p (bb, i, dominated, NULL))
-+ {
-+ struct expr *expr = index_map[i];
-+ struct occr *occr = expr->antic_occr;
-+ rtx insn;
-+ rtx set;
-+
-+ /* Find the right occurrence of this expression. */
-+ while (BLOCK_FOR_INSN (occr->insn) != dominated && occr)
-+ occr = occr->next;
-+
-+ /* Should never happen. */
-+ if (!occr)
-+ abort ();
-+
-+ insn = occr->insn;
-+
-+ set = single_set (insn);
-+ if (! set)
-+ abort ();
-+
-+ /* Create a pseudo-reg to store the result of reaching
-+ expressions into. Get the mode for the new pseudo
-+ from the mode of the original destination pseudo. */
-+ if (expr->reaching_reg == NULL)
-+ expr->reaching_reg
-+ = gen_reg_rtx (GET_MODE (SET_DEST (set)));
-+
-+ gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn);
-+ delete_insn (insn);
-+ occr->deleted_p = 1;
-+ if (!insn_inserted_p)
-+ {
-+ insert_insn_end_bb (index_map[i], bb, 0);
-+ insn_inserted_p = 1;
-+ }
-+ }
-+ }
-+ }
-+ }
-+ free (domby);
-+ }
-+
-+ free (index_map);
-+}
-+
-+/* Top level routine to perform one code hoisting (aka unification) pass
-+
-+ Return nonzero if a change was made. */
-+
-+static int
-+one_code_hoisting_pass ()
-+{
-+ int changed = 0;
-+
-+ alloc_hash_table (max_cuid, &expr_hash_table, 0);
-+ compute_hash_table (&expr_hash_table);
-+ if (gcse_file)
-+ dump_hash_table (gcse_file, "Code Hosting Expressions", &expr_hash_table);
-+
-+ if (expr_hash_table.n_elems > 0)
-+ {
-+ alloc_code_hoist_mem (last_basic_block, expr_hash_table.n_elems);
-+ compute_code_hoist_data ();
-+ hoist_code ();
-+ free_code_hoist_mem ();
-+ }
-+
-+ free_hash_table (&expr_hash_table);
-+
-+ return changed;
-+}
-+\f
-+/* Here we provide the things required to do store motion towards
-+ the exit. In order for this to be effective, gcse also needed to
-+ be taught how to move a load when it is kill only by a store to itself.
-+
-+ int i;
-+ float a[10];
-+
-+ void foo(float scale)
-+ {
-+ for (i=0; i<10; i++)
-+ a[i] *= scale;
-+ }
-+
-+ 'i' is both loaded and stored to in the loop. Normally, gcse cannot move
-+ the load out since its live around the loop, and stored at the bottom
-+ of the loop.
-+
-+ The 'Load Motion' referred to and implemented in this file is
-+ an enhancement to gcse which when using edge based lcm, recognizes
-+ this situation and allows gcse to move the load out of the loop.
-+
-+ Once gcse has hoisted the load, store motion can then push this
-+ load towards the exit, and we end up with no loads or stores of 'i'
-+ in the loop. */
-+
-+/* This will search the ldst list for a matching expression. If it
-+ doesn't find one, we create one and initialize it. */
-+
-+static struct ls_expr *
-+ldst_entry (x)
-+ rtx x;
-+{
-+ struct ls_expr * ptr;
-+
-+ for (ptr = first_ls_expr(); ptr != NULL; ptr = next_ls_expr (ptr))
-+ if (expr_equiv_p (ptr->pattern, x))
-+ break;
-+
-+ if (!ptr)
-+ {
-+ ptr = (struct ls_expr *) xmalloc (sizeof (struct ls_expr));
-+
-+ ptr->next = pre_ldst_mems;
-+ ptr->expr = NULL;
-+ ptr->pattern = x;
-+ ptr->loads = NULL_RTX;
-+ ptr->stores = NULL_RTX;
-+ ptr->reaching_reg = NULL_RTX;
-+ ptr->invalid = 0;
-+ ptr->index = 0;
-+ ptr->hash_index = 0;
-+ pre_ldst_mems = ptr;
-+ }
-+
-+ return ptr;
-+}
-+
-+/* Free up an individual ldst entry. */
-+
-+static void
-+free_ldst_entry (ptr)
-+ struct ls_expr * ptr;
-+{
-+ free_INSN_LIST_list (& ptr->loads);
-+ free_INSN_LIST_list (& ptr->stores);
-+
-+ free (ptr);
-+}
-+
-+/* Free up all memory associated with the ldst list. */
-+
-+static void
-+free_ldst_mems ()
-+{
-+ while (pre_ldst_mems)
-+ {
-+ struct ls_expr * tmp = pre_ldst_mems;
-+
-+ pre_ldst_mems = pre_ldst_mems->next;
-+
-+ free_ldst_entry (tmp);
-+ }
-+
-+ pre_ldst_mems = NULL;
-+}
-+
-+/* Dump debugging info about the ldst list. */
-+
-+static void
-+print_ldst_list (file)
-+ FILE * file;
-+{
-+ struct ls_expr * ptr;
-+
-+ fprintf (file, "LDST list: \n");
-+
-+ for (ptr = first_ls_expr(); ptr != NULL; ptr = next_ls_expr (ptr))
-+ {
-+ fprintf (file, " Pattern (%3d): ", ptr->index);
-+
-+ print_rtl (file, ptr->pattern);
-+
-+ fprintf (file, "\n Loads : ");
-+
-+ if (ptr->loads)
-+ print_rtl (file, ptr->loads);
-+ else
-+ fprintf (file, "(nil)");
-+
-+ fprintf (file, "\n Stores : ");
-+
-+ if (ptr->stores)
-+ print_rtl (file, ptr->stores);
-+ else
-+ fprintf (file, "(nil)");
-+
-+ fprintf (file, "\n\n");
-+ }
-+
-+ fprintf (file, "\n");
-+}
-+
-+/* Returns 1 if X is in the list of ldst only expressions. */
-+
-+static struct ls_expr *
-+find_rtx_in_ldst (x)
-+ rtx x;
-+{
-+ struct ls_expr * ptr;
-+
-+ for (ptr = pre_ldst_mems; ptr != NULL; ptr = ptr->next)
-+ if (expr_equiv_p (ptr->pattern, x) && ! ptr->invalid)
-+ return ptr;
-+
-+ return NULL;
-+}
-+
-+/* Assign each element of the list of mems a monotonically increasing value. */
-+
-+static int
-+enumerate_ldsts ()
-+{
-+ struct ls_expr * ptr;
-+ int n = 0;
-+
-+ for (ptr = pre_ldst_mems; ptr != NULL; ptr = ptr->next)
-+ ptr->index = n++;
-+
-+ return n;
-+}
-+
-+/* Return first item in the list. */
-+
-+static inline struct ls_expr *
-+first_ls_expr ()
-+{
-+ return pre_ldst_mems;
-+}
-+
-+/* Return the next item in ther list after the specified one. */
-+
-+static inline struct ls_expr *
-+next_ls_expr (ptr)
-+ struct ls_expr * ptr;
-+{
-+ return ptr->next;
-+}
-+\f
-+/* Load Motion for loads which only kill themselves. */
-+
-+/* Return true if x is a simple MEM operation, with no registers or
-+ side effects. These are the types of loads we consider for the
-+ ld_motion list, otherwise we let the usual aliasing take care of it. */
-+
-+static int
-+simple_mem (x)
-+ rtx x;
-+{
-+ if (GET_CODE (x) != MEM)
-+ return 0;
-+
-+ if (MEM_VOLATILE_P (x))
-+ return 0;
-+
-+ if (GET_MODE (x) == BLKmode)
-+ return 0;
-+
-+ if (!rtx_varies_p (XEXP (x, 0), 0))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/* Make sure there isn't a buried reference in this pattern anywhere.
-+ If there is, invalidate the entry for it since we're not capable
-+ of fixing it up just yet.. We have to be sure we know about ALL
-+ loads since the aliasing code will allow all entries in the
-+ ld_motion list to not-alias itself. If we miss a load, we will get
-+ the wrong value since gcse might common it and we won't know to
-+ fix it up. */
-+
-+static void
-+invalidate_any_buried_refs (x)
-+ rtx x;
-+{
-+ const char * fmt;
-+ int i, j;
-+ struct ls_expr * ptr;
-+
-+ /* Invalidate it in the list. */
-+ if (GET_CODE (x) == MEM && simple_mem (x))
-+ {
-+ ptr = ldst_entry (x);
-+ ptr->invalid = 1;
-+ }
-+
-+ /* Recursively process the insn. */
-+ fmt = GET_RTX_FORMAT (GET_CODE (x));
-+
-+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ invalidate_any_buried_refs (XEXP (x, i));
-+ else if (fmt[i] == 'E')
-+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-+ invalidate_any_buried_refs (XVECEXP (x, i, j));
-+ }
-+}
-+
-+/* Find all the 'simple' MEMs which are used in LOADs and STORES. Simple
-+ being defined as MEM loads and stores to symbols, with no
-+ side effects and no registers in the expression. If there are any
-+ uses/defs which don't match this criteria, it is invalidated and
-+ trimmed out later. */
-+
-+static void
-+compute_ld_motion_mems ()
-+{
-+ struct ls_expr * ptr;
-+ basic_block bb;
-+ rtx insn;
-+
-+ pre_ldst_mems = NULL;
-+
-+ FOR_EACH_BB (bb)
-+ {
-+ for (insn = bb->head;
-+ insn && insn != NEXT_INSN (bb->end);
-+ insn = NEXT_INSN (insn))
-+ {
-+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-+ {
-+ if (GET_CODE (PATTERN (insn)) == SET)
-+ {
-+ rtx src = SET_SRC (PATTERN (insn));
-+ rtx dest = SET_DEST (PATTERN (insn));
-+
-+ /* Check for a simple LOAD... */
-+ if (GET_CODE (src) == MEM && simple_mem (src))
-+ {
-+ ptr = ldst_entry (src);
-+ if (GET_CODE (dest) == REG)
-+ ptr->loads = alloc_INSN_LIST (insn, ptr->loads);
-+ else
-+ ptr->invalid = 1;
-+ }
-+ else
-+ {
-+ /* Make sure there isn't a buried load somewhere. */
-+ invalidate_any_buried_refs (src);
-+ }
-+
-+ /* Check for stores. Don't worry about aliased ones, they
-+ will block any movement we might do later. We only care
-+ about this exact pattern since those are the only
-+ circumstance that we will ignore the aliasing info. */
-+ if (GET_CODE (dest) == MEM && simple_mem (dest))
-+ {
-+ ptr = ldst_entry (dest);
-+
-+ if (GET_CODE (src) != MEM
-+ && GET_CODE (src) != ASM_OPERANDS)
-+ ptr->stores = alloc_INSN_LIST (insn, ptr->stores);
-+ else
-+ ptr->invalid = 1;
-+ }
-+ }
-+ else
-+ invalidate_any_buried_refs (PATTERN (insn));
-+ }
-+ }
-+ }
-+}
-+
-+/* Remove any references that have been either invalidated or are not in the
-+ expression list for pre gcse. */
-+
-+static void
-+trim_ld_motion_mems ()
-+{
-+ struct ls_expr * last = NULL;
-+ struct ls_expr * ptr = first_ls_expr ();
-+
-+ while (ptr != NULL)
-+ {
-+ int del = ptr->invalid;
-+ struct expr * expr = NULL;
-+
-+ /* Delete if entry has been made invalid. */
-+ if (!del)
-+ {
-+ unsigned int i;
-+
-+ del = 1;
-+ /* Delete if we cannot find this mem in the expression list. */
-+ for (i = 0; i < expr_hash_table.size && del; i++)
-+ {
-+ for (expr = expr_hash_table.table[i];
-+ expr != NULL;
-+ expr = expr->next_same_hash)
-+ if (expr_equiv_p (expr->expr, ptr->pattern))
-+ {
-+ del = 0;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (del)
-+ {
-+ if (last != NULL)
-+ {
-+ last->next = ptr->next;
-+ free_ldst_entry (ptr);
-+ ptr = last->next;
-+ }
-+ else
-+ {
-+ pre_ldst_mems = pre_ldst_mems->next;
-+ free_ldst_entry (ptr);
-+ ptr = pre_ldst_mems;
-+ }
-+ }
-+ else
-+ {
-+ /* Set the expression field if we are keeping it. */
-+ last = ptr;
-+ ptr->expr = expr;
-+ ptr = ptr->next;
-+ }
-+ }
-+
-+ /* Show the world what we've found. */
-+ if (gcse_file && pre_ldst_mems != NULL)
-+ print_ldst_list (gcse_file);
-+}
-+
-+/* This routine will take an expression which we are replacing with
-+ a reaching register, and update any stores that are needed if
-+ that expression is in the ld_motion list. Stores are updated by
-+ copying their SRC to the reaching register, and then storeing
-+ the reaching register into the store location. These keeps the
-+ correct value in the reaching register for the loads. */
-+
-+static void
-+update_ld_motion_stores (expr)
-+ struct expr * expr;
-+{
-+ struct ls_expr * mem_ptr;
-+
-+ if ((mem_ptr = find_rtx_in_ldst (expr->expr)))
-+ {
-+ /* We can try to find just the REACHED stores, but is shouldn't
-+ matter to set the reaching reg everywhere... some might be
-+ dead and should be eliminated later. */
-+
-+ /* We replace SET mem = expr with
-+ SET reg = expr
-+ SET mem = reg , where reg is the
-+ reaching reg used in the load. */
-+ rtx list = mem_ptr->stores;
-+
-+ for ( ; list != NULL_RTX; list = XEXP (list, 1))
-+ {
-+ rtx insn = XEXP (list, 0);
-+ rtx pat = PATTERN (insn);
-+ rtx src = SET_SRC (pat);
-+ rtx reg = expr->reaching_reg;
-+ rtx copy, new;
-+
-+ /* If we've already copied it, continue. */
-+ if (expr->reaching_reg == src)
-+ continue;
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "PRE: store updated with reaching reg ");
-+ print_rtl (gcse_file, expr->reaching_reg);
-+ fprintf (gcse_file, ":\n ");
-+ print_inline_rtx (gcse_file, insn, 8);
-+ fprintf (gcse_file, "\n");
-+ }
-+
-+ copy = gen_move_insn ( reg, SET_SRC (pat));
-+ new = emit_insn_before (copy, insn);
-+ record_one_set (REGNO (reg), new);
-+ SET_SRC (pat) = reg;
-+
-+ /* un-recognize this pattern since it's probably different now. */
-+ INSN_CODE (insn) = -1;
-+ gcse_create_count++;
-+ }
-+ }
-+}
-+\f
-+/* Store motion code. */
-+
-+/* This is used to communicate the target bitvector we want to use in the
-+ reg_set_info routine when called via the note_stores mechanism. */
-+static sbitmap * regvec;
-+
-+/* Used in computing the reverse edge graph bit vectors. */
-+static sbitmap * st_antloc;
-+
-+/* Global holding the number of store expressions we are dealing with. */
-+static int num_stores;
-+
-+/* Checks to set if we need to mark a register set. Called from note_stores. */
-+
-+static void
-+reg_set_info (dest, setter, data)
-+ rtx dest, setter ATTRIBUTE_UNUSED;
-+ void * data ATTRIBUTE_UNUSED;
-+{
-+ if (GET_CODE (dest) == SUBREG)
-+ dest = SUBREG_REG (dest);
-+
-+ if (GET_CODE (dest) == REG)
-+ SET_BIT (*regvec, REGNO (dest));
-+}
-+
-+/* Return nonzero if the register operands of expression X are killed
-+ anywhere in basic block BB. */
-+
-+static int
-+store_ops_ok (x, bb)
-+ rtx x;
-+ basic_block bb;
-+{
-+ int i;
-+ enum rtx_code code;
-+ const char * fmt;
-+
-+ /* Repeat is used to turn tail-recursion into iteration. */
-+ repeat:
-+
-+ if (x == 0)
-+ return 1;
-+
-+ code = GET_CODE (x);
-+ switch (code)
-+ {
-+ case REG:
-+ /* If a reg has changed after us in this
-+ block, the operand has been killed. */
-+ return TEST_BIT (reg_set_in_block[bb->index], REGNO (x));
-+
-+ case MEM:
-+ x = XEXP (x, 0);
-+ goto repeat;
-+
-+ case PRE_DEC:
-+ case PRE_INC:
-+ case POST_DEC:
-+ case POST_INC:
-+ return 0;
-+
-+ case PC:
-+ case CC0: /*FIXME*/
-+ case CONST:
-+ case CONST_INT:
-+ case CONST_DOUBLE:
-+ case CONST_VECTOR:
-+ case SYMBOL_REF:
-+ case LABEL_REF:
-+ case ADDR_VEC:
-+ case ADDR_DIFF_VEC:
-+ return 1;
-+
-+ default:
-+ break;
-+ }
-+
-+ i = GET_RTX_LENGTH (code) - 1;
-+ fmt = GET_RTX_FORMAT (code);
-+
-+ for (; i >= 0; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ {
-+ rtx tem = XEXP (x, i);
-+
-+ /* If we are about to do the last recursive call
-+ needed at this level, change it into iteration.
-+ This function is called enough to be worth it. */
-+ if (i == 0)
-+ {
-+ x = tem;
-+ goto repeat;
-+ }
-+
-+ if (! store_ops_ok (tem, bb))
-+ return 0;
-+ }
-+ else if (fmt[i] == 'E')
-+ {
-+ int j;
-+
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ {
-+ if (! store_ops_ok (XVECEXP (x, i, j), bb))
-+ return 0;
-+ }
-+ }
-+ }
-+
-+ return 1;
-+}
-+
-+/* Determine whether insn is MEM store pattern that we will consider moving. */
-+
-+static void
-+find_moveable_store (insn)
-+ rtx insn;
-+{
-+ struct ls_expr * ptr;
-+ rtx dest = PATTERN (insn);
-+
-+ if (GET_CODE (dest) != SET
-+ || GET_CODE (SET_SRC (dest)) == ASM_OPERANDS)
-+ return;
-+
-+ dest = SET_DEST (dest);
-+
-+ if (GET_CODE (dest) != MEM || MEM_VOLATILE_P (dest)
-+ || GET_MODE (dest) == BLKmode)
-+ return;
-+
-+ if (GET_CODE (XEXP (dest, 0)) != SYMBOL_REF)
-+ return;
-+
-+ if (rtx_varies_p (XEXP (dest, 0), 0))
-+ return;
-+
-+ ptr = ldst_entry (dest);
-+ ptr->stores = alloc_INSN_LIST (insn, ptr->stores);
-+}
-+
-+/* Perform store motion. Much like gcse, except we move expressions the
-+ other way by looking at the flowgraph in reverse. */
-+
-+static int
-+compute_store_table ()
-+{
-+ int ret;
-+ basic_block bb;
-+ unsigned regno;
-+ rtx insn, pat;
-+
-+ max_gcse_regno = max_reg_num ();
-+
-+ reg_set_in_block = (sbitmap *) sbitmap_vector_alloc (last_basic_block,
-+ max_gcse_regno);
-+ sbitmap_vector_zero (reg_set_in_block, last_basic_block);
-+ pre_ldst_mems = 0;
-+
-+ /* Find all the stores we care about. */
-+ FOR_EACH_BB (bb)
-+ {
-+ regvec = & (reg_set_in_block[bb->index]);
-+ for (insn = bb->end;
-+ insn && insn != PREV_INSN (bb->end);
-+ insn = PREV_INSN (insn))
-+ {
-+ /* Ignore anything that is not a normal insn. */
-+ if (! INSN_P (insn))
-+ continue;
-+
-+ if (GET_CODE (insn) == CALL_INSN)
-+ {
-+ bool clobbers_all = false;
-+#ifdef NON_SAVING_SETJMP
-+ if (NON_SAVING_SETJMP
-+ && find_reg_note (insn, REG_SETJMP, NULL_RTX))
-+ clobbers_all = true;
-+#endif
-+
-+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-+ if (clobbers_all
-+ || TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
-+ SET_BIT (reg_set_in_block[bb->index], regno);
-+ }
-+
-+ pat = PATTERN (insn);
-+ note_stores (pat, reg_set_info, NULL);
-+
-+ /* Now that we've marked regs, look for stores. */
-+ if (GET_CODE (pat) == SET)
-+ find_moveable_store (insn);
-+ }
-+ }
-+
-+ ret = enumerate_ldsts ();
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "Store Motion Expressions.\n");
-+ print_ldst_list (gcse_file);
-+ }
-+
-+ return ret;
-+}
-+
-+/* Check to see if the load X is aliased with STORE_PATTERN. */
-+
-+static int
-+load_kills_store (x, store_pattern)
-+ rtx x, store_pattern;
-+{
-+ if (true_dependence (x, GET_MODE (x), store_pattern, rtx_addr_varies_p))
-+ return 1;
-+ return 0;
-+}
-+
-+/* Go through the entire insn X, looking for any loads which might alias
-+ STORE_PATTERN. Return 1 if found. */
-+
-+static int
-+find_loads (x, store_pattern)
-+ rtx x, store_pattern;
-+{
-+ const char * fmt;
-+ int i, j;
-+ int ret = 0;
-+
-+ if (!x)
-+ return 0;
-+
-+ if (GET_CODE (x) == SET)
-+ x = SET_SRC (x);
-+
-+ if (GET_CODE (x) == MEM)
-+ {
-+ if (load_kills_store (x, store_pattern))
-+ return 1;
-+ }
-+
-+ /* Recursively process the insn. */
-+ fmt = GET_RTX_FORMAT (GET_CODE (x));
-+
-+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0 && !ret; i--)
-+ {
-+ if (fmt[i] == 'e')
-+ ret |= find_loads (XEXP (x, i), store_pattern);
-+ else if (fmt[i] == 'E')
-+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-+ ret |= find_loads (XVECEXP (x, i, j), store_pattern);
-+ }
-+ return ret;
-+}
-+
-+/* Check if INSN kills the store pattern X (is aliased with it).
-+ Return 1 if it it does. */
-+
-+static int
-+store_killed_in_insn (x, insn)
-+ rtx x, insn;
-+{
-+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
-+ return 0;
-+
-+ if (GET_CODE (insn) == CALL_INSN)
-+ {
-+ /* A normal or pure call might read from pattern,
-+ but a const call will not. */
-+ return ! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn);
-+ }
-+
-+ if (GET_CODE (PATTERN (insn)) == SET)
-+ {
-+ rtx pat = PATTERN (insn);
-+ /* Check for memory stores to aliased objects. */
-+ if (GET_CODE (SET_DEST (pat)) == MEM && !expr_equiv_p (SET_DEST (pat), x))
-+ /* pretend its a load and check for aliasing. */
-+ if (find_loads (SET_DEST (pat), x))
-+ return 1;
-+ return find_loads (SET_SRC (pat), x);
-+ }
-+ else
-+ return find_loads (PATTERN (insn), x);
-+}
-+
-+/* Returns 1 if the expression X is loaded or clobbered on or after INSN
-+ within basic block BB. */
-+
-+static int
-+store_killed_after (x, insn, bb)
-+ rtx x, insn;
-+ basic_block bb;
-+{
-+ rtx last = bb->end;
-+
-+ if (insn == last)
-+ return 0;
-+
-+ /* Check if the register operands of the store are OK in this block.
-+ Note that if registers are changed ANYWHERE in the block, we'll
-+ decide we can't move it, regardless of whether it changed above
-+ or below the store. This could be improved by checking the register
-+ operands while lookinng for aliasing in each insn. */
-+ if (!store_ops_ok (XEXP (x, 0), bb))
-+ return 1;
-+
-+ for ( ; insn && insn != NEXT_INSN (last); insn = NEXT_INSN (insn))
-+ if (store_killed_in_insn (x, insn))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+/* Returns 1 if the expression X is loaded or clobbered on or before INSN
-+ within basic block BB. */
-+static int
-+store_killed_before (x, insn, bb)
-+ rtx x, insn;
-+ basic_block bb;
-+{
-+ rtx first = bb->head;
-+
-+ if (insn == first)
-+ return store_killed_in_insn (x, insn);
-+
-+ /* Check if the register operands of the store are OK in this block.
-+ Note that if registers are changed ANYWHERE in the block, we'll
-+ decide we can't move it, regardless of whether it changed above
-+ or below the store. This could be improved by checking the register
-+ operands while lookinng for aliasing in each insn. */
-+ if (!store_ops_ok (XEXP (x, 0), bb))
-+ return 1;
-+
-+ for ( ; insn && insn != PREV_INSN (first); insn = PREV_INSN (insn))
-+ if (store_killed_in_insn (x, insn))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+#define ANTIC_STORE_LIST(x) ((x)->loads)
-+#define AVAIL_STORE_LIST(x) ((x)->stores)
-+
-+/* Given the table of available store insns at the end of blocks,
-+ determine which ones are not killed by aliasing, and generate
-+ the appropriate vectors for gen and killed. */
-+static void
-+build_store_vectors ()
-+{
-+ basic_block bb, b;
-+ rtx insn, st;
-+ struct ls_expr * ptr;
-+
-+ /* Build the gen_vector. This is any store in the table which is not killed
-+ by aliasing later in its block. */
-+ ae_gen = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
-+ sbitmap_vector_zero (ae_gen, last_basic_block);
-+
-+ st_antloc = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
-+ sbitmap_vector_zero (st_antloc, last_basic_block);
-+
-+ for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
-+ {
-+ /* Put all the stores into either the antic list, or the avail list,
-+ or both. */
-+ rtx store_list = ptr->stores;
-+ ptr->stores = NULL_RTX;
-+
-+ for (st = store_list; st != NULL; st = XEXP (st, 1))
-+ {
-+ insn = XEXP (st, 0);
-+ bb = BLOCK_FOR_INSN (insn);
-+
-+ if (!store_killed_after (ptr->pattern, insn, bb))
-+ {
-+ /* If we've already seen an availale expression in this block,
-+ we can delete the one we saw already (It occurs earlier in
-+ the block), and replace it with this one). We'll copy the
-+ old SRC expression to an unused register in case there
-+ are any side effects. */
-+ if (TEST_BIT (ae_gen[bb->index], ptr->index))
-+ {
-+ /* Find previous store. */
-+ rtx st;
-+ for (st = AVAIL_STORE_LIST (ptr); st ; st = XEXP (st, 1))
-+ if (BLOCK_FOR_INSN (XEXP (st, 0)) == bb)
-+ break;
-+ if (st)
-+ {
-+ rtx r = gen_reg_rtx (GET_MODE (ptr->pattern));
-+ if (gcse_file)
-+ fprintf (gcse_file, "Removing redundant store:\n");
-+ replace_store_insn (r, XEXP (st, 0), bb);
-+ XEXP (st, 0) = insn;
-+ continue;
-+ }
-+ }
-+ SET_BIT (ae_gen[bb->index], ptr->index);
-+ AVAIL_STORE_LIST (ptr) = alloc_INSN_LIST (insn,
-+ AVAIL_STORE_LIST (ptr));
-+ }
-+
-+ if (!store_killed_before (ptr->pattern, insn, bb))
-+ {
-+ SET_BIT (st_antloc[BLOCK_NUM (insn)], ptr->index);
-+ ANTIC_STORE_LIST (ptr) = alloc_INSN_LIST (insn,
-+ ANTIC_STORE_LIST (ptr));
-+ }
-+ }
-+
-+ /* Free the original list of store insns. */
-+ free_INSN_LIST_list (&store_list);
-+ }
-+
-+ ae_kill = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
-+ sbitmap_vector_zero (ae_kill, last_basic_block);
-+
-+ transp = (sbitmap *) sbitmap_vector_alloc (last_basic_block, num_stores);
-+ sbitmap_vector_zero (transp, last_basic_block);
-+
-+ for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
-+ FOR_EACH_BB (b)
-+ {
-+ if (store_killed_after (ptr->pattern, b->head, b))
-+ {
-+ /* The anticipatable expression is not killed if it's gen'd. */
-+ /*
-+ We leave this check out for now. If we have a code sequence
-+ in a block which looks like:
-+ ST MEMa = x
-+ L y = MEMa
-+ ST MEMa = z
-+ We should flag this as having an ANTIC expression, NOT
-+ transparent, NOT killed, and AVAIL.
-+ Unfortunately, since we haven't re-written all loads to
-+ use the reaching reg, we'll end up doing an incorrect
-+ Load in the middle here if we push the store down. It happens in
-+ gcc.c-torture/execute/960311-1.c with -O3
-+ If we always kill it in this case, we'll sometimes do
-+ uneccessary work, but it shouldn't actually hurt anything.
-+ if (!TEST_BIT (ae_gen[b], ptr->index)). */
-+ SET_BIT (ae_kill[b->index], ptr->index);
-+ }
-+ else
-+ SET_BIT (transp[b->index], ptr->index);
-+ }
-+
-+ /* Any block with no exits calls some non-returning function, so
-+ we better mark the store killed here, or we might not store to
-+ it at all. If we knew it was abort, we wouldn't have to store,
-+ but we don't know that for sure. */
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "ST_avail and ST_antic (shown under loads..)\n");
-+ print_ldst_list (gcse_file);
-+ dump_sbitmap_vector (gcse_file, "st_antloc", "", st_antloc, last_basic_block);
-+ dump_sbitmap_vector (gcse_file, "st_kill", "", ae_kill, last_basic_block);
-+ dump_sbitmap_vector (gcse_file, "Transpt", "", transp, last_basic_block);
-+ dump_sbitmap_vector (gcse_file, "st_avloc", "", ae_gen, last_basic_block);
-+ }
-+}
-+
-+/* Insert an instruction at the begining of a basic block, and update
-+ the BLOCK_HEAD if needed. */
-+
-+static void
-+insert_insn_start_bb (insn, bb)
-+ rtx insn;
-+ basic_block bb;
-+{
-+ /* Insert at start of successor block. */
-+ rtx prev = PREV_INSN (bb->head);
-+ rtx before = bb->head;
-+ while (before != 0)
-+ {
-+ if (GET_CODE (before) != CODE_LABEL
-+ && (GET_CODE (before) != NOTE
-+ || NOTE_LINE_NUMBER (before) != NOTE_INSN_BASIC_BLOCK))
-+ break;
-+ prev = before;
-+ if (prev == bb->end)
-+ break;
-+ before = NEXT_INSN (before);
-+ }
-+
-+ insn = emit_insn_after (insn, prev);
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "STORE_MOTION insert store at start of BB %d:\n",
-+ bb->index);
-+ print_inline_rtx (gcse_file, insn, 6);
-+ fprintf (gcse_file, "\n");
-+ }
-+}
-+
-+/* This routine will insert a store on an edge. EXPR is the ldst entry for
-+ the memory reference, and E is the edge to insert it on. Returns nonzero
-+ if an edge insertion was performed. */
-+
-+static int
-+insert_store (expr, e)
-+ struct ls_expr * expr;
-+ edge e;
-+{
-+ rtx reg, insn;
-+ basic_block bb;
-+ edge tmp;
-+
-+ /* We did all the deleted before this insert, so if we didn't delete a
-+ store, then we haven't set the reaching reg yet either. */
-+ if (expr->reaching_reg == NULL_RTX)
-+ return 0;
-+
-+ reg = expr->reaching_reg;
-+ insn = gen_move_insn (expr->pattern, reg);
-+
-+ /* If we are inserting this expression on ALL predecessor edges of a BB,
-+ insert it at the start of the BB, and reset the insert bits on the other
-+ edges so we don't try to insert it on the other edges. */
-+ bb = e->dest;
-+ for (tmp = e->dest->pred; tmp ; tmp = tmp->pred_next)
-+ {
-+ int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
-+ if (index == EDGE_INDEX_NO_EDGE)
-+ abort ();
-+ if (! TEST_BIT (pre_insert_map[index], expr->index))
-+ break;
-+ }
-+
-+ /* If tmp is NULL, we found an insertion on every edge, blank the
-+ insertion vector for these edges, and insert at the start of the BB. */
-+ if (!tmp && bb != EXIT_BLOCK_PTR)
-+ {
-+ for (tmp = e->dest->pred; tmp ; tmp = tmp->pred_next)
-+ {
-+ int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest);
-+ RESET_BIT (pre_insert_map[index], expr->index);
-+ }
-+ insert_insn_start_bb (insn, bb);
-+ return 0;
-+ }
-+
-+ /* We can't insert on this edge, so we'll insert at the head of the
-+ successors block. See Morgan, sec 10.5. */
-+ if ((e->flags & EDGE_ABNORMAL) == EDGE_ABNORMAL)
-+ {
-+ insert_insn_start_bb (insn, bb);
-+ return 0;
-+ }
-+
-+ insert_insn_on_edge (insn, e);
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "STORE_MOTION insert insn on edge (%d, %d):\n",
-+ e->src->index, e->dest->index);
-+ print_inline_rtx (gcse_file, insn, 6);
-+ fprintf (gcse_file, "\n");
-+ }
-+
-+ return 1;
-+}
-+
-+/* This routine will replace a store with a SET to a specified register. */
-+
-+static void
-+replace_store_insn (reg, del, bb)
-+ rtx reg, del;
-+ basic_block bb;
-+{
-+ rtx insn;
-+
-+ insn = gen_move_insn (reg, SET_SRC (PATTERN (del)));
-+ insn = emit_insn_after (insn, del);
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file,
-+ "STORE_MOTION delete insn in BB %d:\n ", bb->index);
-+ print_inline_rtx (gcse_file, del, 6);
-+ fprintf (gcse_file, "\nSTORE MOTION replaced with insn:\n ");
-+ print_inline_rtx (gcse_file, insn, 6);
-+ fprintf (gcse_file, "\n");
-+ }
-+
-+ delete_insn (del);
-+}
-+
-+
-+/* Delete a store, but copy the value that would have been stored into
-+ the reaching_reg for later storing. */
-+
-+static void
-+delete_store (expr, bb)
-+ struct ls_expr * expr;
-+ basic_block bb;
-+{
-+ rtx reg, i, del;
-+
-+ if (expr->reaching_reg == NULL_RTX)
-+ expr->reaching_reg = gen_reg_rtx (GET_MODE (expr->pattern));
-+
-+
-+ /* If there is more than 1 store, the earlier ones will be dead,
-+ but it doesn't hurt to replace them here. */
-+ reg = expr->reaching_reg;
-+
-+ for (i = AVAIL_STORE_LIST (expr); i; i = XEXP (i, 1))
-+ {
-+ del = XEXP (i, 0);
-+ if (BLOCK_FOR_INSN (del) == bb)
-+ {
-+ /* We know there is only one since we deleted redundant
-+ ones during the available computation. */
-+ replace_store_insn (reg, del, bb);
-+ break;
-+ }
-+ }
-+}
-+
-+/* Free memory used by store motion. */
-+
-+static void
-+free_store_memory ()
-+{
-+ free_ldst_mems ();
-+
-+ if (ae_gen)
-+ sbitmap_vector_free (ae_gen);
-+ if (ae_kill)
-+ sbitmap_vector_free (ae_kill);
-+ if (transp)
-+ sbitmap_vector_free (transp);
-+ if (st_antloc)
-+ sbitmap_vector_free (st_antloc);
-+ if (pre_insert_map)
-+ sbitmap_vector_free (pre_insert_map);
-+ if (pre_delete_map)
-+ sbitmap_vector_free (pre_delete_map);
-+ if (reg_set_in_block)
-+ sbitmap_vector_free (reg_set_in_block);
-+
-+ ae_gen = ae_kill = transp = st_antloc = NULL;
-+ pre_insert_map = pre_delete_map = reg_set_in_block = NULL;
-+}
-+
-+/* Perform store motion. Much like gcse, except we move expressions the
-+ other way by looking at the flowgraph in reverse. */
-+
-+static void
-+store_motion ()
-+{
-+ basic_block bb;
-+ int x;
-+ struct ls_expr * ptr;
-+ int update_flow = 0;
-+
-+ if (gcse_file)
-+ {
-+ fprintf (gcse_file, "before store motion\n");
-+ print_rtl (gcse_file, get_insns ());
-+ }
-+
-+
-+ init_alias_analysis ();
-+
-+ /* Find all the stores that are live to the end of their block. */
-+ num_stores = compute_store_table ();
-+ if (num_stores == 0)
-+ {
-+ sbitmap_vector_free (reg_set_in_block);
-+ end_alias_analysis ();
-+ return;
-+ }
-+
-+ /* Now compute whats actually available to move. */
-+ add_noreturn_fake_exit_edges ();
-+ build_store_vectors ();
-+
-+ edge_list = pre_edge_rev_lcm (gcse_file, num_stores, transp, ae_gen,
-+ st_antloc, ae_kill, &pre_insert_map,
-+ &pre_delete_map);
-+
-+ /* Now we want to insert the new stores which are going to be needed. */
-+ for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr))
-+ {
-+ FOR_EACH_BB (bb)
-+ if (TEST_BIT (pre_delete_map[bb->index], ptr->index))
-+ delete_store (ptr, bb);
-+
-+ for (x = 0; x < NUM_EDGES (edge_list); x++)
-+ if (TEST_BIT (pre_insert_map[x], ptr->index))
-+ update_flow |= insert_store (ptr, INDEX_EDGE (edge_list, x));
-+ }
-+
-+ if (update_flow)
-+ commit_edge_insertions ();
-+
-+ free_store_memory ();
-+ free_edge_list (edge_list);
-+ remove_fake_edges ();
-+ end_alias_analysis ();
-+}
-+
-+#include "gt-gcse.h"
-diff -ruN gcc-3.3.1/gcc/integrate.c gcc-3.3.1.pp/gcc/integrate.c
---- gcc-3.3.1/gcc/integrate.c 2003-07-15 01:05:43.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/integrate.c 2003-09-05 11:58:59.000000000 +0000
-@@ -401,6 +401,10 @@
- /* These args would always appear unused, if not for this. */
- TREE_USED (copy) = 1;
-
-+ /* The inlined variable is marked as INLINE not to sweep by propolice */
-+ if (flag_propolice_protection && TREE_CODE (copy) == VAR_DECL)
-+ DECL_INLINE (copy) = 1;
-+
- /* Set the context for the new declaration. */
- if (!DECL_CONTEXT (decl))
- /* Globals stay global. */
-@@ -1965,6 +1969,10 @@
-
- seq = get_insns ();
- end_sequence ();
-+#ifdef FRAME_GROWS_DOWNWARD
-+ if (flag_propolice_protection && GET_CODE (seq) == SET)
-+ RTX_INTEGRATED_P (SET_SRC (seq)) = 1;
-+#endif
- emit_insn_after (seq, map->insns_at_start);
- return temp;
- }
-diff -ruN gcc-3.3.1/gcc/integrate.c.orig gcc-3.3.1.pp/gcc/integrate.c.orig
---- gcc-3.3.1/gcc/integrate.c.orig 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/integrate.c.orig 2003-07-15 01:05:43.000000000 +0000
-@@ -0,0 +1,3213 @@
-+/* Procedure integration for GCC.
-+ Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
-+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
-+ Contributed by Michael Tiemann (tiemann@cygnus.com)
-+
-+This file is part of GCC.
-+
-+GCC is free software; you can redistribute it and/or modify it under
-+the terms of the GNU General Public License as published by the Free
-+Software Foundation; either version 2, or (at your option) any later
-+version.
-+
-+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-+WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GCC; see the file COPYING. If not, write to the Free
-+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-+02111-1307, USA. */
-+
-+#include "config.h"
-+#include "system.h"
-+
-+#include "rtl.h"
-+#include "tree.h"
-+#include "tm_p.h"
-+#include "regs.h"
-+#include "flags.h"
-+#include "debug.h"
-+#include "insn-config.h"
-+#include "expr.h"
-+#include "output.h"
-+#include "recog.h"
-+#include "integrate.h"
-+#include "real.h"
-+#include "except.h"
-+#include "function.h"
-+#include "toplev.h"
-+#include "intl.h"
-+#include "loop.h"
-+#include "params.h"
-+#include "ggc.h"
-+#include "target.h"
-+#include "langhooks.h"
-+
-+/* Similar, but round to the next highest integer that meets the
-+ alignment. */
-+#define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
-+
-+/* Default max number of insns a function can have and still be inline.
-+ This is overridden on RISC machines. */
-+#ifndef INTEGRATE_THRESHOLD
-+/* Inlining small functions might save more space then not inlining at
-+ all. Assume 1 instruction for the call and 1.5 insns per argument. */
-+#define INTEGRATE_THRESHOLD(DECL) \
-+ (optimize_size \
-+ ? (1 + (3 * list_length (DECL_ARGUMENTS (DECL))) / 2) \
-+ : (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
-+#endif
-+\f
-+
-+/* Private type used by {get/has}_func_hard_reg_initial_val. */
-+typedef struct initial_value_pair GTY(()) {
-+ rtx hard_reg;
-+ rtx pseudo;
-+} initial_value_pair;
-+typedef struct initial_value_struct GTY(()) {
-+ int num_entries;
-+ int max_entries;
-+ initial_value_pair * GTY ((length ("%h.num_entries"))) entries;
-+} initial_value_struct;
-+
-+static void setup_initial_hard_reg_value_integration PARAMS ((struct function *, struct inline_remap *));
-+
-+static rtvec initialize_for_inline PARAMS ((tree));
-+static void note_modified_parmregs PARAMS ((rtx, rtx, void *));
-+static void integrate_parm_decls PARAMS ((tree, struct inline_remap *,
-+ rtvec));
-+static tree integrate_decl_tree PARAMS ((tree,
-+ struct inline_remap *));
-+static void subst_constants PARAMS ((rtx *, rtx,
-+ struct inline_remap *, int));
-+static void set_block_origin_self PARAMS ((tree));
-+static void set_block_abstract_flags PARAMS ((tree, int));
-+static void process_reg_param PARAMS ((struct inline_remap *, rtx,
-+ rtx));
-+void set_decl_abstract_flags PARAMS ((tree, int));
-+static void mark_stores PARAMS ((rtx, rtx, void *));
-+static void save_parm_insns PARAMS ((rtx, rtx));
-+static void copy_insn_list PARAMS ((rtx, struct inline_remap *,
-+ rtx));
-+static void copy_insn_notes PARAMS ((rtx, struct inline_remap *,
-+ int));
-+static int compare_blocks PARAMS ((const PTR, const PTR));
-+static int find_block PARAMS ((const PTR, const PTR));
-+
-+/* Used by copy_rtx_and_substitute; this indicates whether the function is
-+ called for the purpose of inlining or some other purpose (i.e. loop
-+ unrolling). This affects how constant pool references are handled.
-+ This variable contains the FUNCTION_DECL for the inlined function. */
-+static struct function *inlining = 0;
-+\f
-+/* Returns the Ith entry in the label_map contained in MAP. If the
-+ Ith entry has not yet been set, return a fresh label. This function
-+ performs a lazy initialization of label_map, thereby avoiding huge memory
-+ explosions when the label_map gets very large. */
-+
-+rtx
-+get_label_from_map (map, i)
-+ struct inline_remap *map;
-+ int i;
-+{
-+ rtx x = map->label_map[i];
-+
-+ if (x == NULL_RTX)
-+ x = map->label_map[i] = gen_label_rtx ();
-+
-+ return x;
-+}
-+
-+/* Return false if the function FNDECL cannot be inlined on account of its
-+ attributes, true otherwise. */
-+bool
-+function_attribute_inlinable_p (fndecl)
-+ tree fndecl;
-+{
-+ if (targetm.attribute_table)
-+ {
-+ tree a;
-+
-+ for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
-+ {
-+ tree name = TREE_PURPOSE (a);
-+ int i;
-+
-+ for (i = 0; targetm.attribute_table[i].name != NULL; i++)
-+ if (is_attribute_p (targetm.attribute_table[i].name, name))
-+ return (*targetm.function_attribute_inlinable_p) (fndecl);
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+/* Zero if the current function (whose FUNCTION_DECL is FNDECL)
-+ is safe and reasonable to integrate into other functions.
-+ Nonzero means value is a warning msgid with a single %s
-+ for the function's name. */
-+
-+const char *
-+function_cannot_inline_p (fndecl)
-+ tree fndecl;
-+{
-+ rtx insn;
-+ tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
-+
-+ /* For functions marked as inline increase the maximum size to
-+ MAX_INLINE_INSNS_RTL (--param max-inline-insn-rtl=<n>). For
-+ regular functions use the limit given by INTEGRATE_THRESHOLD.
-+ Note that the RTL inliner is not used by the languages that use
-+ the tree inliner (C, C++). */
-+
-+ int max_insns = (DECL_INLINE (fndecl))
-+ ? (MAX_INLINE_INSNS_RTL
-+ + 8 * list_length (DECL_ARGUMENTS (fndecl)))
-+ : INTEGRATE_THRESHOLD (fndecl);
-+
-+ int ninsns = 0;
-+ tree parms;
-+
-+ if (DECL_UNINLINABLE (fndecl))
-+ return N_("function cannot be inline");
-+
-+ /* No inlines with varargs. */
-+ if (last && TREE_VALUE (last) != void_type_node)
-+ return N_("varargs function cannot be inline");
-+
-+ if (current_function_calls_alloca)
-+ return N_("function using alloca cannot be inline");
-+
-+ if (current_function_calls_setjmp)
-+ return N_("function using setjmp cannot be inline");
-+
-+ if (current_function_calls_eh_return)
-+ return N_("function uses __builtin_eh_return");
-+
-+ if (current_function_contains_functions)
-+ return N_("function with nested functions cannot be inline");
-+
-+ if (forced_labels)
-+ return
-+ N_("function with label addresses used in initializers cannot inline");
-+
-+ if (current_function_cannot_inline)
-+ return current_function_cannot_inline;
-+
-+ /* If its not even close, don't even look. */
-+ if (get_max_uid () > 3 * max_insns)
-+ return N_("function too large to be inline");
-+
-+#if 0
-+ /* Don't inline functions which do not specify a function prototype and
-+ have BLKmode argument or take the address of a parameter. */
-+ for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
-+ {
-+ if (TYPE_MODE (TREE_TYPE (parms)) == BLKmode)
-+ TREE_ADDRESSABLE (parms) = 1;
-+ if (last == NULL_TREE && TREE_ADDRESSABLE (parms))
-+ return N_("no prototype, and parameter address used; cannot be inline");
-+ }
-+#endif
-+
-+ /* We can't inline functions that return structures
-+ the old-fashioned PCC way, copying into a static block. */
-+ if (current_function_returns_pcc_struct)
-+ return N_("inline functions not supported for this return value type");
-+
-+ /* We can't inline functions that return structures of varying size. */
-+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
-+ && int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0)
-+ return N_("function with varying-size return value cannot be inline");
-+
-+ /* Cannot inline a function with a varying size argument or one that
-+ receives a transparent union. */
-+ for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
-+ {
-+ if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
-+ return N_("function with varying-size parameter cannot be inline");
-+ else if (TREE_CODE (TREE_TYPE (parms)) == UNION_TYPE
-+ && TYPE_TRANSPARENT_UNION (TREE_TYPE (parms)))
-+ return N_("function with transparent unit parameter cannot be inline");
-+ }
-+
-+ if (get_max_uid () > max_insns)
-+ {
-+ for (ninsns = 0, insn = get_first_nonparm_insn ();
-+ insn && ninsns < max_insns;
-+ insn = NEXT_INSN (insn))
-+ if (INSN_P (insn))
-+ ninsns++;
-+
-+ if (ninsns >= max_insns)
-+ return N_("function too large to be inline");
-+ }
-+
-+ /* We will not inline a function which uses computed goto. The addresses of
-+ its local labels, which may be tucked into global storage, are of course
-+ not constant across instantiations, which causes unexpected behavior. */
-+ if (current_function_has_computed_jump)
-+ return N_("function with computed jump cannot inline");
-+
-+ /* We cannot inline a nested function that jumps to a nonlocal label. */
-+ if (current_function_has_nonlocal_goto)
-+ return N_("function with nonlocal goto cannot be inline");
-+
-+ /* We can't inline functions that return a PARALLEL rtx. */
-+ if (DECL_RTL_SET_P (DECL_RESULT (fndecl)))
-+ {
-+ rtx result = DECL_RTL (DECL_RESULT (fndecl));
-+ if (GET_CODE (result) == PARALLEL)
-+ return N_("inline functions not supported for this return value type");
-+ }
-+
-+ /* If the function has a target specific attribute attached to it,
-+ then we assume that we should not inline it. This can be overriden
-+ by the target if it defines TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P. */
-+ if (!function_attribute_inlinable_p (fndecl))
-+ return N_("function with target specific attribute(s) cannot be inlined");
-+
-+ return NULL;
-+}
-+\f
-+/* Map pseudo reg number into the PARM_DECL for the parm living in the reg.
-+ Zero for a reg that isn't a parm's home.
-+ Only reg numbers less than max_parm_reg are mapped here. */
-+static tree *parmdecl_map;
-+
-+/* In save_for_inline, nonzero if past the parm-initialization insns. */
-+static int in_nonparm_insns;
-+\f
-+/* Subroutine for `save_for_inline'. Performs initialization
-+ needed to save FNDECL's insns and info for future inline expansion. */
-+
-+static rtvec
-+initialize_for_inline (fndecl)
-+ tree fndecl;
-+{
-+ int i;
-+ rtvec arg_vector;
-+ tree parms;
-+
-+ /* Clear out PARMDECL_MAP. It was allocated in the caller's frame. */
-+ memset ((char *) parmdecl_map, 0, max_parm_reg * sizeof (tree));
-+ arg_vector = rtvec_alloc (list_length (DECL_ARGUMENTS (fndecl)));
-+
-+ for (parms = DECL_ARGUMENTS (fndecl), i = 0;
-+ parms;
-+ parms = TREE_CHAIN (parms), i++)
-+ {
-+ rtx p = DECL_RTL (parms);
-+
-+ /* If we have (mem (addressof (mem ...))), use the inner MEM since
-+ otherwise the copy_rtx call below will not unshare the MEM since
-+ it shares ADDRESSOF. */
-+ if (GET_CODE (p) == MEM && GET_CODE (XEXP (p, 0)) == ADDRESSOF
-+ && GET_CODE (XEXP (XEXP (p, 0), 0)) == MEM)
-+ p = XEXP (XEXP (p, 0), 0);
-+
-+ RTVEC_ELT (arg_vector, i) = p;
-+
-+ if (GET_CODE (p) == REG)
-+ parmdecl_map[REGNO (p)] = parms;
-+ else if (GET_CODE (p) == CONCAT)
-+ {
-+ rtx preal = gen_realpart (GET_MODE (XEXP (p, 0)), p);
-+ rtx pimag = gen_imagpart (GET_MODE (preal), p);
-+
-+ if (GET_CODE (preal) == REG)
-+ parmdecl_map[REGNO (preal)] = parms;
-+ if (GET_CODE (pimag) == REG)
-+ parmdecl_map[REGNO (pimag)] = parms;
-+ }
-+
-+ /* This flag is cleared later
-+ if the function ever modifies the value of the parm. */
-+ TREE_READONLY (parms) = 1;
-+ }
-+
-+ return arg_vector;
-+}
-+
-+/* Copy NODE (which must be a DECL, but not a PARM_DECL). The DECL
-+ originally was in the FROM_FN, but now it will be in the
-+ TO_FN. */
-+
-+tree
-+copy_decl_for_inlining (decl, from_fn, to_fn)
-+ tree decl;
-+ tree from_fn;
-+ tree to_fn;
-+{
-+ tree copy;
-+
-+ /* Copy the declaration. */
-+ if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL)
-+ {
-+ tree type;
-+ int invisiref = 0;
-+
-+ /* See if the frontend wants to pass this by invisible reference. */
-+ if (TREE_CODE (decl) == PARM_DECL
-+ && DECL_ARG_TYPE (decl) != TREE_TYPE (decl)
-+ && POINTER_TYPE_P (DECL_ARG_TYPE (decl))
-+ && TREE_TYPE (DECL_ARG_TYPE (decl)) == TREE_TYPE (decl))
-+ {
-+ invisiref = 1;
-+ type = DECL_ARG_TYPE (decl);
-+ }
-+ else
-+ type = TREE_TYPE (decl);
-+
-+ /* For a parameter, we must make an equivalent VAR_DECL, not a
-+ new PARM_DECL. */
-+ copy = build_decl (VAR_DECL, DECL_NAME (decl), type);
-+ if (!invisiref)
-+ {
-+ TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
-+ TREE_READONLY (copy) = TREE_READONLY (decl);
-+ TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
-+ }
-+ else
-+ {
-+ TREE_ADDRESSABLE (copy) = 0;
-+ TREE_READONLY (copy) = 1;
-+ TREE_THIS_VOLATILE (copy) = 0;
-+ }
-+ }
-+ else
-+ {
-+ copy = copy_node (decl);
-+ /* The COPY is not abstract; it will be generated in TO_FN. */
-+ DECL_ABSTRACT (copy) = 0;
-+ (*lang_hooks.dup_lang_specific_decl) (copy);
-+
-+ /* TREE_ADDRESSABLE isn't used to indicate that a label's
-+ address has been taken; it's for internal bookkeeping in
-+ expand_goto_internal. */
-+ if (TREE_CODE (copy) == LABEL_DECL)
-+ TREE_ADDRESSABLE (copy) = 0;
-+ }
-+
-+ /* Set the DECL_ABSTRACT_ORIGIN so the debugging routines know what
-+ declaration inspired this copy. */
-+ DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
-+
-+ /* The new variable/label has no RTL, yet. */
-+ SET_DECL_RTL (copy, NULL_RTX);
-+
-+ /* These args would always appear unused, if not for this. */
-+ TREE_USED (copy) = 1;
-+
-+ /* Set the context for the new declaration. */
-+ if (!DECL_CONTEXT (decl))
-+ /* Globals stay global. */
-+ ;
-+ else if (DECL_CONTEXT (decl) != from_fn)
-+ /* Things that weren't in the scope of the function we're inlining
-+ from aren't in the scope we're inlining too, either. */
-+ ;
-+ else if (TREE_STATIC (decl))
-+ /* Function-scoped static variables should say in the original
-+ function. */
-+ ;
-+ else
-+ /* Ordinary automatic local variables are now in the scope of the
-+ new function. */
-+ DECL_CONTEXT (copy) = to_fn;
-+
-+ return copy;
-+}
-+
-+/* Make the insns and PARM_DECLs of the current function permanent
-+ and record other information in DECL_SAVED_INSNS to allow inlining
-+ of this function in subsequent calls.
-+
-+ This routine need not copy any insns because we are not going
-+ to immediately compile the insns in the insn chain. There
-+ are two cases when we would compile the insns for FNDECL:
-+ (1) when FNDECL is expanded inline, and (2) when FNDECL needs to
-+ be output at the end of other compilation, because somebody took
-+ its address. In the first case, the insns of FNDECL are copied
-+ as it is expanded inline, so FNDECL's saved insns are not
-+ modified. In the second case, FNDECL is used for the last time,
-+ so modifying the rtl is not a problem.
-+
-+ We don't have to worry about FNDECL being inline expanded by
-+ other functions which are written at the end of compilation
-+ because flag_no_inline is turned on when we begin writing
-+ functions at the end of compilation. */
-+
-+void
-+save_for_inline (fndecl)
-+ tree fndecl;
-+{
-+ rtx insn;
-+ rtvec argvec;
-+ rtx first_nonparm_insn;
-+
-+ /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
-+ Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
-+ Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
-+ for the parms, prior to elimination of virtual registers.
-+ These values are needed for substituting parms properly. */
-+ if (! flag_no_inline)
-+ parmdecl_map = (tree *) xmalloc (max_parm_reg * sizeof (tree));
-+
-+ /* Make and emit a return-label if we have not already done so. */
-+
-+ if (return_label == 0)
-+ {
-+ return_label = gen_label_rtx ();
-+ emit_label (return_label);
-+ }
-+
-+ if (! flag_no_inline)
-+ argvec = initialize_for_inline (fndecl);
-+ else
-+ argvec = NULL;
-+
-+ /* Delete basic block notes created by early run of find_basic_block.
-+ The notes would be later used by find_basic_blocks to reuse the memory
-+ for basic_block structures on already freed obstack. */
-+ for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
-+ delete_related_insns (insn);
-+
-+ /* If there are insns that copy parms from the stack into pseudo registers,
-+ those insns are not copied. `expand_inline_function' must
-+ emit the correct code to handle such things. */
-+
-+ insn = get_insns ();
-+ if (GET_CODE (insn) != NOTE)
-+ abort ();
-+
-+ if (! flag_no_inline)
-+ {
-+ /* Get the insn which signals the end of parameter setup code. */
-+ first_nonparm_insn = get_first_nonparm_insn ();
-+
-+ /* Now just scan the chain of insns to see what happens to our
-+ PARM_DECLs. If a PARM_DECL is used but never modified, we
-+ can substitute its rtl directly when expanding inline (and
-+ perform constant folding when its incoming value is
-+ constant). Otherwise, we have to copy its value into a new
-+ register and track the new register's life. */
-+ in_nonparm_insns = 0;
-+ save_parm_insns (insn, first_nonparm_insn);
-+
-+ cfun->inl_max_label_num = max_label_num ();
-+ cfun->inl_last_parm_insn = cfun->x_last_parm_insn;
-+ cfun->original_arg_vector = argvec;
-+ }
-+ cfun->original_decl_initial = DECL_INITIAL (fndecl);
-+ cfun->no_debugging_symbols = (write_symbols == NO_DEBUG);
-+ DECL_SAVED_INSNS (fndecl) = cfun;
-+
-+ /* Clean up. */
-+ if (! flag_no_inline)
-+ free (parmdecl_map);
-+}
-+
-+/* Scan the chain of insns to see what happens to our PARM_DECLs. If a
-+ PARM_DECL is used but never modified, we can substitute its rtl directly
-+ when expanding inline (and perform constant folding when its incoming
-+ value is constant). Otherwise, we have to copy its value into a new
-+ register and track the new register's life. */
-+
-+static void
-+save_parm_insns (insn, first_nonparm_insn)
-+ rtx insn;
-+ rtx first_nonparm_insn;
-+{
-+ if (insn == NULL_RTX)
-+ return;
-+
-+ for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
-+ {
-+ if (insn == first_nonparm_insn)
-+ in_nonparm_insns = 1;
-+
-+ if (INSN_P (insn))
-+ {
-+ /* Record what interesting things happen to our parameters. */
-+ note_stores (PATTERN (insn), note_modified_parmregs, NULL);
-+
-+ /* If this is a CALL_PLACEHOLDER insn then we need to look into the
-+ three attached sequences: normal call, sibling call and tail
-+ recursion. */
-+ if (GET_CODE (insn) == CALL_INSN
-+ && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-+ {
-+ int i;
-+
-+ for (i = 0; i < 3; i++)
-+ save_parm_insns (XEXP (PATTERN (insn), i),
-+ first_nonparm_insn);
-+ }
-+ }
-+ }
-+}
-+\f
-+/* Note whether a parameter is modified or not. */
-+
-+static void
-+note_modified_parmregs (reg, x, data)
-+ rtx reg;
-+ rtx x ATTRIBUTE_UNUSED;
-+ void *data ATTRIBUTE_UNUSED;
-+{
-+ if (GET_CODE (reg) == REG && in_nonparm_insns
-+ && REGNO (reg) < max_parm_reg
-+ && REGNO (reg) >= FIRST_PSEUDO_REGISTER
-+ && parmdecl_map[REGNO (reg)] != 0)
-+ TREE_READONLY (parmdecl_map[REGNO (reg)]) = 0;
-+}
-+
-+/* Unfortunately, we need a global copy of const_equiv map for communication
-+ with a function called from note_stores. Be *very* careful that this
-+ is used properly in the presence of recursion. */
-+
-+varray_type global_const_equiv_varray;
-+\f
-+#define FIXED_BASE_PLUS_P(X) \
-+ (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
-+ && GET_CODE (XEXP (X, 0)) == REG \
-+ && REGNO (XEXP (X, 0)) >= FIRST_VIRTUAL_REGISTER \
-+ && REGNO (XEXP (X, 0)) <= LAST_VIRTUAL_REGISTER)
-+
-+/* Called to set up a mapping for the case where a parameter is in a
-+ register. If it is read-only and our argument is a constant, set up the
-+ constant equivalence.
-+
-+ If LOC is REG_USERVAR_P, the usual case, COPY must also have that flag set
-+ if it is a register.
-+
-+ Also, don't allow hard registers here; they might not be valid when
-+ substituted into insns. */
-+static void
-+process_reg_param (map, loc, copy)
-+ struct inline_remap *map;
-+ rtx loc, copy;
-+{
-+ if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
-+ || (GET_CODE (copy) == REG && REG_USERVAR_P (loc)
-+ && ! REG_USERVAR_P (copy))
-+ || (GET_CODE (copy) == REG
-+ && REGNO (copy) < FIRST_PSEUDO_REGISTER))
-+ {
-+ rtx temp = copy_to_mode_reg (GET_MODE (loc), copy);
-+ REG_USERVAR_P (temp) = REG_USERVAR_P (loc);
-+ if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
-+ SET_CONST_EQUIV_DATA (map, temp, copy, CONST_AGE_PARM);
-+ copy = temp;
-+ }
-+ map->reg_map[REGNO (loc)] = copy;
-+}
-+
-+/* Compare two BLOCKs for qsort. The key we sort on is the
-+ BLOCK_ABSTRACT_ORIGIN of the blocks. We cannot just subtract the
-+ two pointers, because it may overflow sizeof(int). */
-+
-+static int
-+compare_blocks (v1, v2)
-+ const PTR v1;
-+ const PTR v2;
-+{
-+ tree b1 = *((const tree *) v1);
-+ tree b2 = *((const tree *) v2);
-+ char *p1 = (char *) BLOCK_ABSTRACT_ORIGIN (b1);
-+ char *p2 = (char *) BLOCK_ABSTRACT_ORIGIN (b2);
-+
-+ if (p1 == p2)
-+ return 0;
-+ return p1 < p2 ? -1 : 1;
-+}
-+
-+/* Compare two BLOCKs for bsearch. The first pointer corresponds to
-+ an original block; the second to a remapped equivalent. */
-+
-+static int
-+find_block (v1, v2)
-+ const PTR v1;
-+ const PTR v2;
-+{
-+ const union tree_node *b1 = (const union tree_node *) v1;
-+ tree b2 = *((const tree *) v2);
-+ char *p1 = (char *) b1;
-+ char *p2 = (char *) BLOCK_ABSTRACT_ORIGIN (b2);
-+
-+ if (p1 == p2)
-+ return 0;
-+ return p1 < p2 ? -1 : 1;
-+}
-+
-+/* Integrate the procedure defined by FNDECL. Note that this function
-+ may wind up calling itself. Since the static variables are not
-+ reentrant, we do not assign them until after the possibility
-+ of recursion is eliminated.
-+
-+ If IGNORE is nonzero, do not produce a value.
-+ Otherwise store the value in TARGET if it is nonzero and that is convenient.
-+
-+ Value is:
-+ (rtx)-1 if we could not substitute the function
-+ 0 if we substituted it and it does not produce a value
-+ else an rtx for where the value is stored. */
-+
-+rtx
-+expand_inline_function (fndecl, parms, target, ignore, type,
-+ structure_value_addr)
-+ tree fndecl, parms;
-+ rtx target;
-+ int ignore;
-+ tree type;
-+ rtx structure_value_addr;
-+{
-+ struct function *inlining_previous;
-+ struct function *inl_f = DECL_SAVED_INSNS (fndecl);
-+ tree formal, actual, block;
-+ rtx parm_insns = inl_f->emit->x_first_insn;
-+ rtx insns = (inl_f->inl_last_parm_insn
-+ ? NEXT_INSN (inl_f->inl_last_parm_insn)
-+ : parm_insns);
-+ tree *arg_trees;
-+ rtx *arg_vals;
-+ int max_regno;
-+ int i;
-+ int min_labelno = inl_f->emit->x_first_label_num;
-+ int max_labelno = inl_f->inl_max_label_num;
-+ int nargs;
-+ rtx loc;
-+ rtx stack_save = 0;
-+ rtx temp;
-+ struct inline_remap *map = 0;
-+ rtvec arg_vector = inl_f->original_arg_vector;
-+ rtx static_chain_value = 0;
-+ int inl_max_uid;
-+ int eh_region_offset;
-+
-+ /* The pointer used to track the true location of the memory used
-+ for MAP->LABEL_MAP. */
-+ rtx *real_label_map = 0;
-+
-+ /* Allow for equivalences of the pseudos we make for virtual fp and ap. */
-+ max_regno = inl_f->emit->x_reg_rtx_no + 3;
-+ if (max_regno < FIRST_PSEUDO_REGISTER)
-+ abort ();
-+
-+ /* Pull out the decl for the function definition; fndecl may be a
-+ local declaration, which would break DECL_ABSTRACT_ORIGIN. */
-+ fndecl = inl_f->decl;
-+
-+ nargs = list_length (DECL_ARGUMENTS (fndecl));
-+
-+ if (cfun->preferred_stack_boundary < inl_f->preferred_stack_boundary)
-+ cfun->preferred_stack_boundary = inl_f->preferred_stack_boundary;
-+
-+ /* Check that the parms type match and that sufficient arguments were
-+ passed. Since the appropriate conversions or default promotions have
-+ already been applied, the machine modes should match exactly. */
-+
-+ for (formal = DECL_ARGUMENTS (fndecl), actual = parms;
-+ formal;
-+ formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual))
-+ {
-+ tree arg;
-+ enum machine_mode mode;
-+
-+ if (actual == 0)
-+ return (rtx) (size_t) -1;
-+
-+ arg = TREE_VALUE (actual);
-+ mode = TYPE_MODE (DECL_ARG_TYPE (formal));
-+
-+ if (arg == error_mark_node
-+ || mode != TYPE_MODE (TREE_TYPE (arg))
-+ /* If they are block mode, the types should match exactly.
-+ They don't match exactly if TREE_TYPE (FORMAL) == ERROR_MARK_NODE,
-+ which could happen if the parameter has incomplete type. */
-+ || (mode == BLKmode
-+ && (TYPE_MAIN_VARIANT (TREE_TYPE (arg))
-+ != TYPE_MAIN_VARIANT (TREE_TYPE (formal)))))
-+ return (rtx) (size_t) -1;
-+ }
-+
-+ /* Extra arguments are valid, but will be ignored below, so we must
-+ evaluate them here for side-effects. */
-+ for (; actual; actual = TREE_CHAIN (actual))
-+ expand_expr (TREE_VALUE (actual), const0_rtx,
-+ TYPE_MODE (TREE_TYPE (TREE_VALUE (actual))), 0);
-+
-+ /* Expand the function arguments. Do this first so that any
-+ new registers get created before we allocate the maps. */
-+
-+ arg_vals = (rtx *) xmalloc (nargs * sizeof (rtx));
-+ arg_trees = (tree *) xmalloc (nargs * sizeof (tree));
-+
-+ for (formal = DECL_ARGUMENTS (fndecl), actual = parms, i = 0;
-+ formal;
-+ formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual), i++)
-+ {
-+ /* Actual parameter, converted to the type of the argument within the
-+ function. */
-+ tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual));
-+ /* Mode of the variable used within the function. */
-+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal));
-+ int invisiref = 0;
-+
-+ arg_trees[i] = arg;
-+ loc = RTVEC_ELT (arg_vector, i);
-+
-+ /* If this is an object passed by invisible reference, we copy the
-+ object into a stack slot and save its address. If this will go
-+ into memory, we do nothing now. Otherwise, we just expand the
-+ argument. */
-+ if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
-+ && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
-+ {
-+ rtx stack_slot = assign_temp (TREE_TYPE (arg), 1, 1, 1);
-+
-+ store_expr (arg, stack_slot, 0);
-+ arg_vals[i] = XEXP (stack_slot, 0);
-+ invisiref = 1;
-+ }
-+ else if (GET_CODE (loc) != MEM)
-+ {
-+ if (GET_MODE (loc) != TYPE_MODE (TREE_TYPE (arg)))
-+ {
-+ int unsignedp = TREE_UNSIGNED (TREE_TYPE (formal));
-+ enum machine_mode pmode = TYPE_MODE (TREE_TYPE (formal));
-+
-+ pmode = promote_mode (TREE_TYPE (formal), pmode,
-+ &unsignedp, 0);
-+
-+ if (GET_MODE (loc) != pmode)
-+ abort ();
-+
-+ /* The mode if LOC and ARG can differ if LOC was a variable
-+ that had its mode promoted via PROMOTED_MODE. */
-+ arg_vals[i] = convert_modes (pmode,
-+ TYPE_MODE (TREE_TYPE (arg)),
-+ expand_expr (arg, NULL_RTX, mode,
-+ EXPAND_SUM),
-+ unsignedp);
-+ }
-+ else
-+ arg_vals[i] = expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);
-+ }
-+ else
-+ arg_vals[i] = 0;
-+
-+ if (arg_vals[i] != 0
-+ && (! TREE_READONLY (formal)
-+ /* If the parameter is not read-only, copy our argument through
-+ a register. Also, we cannot use ARG_VALS[I] if it overlaps
-+ TARGET in any way. In the inline function, they will likely
-+ be two different pseudos, and `safe_from_p' will make all
-+ sorts of smart assumptions about their not conflicting.
-+ But if ARG_VALS[I] overlaps TARGET, these assumptions are
-+ wrong, so put ARG_VALS[I] into a fresh register.
-+ Don't worry about invisible references, since their stack
-+ temps will never overlap the target. */
-+ || (target != 0
-+ && ! invisiref
-+ && (GET_CODE (arg_vals[i]) == REG
-+ || GET_CODE (arg_vals[i]) == SUBREG
-+ || GET_CODE (arg_vals[i]) == MEM)
-+ && reg_overlap_mentioned_p (arg_vals[i], target))
-+ /* ??? We must always copy a SUBREG into a REG, because it might
-+ get substituted into an address, and not all ports correctly
-+ handle SUBREGs in addresses. */
-+ || (GET_CODE (arg_vals[i]) == SUBREG)))
-+ arg_vals[i] = copy_to_mode_reg (GET_MODE (loc), arg_vals[i]);
-+
-+ if (arg_vals[i] != 0 && GET_CODE (arg_vals[i]) == REG
-+ && POINTER_TYPE_P (TREE_TYPE (formal)))
-+ mark_reg_pointer (arg_vals[i],
-+ TYPE_ALIGN (TREE_TYPE (TREE_TYPE (formal))));
-+ }
-+
-+ /* Allocate the structures we use to remap things. */
-+
-+ map = (struct inline_remap *) xcalloc (1, sizeof (struct inline_remap));
-+ map->fndecl = fndecl;
-+
-+ VARRAY_TREE_INIT (map->block_map, 10, "block_map");
-+ map->reg_map = (rtx *) xcalloc (max_regno, sizeof (rtx));
-+
-+ /* We used to use alloca here, but the size of what it would try to
-+ allocate would occasionally cause it to exceed the stack limit and
-+ cause unpredictable core dumps. */
-+ real_label_map
-+ = (rtx *) xmalloc ((max_labelno) * sizeof (rtx));
-+ map->label_map = real_label_map;
-+ map->local_return_label = NULL_RTX;
-+
-+ inl_max_uid = (inl_f->emit->x_cur_insn_uid + 1);
-+ map->insn_map = (rtx *) xcalloc (inl_max_uid, sizeof (rtx));
-+ map->min_insnno = 0;
-+ map->max_insnno = inl_max_uid;
-+
-+ map->integrating = 1;
-+ map->compare_src = NULL_RTX;
-+ map->compare_mode = VOIDmode;
-+
-+ /* const_equiv_varray maps pseudos in our routine to constants, so
-+ it needs to be large enough for all our pseudos. This is the
-+ number we are currently using plus the number in the called
-+ routine, plus 15 for each arg, five to compute the virtual frame
-+ pointer, and five for the return value. This should be enough
-+ for most cases. We do not reference entries outside the range of
-+ the map.
-+
-+ ??? These numbers are quite arbitrary and were obtained by
-+ experimentation. At some point, we should try to allocate the
-+ table after all the parameters are set up so we can more accurately
-+ estimate the number of pseudos we will need. */
-+
-+ VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray,
-+ (max_reg_num ()
-+ + (max_regno - FIRST_PSEUDO_REGISTER)
-+ + 15 * nargs
-+ + 10),
-+ "expand_inline_function");
-+ map->const_age = 0;
-+
-+ /* Record the current insn in case we have to set up pointers to frame
-+ and argument memory blocks. If there are no insns yet, add a dummy
-+ insn that can be used as an insertion point. */
-+ map->insns_at_start = get_last_insn ();
-+ if (map->insns_at_start == 0)
-+ map->insns_at_start = emit_note (NULL, NOTE_INSN_DELETED);
-+
-+ map->regno_pointer_align = inl_f->emit->regno_pointer_align;
-+ map->x_regno_reg_rtx = inl_f->emit->x_regno_reg_rtx;
-+
-+ /* Update the outgoing argument size to allow for those in the inlined
-+ function. */
-+ if (inl_f->outgoing_args_size > current_function_outgoing_args_size)
-+ current_function_outgoing_args_size = inl_f->outgoing_args_size;
-+
-+ /* If the inline function needs to make PIC references, that means
-+ that this function's PIC offset table must be used. */
-+ if (inl_f->uses_pic_offset_table)
-+ current_function_uses_pic_offset_table = 1;
-+
-+ /* If this function needs a context, set it up. */
-+ if (inl_f->needs_context)
-+ static_chain_value = lookup_static_chain (fndecl);
-+
-+ if (GET_CODE (parm_insns) == NOTE
-+ && NOTE_LINE_NUMBER (parm_insns) > 0)
-+ {
-+ rtx note = emit_note (NOTE_SOURCE_FILE (parm_insns),
-+ NOTE_LINE_NUMBER (parm_insns));
-+ if (note)
-+ RTX_INTEGRATED_P (note) = 1;
-+ }
-+
-+ /* Process each argument. For each, set up things so that the function's
-+ reference to the argument will refer to the argument being passed.
-+ We only replace REG with REG here. Any simplifications are done
-+ via const_equiv_map.
-+
-+ We make two passes: In the first, we deal with parameters that will
-+ be placed into registers, since we need to ensure that the allocated
-+ register number fits in const_equiv_map. Then we store all non-register
-+ parameters into their memory location. */
-+
-+ /* Don't try to free temp stack slots here, because we may put one of the
-+ parameters into a temp stack slot. */
-+
-+ for (i = 0; i < nargs; i++)
-+ {
-+ rtx copy = arg_vals[i];
-+
-+ loc = RTVEC_ELT (arg_vector, i);
-+
-+ /* There are three cases, each handled separately. */
-+ if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
-+ && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
-+ {
-+ /* This must be an object passed by invisible reference (it could
-+ also be a variable-sized object, but we forbid inlining functions
-+ with variable-sized arguments). COPY is the address of the
-+ actual value (this computation will cause it to be copied). We
-+ map that address for the register, noting the actual address as
-+ an equivalent in case it can be substituted into the insns. */
-+
-+ if (GET_CODE (copy) != REG)
-+ {
-+ temp = copy_addr_to_reg (copy);
-+ if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
-+ SET_CONST_EQUIV_DATA (map, temp, copy, CONST_AGE_PARM);
-+ copy = temp;
-+ }
-+ map->reg_map[REGNO (XEXP (loc, 0))] = copy;
-+ }
-+ else if (GET_CODE (loc) == MEM)
-+ {
-+ /* This is the case of a parameter that lives in memory. It
-+ will live in the block we allocate in the called routine's
-+ frame that simulates the incoming argument area. Do nothing
-+ with the parameter now; we will call store_expr later. In
-+ this case, however, we must ensure that the virtual stack and
-+ incoming arg rtx values are expanded now so that we can be
-+ sure we have enough slots in the const equiv map since the
-+ store_expr call can easily blow the size estimate. */
-+ if (DECL_SAVED_INSNS (fndecl)->args_size != 0)
-+ copy_rtx_and_substitute (virtual_incoming_args_rtx, map, 0);
-+ }
-+ else if (GET_CODE (loc) == REG)
-+ process_reg_param (map, loc, copy);
-+ else if (GET_CODE (loc) == CONCAT)
-+ {
-+ rtx locreal = gen_realpart (GET_MODE (XEXP (loc, 0)), loc);
-+ rtx locimag = gen_imagpart (GET_MODE (XEXP (loc, 0)), loc);
-+ rtx copyreal = gen_realpart (GET_MODE (locreal), copy);
-+ rtx copyimag = gen_imagpart (GET_MODE (locimag), copy);
-+
-+ process_reg_param (map, locreal, copyreal);
-+ process_reg_param (map, locimag, copyimag);
-+ }
-+ else
-+ abort ();
-+ }
-+
-+ /* Tell copy_rtx_and_substitute to handle constant pool SYMBOL_REFs
-+ specially. This function can be called recursively, so we need to
-+ save the previous value. */
-+ inlining_previous = inlining;
-+ inlining = inl_f;
-+
-+ /* Now do the parameters that will be placed in memory. */
-+
-+ for (formal = DECL_ARGUMENTS (fndecl), i = 0;
-+ formal; formal = TREE_CHAIN (formal), i++)
-+ {
-+ loc = RTVEC_ELT (arg_vector, i);
-+
-+ if (GET_CODE (loc) == MEM
-+ /* Exclude case handled above. */
-+ && ! (GET_CODE (XEXP (loc, 0)) == REG
-+ && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER))
-+ {
-+ rtx note = emit_note (DECL_SOURCE_FILE (formal),
-+ DECL_SOURCE_LINE (formal));
-+ if (note)
-+ RTX_INTEGRATED_P (note) = 1;
-+
-+ /* Compute the address in the area we reserved and store the
-+ value there. */
-+ temp = copy_rtx_and_substitute (loc, map, 1);
-+ subst_constants (&temp, NULL_RTX, map, 1);
-+ apply_change_group ();
-+ if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
-+ temp = change_address (temp, VOIDmode, XEXP (temp, 0));
-+ store_expr (arg_trees[i], temp, 0);
-+ }
-+ }
-+
-+ /* Deal with the places that the function puts its result.
-+ We are driven by what is placed into DECL_RESULT.
-+
-+ Initially, we assume that we don't have anything special handling for
-+ REG_FUNCTION_RETURN_VALUE_P. */
-+
-+ map->inline_target = 0;
-+ loc = (DECL_RTL_SET_P (DECL_RESULT (fndecl))
-+ ? DECL_RTL (DECL_RESULT (fndecl)) : NULL_RTX);
-+
-+ if (TYPE_MODE (type) == VOIDmode)
-+ /* There is no return value to worry about. */
-+ ;
-+ else if (GET_CODE (loc) == MEM)
-+ {
-+ if (GET_CODE (XEXP (loc, 0)) == ADDRESSOF)
-+ {
-+ temp = copy_rtx_and_substitute (loc, map, 1);
-+ subst_constants (&temp, NULL_RTX, map, 1);
-+ apply_change_group ();
-+ target = temp;
-+ }
-+ else
-+ {
-+ if (! structure_value_addr
-+ || ! aggregate_value_p (DECL_RESULT (fndecl)))
-+ abort ();
-+
-+ /* Pass the function the address in which to return a structure
-+ value. Note that a constructor can cause someone to call us
-+ with STRUCTURE_VALUE_ADDR, but the initialization takes place
-+ via the first parameter, rather than the struct return address.
-+
-+ We have two cases: If the address is a simple register
-+ indirect, use the mapping mechanism to point that register to
-+ our structure return address. Otherwise, store the structure
-+ return value into the place that it will be referenced from. */
-+
-+ if (GET_CODE (XEXP (loc, 0)) == REG)
-+ {
-+ temp = force_operand (structure_value_addr, NULL_RTX);
-+ temp = force_reg (Pmode, temp);
-+ /* A virtual register might be invalid in an insn, because
-+ it can cause trouble in reload. Since we don't have access
-+ to the expanders at map translation time, make sure we have
-+ a proper register now.
-+ If a virtual register is actually valid, cse or combine
-+ can put it into the mapped insns. */
-+ if (REGNO (temp) >= FIRST_VIRTUAL_REGISTER
-+ && REGNO (temp) <= LAST_VIRTUAL_REGISTER)
-+ temp = copy_to_mode_reg (Pmode, temp);
-+ map->reg_map[REGNO (XEXP (loc, 0))] = temp;
-+
-+ if (CONSTANT_P (structure_value_addr)
-+ || GET_CODE (structure_value_addr) == ADDRESSOF
-+ || (GET_CODE (structure_value_addr) == PLUS
-+ && (XEXP (structure_value_addr, 0)
-+ == virtual_stack_vars_rtx)
-+ && (GET_CODE (XEXP (structure_value_addr, 1))
-+ == CONST_INT)))
-+ {
-+ SET_CONST_EQUIV_DATA (map, temp, structure_value_addr,
-+ CONST_AGE_PARM);
-+ }
-+ }
-+ else
-+ {
-+ temp = copy_rtx_and_substitute (loc, map, 1);
-+ subst_constants (&temp, NULL_RTX, map, 0);
-+ apply_change_group ();
-+ emit_move_insn (temp, structure_value_addr);
-+ }
-+ }
-+ }
-+ else if (ignore)
-+ /* We will ignore the result value, so don't look at its structure.
-+ Note that preparations for an aggregate return value
-+ do need to be made (above) even if it will be ignored. */
-+ ;
-+ else if (GET_CODE (loc) == REG)
-+ {
-+ /* The function returns an object in a register and we use the return
-+ value. Set up our target for remapping. */
-+
-+ /* Machine mode function was declared to return. */
-+ enum machine_mode departing_mode = TYPE_MODE (type);
-+ /* (Possibly wider) machine mode it actually computes
-+ (for the sake of callers that fail to declare it right).
-+ We have to use the mode of the result's RTL, rather than
-+ its type, since expand_function_start may have promoted it. */
-+ enum machine_mode arriving_mode
-+ = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
-+ rtx reg_to_map;
-+
-+ /* Don't use MEMs as direct targets because on some machines
-+ substituting a MEM for a REG makes invalid insns.
-+ Let the combiner substitute the MEM if that is valid. */
-+ if (target == 0 || GET_CODE (target) != REG
-+ || GET_MODE (target) != departing_mode)
-+ {
-+ /* Don't make BLKmode registers. If this looks like
-+ a BLKmode object being returned in a register, get
-+ the mode from that, otherwise abort. */
-+ if (departing_mode == BLKmode)
-+ {
-+ if (REG == GET_CODE (DECL_RTL (DECL_RESULT (fndecl))))
-+ {
-+ departing_mode = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
-+ arriving_mode = departing_mode;
-+ }
-+ else
-+ abort ();
-+ }
-+
-+ target = gen_reg_rtx (departing_mode);
-+ }
-+
-+ /* If function's value was promoted before return,
-+ avoid machine mode mismatch when we substitute INLINE_TARGET.
-+ But TARGET is what we will return to the caller. */
-+ if (arriving_mode != departing_mode)
-+ {
-+ /* Avoid creating a paradoxical subreg wider than
-+ BITS_PER_WORD, since that is illegal. */
-+ if (GET_MODE_BITSIZE (arriving_mode) > BITS_PER_WORD)
-+ {
-+ if (!TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (departing_mode),
-+ GET_MODE_BITSIZE (arriving_mode)))
-+ /* Maybe could be handled by using convert_move () ? */
-+ abort ();
-+ reg_to_map = gen_reg_rtx (arriving_mode);
-+ target = gen_lowpart (departing_mode, reg_to_map);
-+ }
-+ else
-+ reg_to_map = gen_rtx_SUBREG (arriving_mode, target, 0);
-+ }
-+ else
-+ reg_to_map = target;
-+
-+ /* Usually, the result value is the machine's return register.
-+ Sometimes it may be a pseudo. Handle both cases. */
-+ if (REG_FUNCTION_VALUE_P (loc))
-+ map->inline_target = reg_to_map;
-+ else
-+ map->reg_map[REGNO (loc)] = reg_to_map;
-+ }
-+ else if (GET_CODE (loc) == CONCAT)
-+ {
-+ enum machine_mode departing_mode = TYPE_MODE (type);
-+ enum machine_mode arriving_mode
-+ = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
-+
-+ if (departing_mode != arriving_mode)
-+ abort ();
-+ if (GET_CODE (XEXP (loc, 0)) != REG
-+ || GET_CODE (XEXP (loc, 1)) != REG)
-+ abort ();
-+
-+ /* Don't use MEMs as direct targets because on some machines
-+ substituting a MEM for a REG makes invalid insns.
-+ Let the combiner substitute the MEM if that is valid. */
-+ if (target == 0 || GET_CODE (target) != REG
-+ || GET_MODE (target) != departing_mode)
-+ target = gen_reg_rtx (departing_mode);
-+
-+ if (GET_CODE (target) != CONCAT)
-+ abort ();
-+
-+ map->reg_map[REGNO (XEXP (loc, 0))] = XEXP (target, 0);
-+ map->reg_map[REGNO (XEXP (loc, 1))] = XEXP (target, 1);
-+ }
-+ else
-+ abort ();
-+
-+ /* Remap the exception handler data pointer from one to the other. */
-+ temp = get_exception_pointer (inl_f);
-+ if (temp)
-+ map->reg_map[REGNO (temp)] = get_exception_pointer (cfun);
-+
-+ /* Initialize label_map. get_label_from_map will actually make
-+ the labels. */
-+ memset ((char *) &map->label_map[min_labelno], 0,
-+ (max_labelno - min_labelno) * sizeof (rtx));
-+
-+ /* Make copies of the decls of the symbols in the inline function, so that
-+ the copies of the variables get declared in the current function. Set
-+ up things so that lookup_static_chain knows that to interpret registers
-+ in SAVE_EXPRs for TYPE_SIZEs as local. */
-+ inline_function_decl = fndecl;
-+ integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);
-+ block = integrate_decl_tree (inl_f->original_decl_initial, map);
-+ BLOCK_ABSTRACT_ORIGIN (block) = DECL_ORIGIN (fndecl);
-+ inline_function_decl = 0;
-+
-+ /* Make a fresh binding contour that we can easily remove. Do this after
-+ expanding our arguments so cleanups are properly scoped. */
-+ expand_start_bindings_and_block (0, block);
-+
-+ /* Sort the block-map so that it will be easy to find remapped
-+ blocks later. */
-+ qsort (&VARRAY_TREE (map->block_map, 0),
-+ map->block_map->elements_used,
-+ sizeof (tree),
-+ compare_blocks);
-+
-+ /* Perform postincrements before actually calling the function. */
-+ emit_queue ();
-+
-+ /* Clean up stack so that variables might have smaller offsets. */
-+ do_pending_stack_adjust ();
-+
-+ /* Save a copy of the location of const_equiv_varray for
-+ mark_stores, called via note_stores. */
-+ global_const_equiv_varray = map->const_equiv_varray;
-+
-+ /* If the called function does an alloca, save and restore the
-+ stack pointer around the call. This saves stack space, but
-+ also is required if this inline is being done between two
-+ pushes. */
-+ if (inl_f->calls_alloca)
-+ emit_stack_save (SAVE_BLOCK, &stack_save, NULL_RTX);
-+
-+ /* Map pseudos used for initial hard reg values. */
-+ setup_initial_hard_reg_value_integration (inl_f, map);
-+
-+ /* Now copy the insns one by one. */
-+ copy_insn_list (insns, map, static_chain_value);
-+
-+ /* Duplicate the EH regions. This will create an offset from the
-+ region numbers in the function we're inlining to the region
-+ numbers in the calling function. This must wait until after
-+ copy_insn_list, as we need the insn map to be complete. */
-+ eh_region_offset = duplicate_eh_regions (inl_f, map);
-+
-+ /* Now copy the REG_NOTES for those insns. */
-+ copy_insn_notes (insns, map, eh_region_offset);
-+
-+ /* If the insn sequence required one, emit the return label. */
-+ if (map->local_return_label)
-+ emit_label (map->local_return_label);
-+
-+ /* Restore the stack pointer if we saved it above. */
-+ if (inl_f->calls_alloca)
-+ emit_stack_restore (SAVE_BLOCK, stack_save, NULL_RTX);
-+
-+ if (! cfun->x_whole_function_mode_p)
-+ /* In statement-at-a-time mode, we just tell the front-end to add
-+ this block to the list of blocks at this binding level. We
-+ can't do it the way it's done for function-at-a-time mode the
-+ superblocks have not been created yet. */
-+ (*lang_hooks.decls.insert_block) (block);
-+ else
-+ {
-+ BLOCK_CHAIN (block)
-+ = BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
-+ BLOCK_CHAIN (DECL_INITIAL (current_function_decl)) = block;
-+ }
-+
-+ /* End the scope containing the copied formal parameter variables
-+ and copied LABEL_DECLs. We pass NULL_TREE for the variables list
-+ here so that expand_end_bindings will not check for unused
-+ variables. That's already been checked for when the inlined
-+ function was defined. */
-+ expand_end_bindings (NULL_TREE, 1, 1);
-+
-+ /* Must mark the line number note after inlined functions as a repeat, so
-+ that the test coverage code can avoid counting the call twice. This
-+ just tells the code to ignore the immediately following line note, since
-+ there already exists a copy of this note before the expanded inline call.
-+ This line number note is still needed for debugging though, so we can't
-+ delete it. */
-+ if (flag_test_coverage)
-+ emit_note (0, NOTE_INSN_REPEATED_LINE_NUMBER);
-+
-+ emit_line_note (input_filename, lineno);
-+
-+ /* If the function returns a BLKmode object in a register, copy it
-+ out of the temp register into a BLKmode memory object. */
-+ if (target
-+ && TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
-+ && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
-+ target = copy_blkmode_from_reg (0, target, TREE_TYPE (TREE_TYPE (fndecl)));
-+
-+ if (structure_value_addr)
-+ {
-+ target = gen_rtx_MEM (TYPE_MODE (type),
-+ memory_address (TYPE_MODE (type),
-+ structure_value_addr));
-+ set_mem_attributes (target, type, 1);
-+ }
-+
-+ /* Make sure we free the things we explicitly allocated with xmalloc. */
-+ if (real_label_map)
-+ free (real_label_map);
-+ VARRAY_FREE (map->const_equiv_varray);
-+ free (map->reg_map);
-+ free (map->insn_map);
-+ free (map);
-+ free (arg_vals);
-+ free (arg_trees);
-+
-+ inlining = inlining_previous;
-+
-+ return target;
-+}
-+
-+/* Make copies of each insn in the given list using the mapping
-+ computed in expand_inline_function. This function may call itself for
-+ insns containing sequences.
-+
-+ Copying is done in two passes, first the insns and then their REG_NOTES.
-+
-+ If static_chain_value is nonzero, it represents the context-pointer
-+ register for the function. */
-+
-+static void
-+copy_insn_list (insns, map, static_chain_value)
-+ rtx insns;
-+ struct inline_remap *map;
-+ rtx static_chain_value;
-+{
-+ int i;
-+ rtx insn;
-+ rtx temp;
-+#ifdef HAVE_cc0
-+ rtx cc0_insn = 0;
-+#endif
-+ rtx static_chain_mem = 0;
-+
-+ /* Copy the insns one by one. Do this in two passes, first the insns and
-+ then their REG_NOTES. */
-+
-+ /* This loop is very similar to the loop in copy_loop_body in unroll.c. */
-+
-+ for (insn = insns; insn; insn = NEXT_INSN (insn))
-+ {
-+ rtx copy, pattern, set;
-+
-+ map->orig_asm_operands_vector = 0;
-+
-+ switch (GET_CODE (insn))
-+ {
-+ case INSN:
-+ pattern = PATTERN (insn);
-+ set = single_set (insn);
-+ copy = 0;
-+ if (GET_CODE (pattern) == USE
-+ && GET_CODE (XEXP (pattern, 0)) == REG
-+ && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
-+ /* The (USE (REG n)) at return from the function should
-+ be ignored since we are changing (REG n) into
-+ inline_target. */
-+ break;
-+
-+ /* Ignore setting a function value that we don't want to use. */
-+ if (map->inline_target == 0
-+ && set != 0
-+ && GET_CODE (SET_DEST (set)) == REG
-+ && REG_FUNCTION_VALUE_P (SET_DEST (set)))
-+ {
-+ if (volatile_refs_p (SET_SRC (set)))
-+ {
-+ rtx new_set;
-+
-+ /* If we must not delete the source,
-+ load it into a new temporary. */
-+ copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
-+
-+ new_set = single_set (copy);
-+ if (new_set == 0)
-+ abort ();
-+
-+ SET_DEST (new_set)
-+ = gen_reg_rtx (GET_MODE (SET_DEST (new_set)));
-+ }
-+ /* If the source and destination are the same and it
-+ has a note on it, keep the insn. */
-+ else if (rtx_equal_p (SET_DEST (set), SET_SRC (set))
-+ && REG_NOTES (insn) != 0)
-+ copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
-+ else
-+ break;
-+ }
-+
-+ /* Similarly if an ignored return value is clobbered. */
-+ else if (map->inline_target == 0
-+ && GET_CODE (pattern) == CLOBBER
-+ && GET_CODE (XEXP (pattern, 0)) == REG
-+ && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
-+ break;
-+
-+ /* Look for the address of the static chain slot. The
-+ rtx_equal_p comparisons against the
-+ static_chain_incoming_rtx below may fail if the static
-+ chain is in memory and the address specified is not
-+ "legitimate". This happens on Xtensa where the static
-+ chain is at a negative offset from argp and where only
-+ positive offsets are legitimate. When the RTL is
-+ generated, the address is "legitimized" by copying it
-+ into a register, causing the rtx_equal_p comparisons to
-+ fail. This workaround looks for code that sets a
-+ register to the address of the static chain. Subsequent
-+ memory references via that register can then be
-+ identified as static chain references. We assume that
-+ the register is only assigned once, and that the static
-+ chain address is only live in one register at a time. */
-+
-+ else if (static_chain_value != 0
-+ && set != 0
-+ && GET_CODE (static_chain_incoming_rtx) == MEM
-+ && GET_CODE (SET_DEST (set)) == REG
-+ && rtx_equal_p (SET_SRC (set),
-+ XEXP (static_chain_incoming_rtx, 0)))
-+ {
-+ static_chain_mem =
-+ gen_rtx_MEM (GET_MODE (static_chain_incoming_rtx),
-+ SET_DEST (set));
-+
-+ /* emit the instruction in case it is used for something
-+ other than setting the static chain; if it's not used,
-+ it can always be removed as dead code */
-+ copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
-+ }
-+
-+ /* If this is setting the static chain rtx, omit it. */
-+ else if (static_chain_value != 0
-+ && set != 0
-+ && (rtx_equal_p (SET_DEST (set),
-+ static_chain_incoming_rtx)
-+ || (static_chain_mem
-+ && rtx_equal_p (SET_DEST (set), static_chain_mem))))
-+ break;
-+
-+ /* If this is setting the static chain pseudo, set it from
-+ the value we want to give it instead. */
-+ else if (static_chain_value != 0
-+ && set != 0
-+ && (rtx_equal_p (SET_SRC (set),
-+ static_chain_incoming_rtx)
-+ || (static_chain_mem
-+ && rtx_equal_p (SET_SRC (set), static_chain_mem))))
-+ {
-+ rtx newdest = copy_rtx_and_substitute (SET_DEST (set), map, 1);
-+
-+ copy = emit_move_insn (newdest, static_chain_value);
-+ if (GET_CODE (static_chain_incoming_rtx) != MEM)
-+ static_chain_value = 0;
-+ }
-+
-+ /* If this is setting the virtual stack vars register, this must
-+ be the code at the handler for a builtin longjmp. The value
-+ saved in the setjmp buffer will be the address of the frame
-+ we've made for this inlined instance within our frame. But we
-+ know the offset of that value so we can use it to reconstruct
-+ our virtual stack vars register from that value. If we are
-+ copying it from the stack pointer, leave it unchanged. */
-+ else if (set != 0
-+ && rtx_equal_p (SET_DEST (set), virtual_stack_vars_rtx))
-+ {
-+ HOST_WIDE_INT offset;
-+ temp = map->reg_map[REGNO (SET_DEST (set))];
-+ temp = VARRAY_CONST_EQUIV (map->const_equiv_varray,
-+ REGNO (temp)).rtx;
-+
-+ if (rtx_equal_p (temp, virtual_stack_vars_rtx))
-+ offset = 0;
-+ else if (GET_CODE (temp) == PLUS
-+ && rtx_equal_p (XEXP (temp, 0), virtual_stack_vars_rtx)
-+ && GET_CODE (XEXP (temp, 1)) == CONST_INT)
-+ offset = INTVAL (XEXP (temp, 1));
-+ else
-+ abort ();
-+
-+ if (rtx_equal_p (SET_SRC (set), stack_pointer_rtx))
-+ temp = SET_SRC (set);
-+ else
-+ temp = force_operand (plus_constant (SET_SRC (set),
-+ - offset),
-+ NULL_RTX);
-+
-+ copy = emit_move_insn (virtual_stack_vars_rtx, temp);
-+ }
-+
-+ else
-+ copy = emit_insn (copy_rtx_and_substitute (pattern, map, 0));
-+ /* REG_NOTES will be copied later. */
-+
-+#ifdef HAVE_cc0
-+ /* If this insn is setting CC0, it may need to look at
-+ the insn that uses CC0 to see what type of insn it is.
-+ In that case, the call to recog via validate_change will
-+ fail. So don't substitute constants here. Instead,
-+ do it when we emit the following insn.
-+
-+ For example, see the pyr.md file. That machine has signed and
-+ unsigned compares. The compare patterns must check the
-+ following branch insn to see which what kind of compare to
-+ emit.
-+
-+ If the previous insn set CC0, substitute constants on it as
-+ well. */
-+ if (sets_cc0_p (PATTERN (copy)) != 0)
-+ cc0_insn = copy;
-+ else
-+ {
-+ if (cc0_insn)
-+ try_constants (cc0_insn, map);
-+ cc0_insn = 0;
-+ try_constants (copy, map);
-+ }
-+#else
-+ try_constants (copy, map);
-+#endif
-+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
-+ break;
-+
-+ case JUMP_INSN:
-+ if (map->integrating && returnjump_p (insn))
-+ {
-+ if (map->local_return_label == 0)
-+ map->local_return_label = gen_label_rtx ();
-+ pattern = gen_jump (map->local_return_label);
-+ }
-+ else
-+ pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
-+
-+ copy = emit_jump_insn (pattern);
-+
-+#ifdef HAVE_cc0
-+ if (cc0_insn)
-+ try_constants (cc0_insn, map);
-+ cc0_insn = 0;
-+#endif
-+ try_constants (copy, map);
-+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
-+
-+ /* If this used to be a conditional jump insn but whose branch
-+ direction is now know, we must do something special. */
-+ if (any_condjump_p (insn) && onlyjump_p (insn) && map->last_pc_value)
-+ {
-+#ifdef HAVE_cc0
-+ /* If the previous insn set cc0 for us, delete it. */
-+ if (only_sets_cc0_p (PREV_INSN (copy)))
-+ delete_related_insns (PREV_INSN (copy));
-+#endif
-+
-+ /* If this is now a no-op, delete it. */
-+ if (map->last_pc_value == pc_rtx)
-+ {
-+ delete_related_insns (copy);
-+ copy = 0;
-+ }
-+ else
-+ /* Otherwise, this is unconditional jump so we must put a
-+ BARRIER after it. We could do some dead code elimination
-+ here, but jump.c will do it just as well. */
-+ emit_barrier ();
-+ }
-+ break;
-+
-+ case CALL_INSN:
-+ /* If this is a CALL_PLACEHOLDER insn then we need to copy the
-+ three attached sequences: normal call, sibling call and tail
-+ recursion. */
-+ if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-+ {
-+ rtx sequence[3];
-+ rtx tail_label;
-+
-+ for (i = 0; i < 3; i++)
-+ {
-+ rtx seq;
-+
-+ sequence[i] = NULL_RTX;
-+ seq = XEXP (PATTERN (insn), i);
-+ if (seq)
-+ {
-+ start_sequence ();
-+ copy_insn_list (seq, map, static_chain_value);
-+ sequence[i] = get_insns ();
-+ end_sequence ();
-+ }
-+ }
-+
-+ /* Find the new tail recursion label.
-+ It will already be substituted into sequence[2]. */
-+ tail_label = copy_rtx_and_substitute (XEXP (PATTERN (insn), 3),
-+ map, 0);
-+
-+ copy = emit_call_insn (gen_rtx_CALL_PLACEHOLDER (VOIDmode,
-+ sequence[0],
-+ sequence[1],
-+ sequence[2],
-+ tail_label));
-+ break;
-+ }
-+
-+ pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
-+ copy = emit_call_insn (pattern);
-+
-+ SIBLING_CALL_P (copy) = SIBLING_CALL_P (insn);
-+ CONST_OR_PURE_CALL_P (copy) = CONST_OR_PURE_CALL_P (insn);
-+ INSN_SCOPE (copy) = INSN_SCOPE (insn);
-+
-+ /* Because the USAGE information potentially contains objects other
-+ than hard registers, we need to copy it. */
-+
-+ CALL_INSN_FUNCTION_USAGE (copy)
-+ = copy_rtx_and_substitute (CALL_INSN_FUNCTION_USAGE (insn),
-+ map, 0);
-+
-+#ifdef HAVE_cc0
-+ if (cc0_insn)
-+ try_constants (cc0_insn, map);
-+ cc0_insn = 0;
-+#endif
-+ try_constants (copy, map);
-+
-+ /* Be lazy and assume CALL_INSNs clobber all hard registers. */
-+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-+ VARRAY_CONST_EQUIV (map->const_equiv_varray, i).rtx = 0;
-+ break;
-+
-+ case CODE_LABEL:
-+ copy = emit_label (get_label_from_map (map,
-+ CODE_LABEL_NUMBER (insn)));
-+ LABEL_NAME (copy) = LABEL_NAME (insn);
-+ map->const_age++;
-+ break;
-+
-+ case BARRIER:
-+ copy = emit_barrier ();
-+ break;
-+
-+ case NOTE:
-+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)
-+ {
-+ copy = emit_label (get_label_from_map (map,
-+ CODE_LABEL_NUMBER (insn)));
-+ LABEL_NAME (copy) = NOTE_SOURCE_FILE (insn);
-+ map->const_age++;
-+ break;
-+ }
-+
-+ /* NOTE_INSN_FUNCTION_END and NOTE_INSN_FUNCTION_BEG are
-+ discarded because it is important to have only one of
-+ each in the current function.
-+
-+ NOTE_INSN_DELETED notes aren't useful. */
-+
-+ if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
-+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
-+ && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
-+ {
-+ copy = emit_note (NOTE_SOURCE_FILE (insn),
-+ NOTE_LINE_NUMBER (insn));
-+ if (copy
-+ && (NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_BEG
-+ || NOTE_LINE_NUMBER (copy) == NOTE_INSN_BLOCK_END)
-+ && NOTE_BLOCK (insn))
-+ {
-+ tree *mapped_block_p;
-+
-+ mapped_block_p
-+ = (tree *) bsearch (NOTE_BLOCK (insn),
-+ &VARRAY_TREE (map->block_map, 0),
-+ map->block_map->elements_used,
-+ sizeof (tree),
-+ find_block);
-+
-+ if (!mapped_block_p)
-+ abort ();
-+ else
-+ NOTE_BLOCK (copy) = *mapped_block_p;
-+ }
-+ else if (copy
-+ && NOTE_LINE_NUMBER (copy) == NOTE_INSN_EXPECTED_VALUE)
-+ NOTE_EXPECTED_VALUE (copy)
-+ = copy_rtx_and_substitute (NOTE_EXPECTED_VALUE (insn),
-+ map, 0);
-+ }
-+ else
-+ copy = 0;
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+
-+ if (copy)
-+ RTX_INTEGRATED_P (copy) = 1;
-+
-+ map->insn_map[INSN_UID (insn)] = copy;
-+ }
-+}
-+
-+/* Copy the REG_NOTES. Increment const_age, so that only constants
-+ from parameters can be substituted in. These are the only ones
-+ that are valid across the entire function. */
-+
-+static void
-+copy_insn_notes (insns, map, eh_region_offset)
-+ rtx insns;
-+ struct inline_remap *map;
-+ int eh_region_offset;
-+{
-+ rtx insn, new_insn;
-+
-+ map->const_age++;
-+ for (insn = insns; insn; insn = NEXT_INSN (insn))
-+ {
-+ if (! INSN_P (insn))
-+ continue;
-+
-+ new_insn = map->insn_map[INSN_UID (insn)];
-+ if (! new_insn)
-+ continue;
-+
-+ if (REG_NOTES (insn))
-+ {
-+ rtx next, note = copy_rtx_and_substitute (REG_NOTES (insn), map, 0);
-+
-+ /* We must also do subst_constants, in case one of our parameters
-+ has const type and constant value. */
-+ subst_constants (¬e, NULL_RTX, map, 0);
-+ apply_change_group ();
-+ REG_NOTES (new_insn) = note;
-+
-+ /* Delete any REG_LABEL notes from the chain. Remap any
-+ REG_EH_REGION notes. */
-+ for (; note; note = next)
-+ {
-+ next = XEXP (note, 1);
-+ if (REG_NOTE_KIND (note) == REG_LABEL)
-+ remove_note (new_insn, note);
-+ else if (REG_NOTE_KIND (note) == REG_EH_REGION
-+ && INTVAL (XEXP (note, 0)) > 0)
-+ XEXP (note, 0) = GEN_INT (INTVAL (XEXP (note, 0))
-+ + eh_region_offset);
-+ }
-+ }
-+
-+ if (GET_CODE (insn) == CALL_INSN
-+ && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-+ {
-+ int i;
-+ for (i = 0; i < 3; i++)
-+ copy_insn_notes (XEXP (PATTERN (insn), i), map, eh_region_offset);
-+ }
-+
-+ if (GET_CODE (insn) == JUMP_INSN
-+ && GET_CODE (PATTERN (insn)) == RESX)
-+ XINT (PATTERN (new_insn), 0) += eh_region_offset;
-+ }
-+}
-+\f
-+/* Given a chain of PARM_DECLs, ARGS, copy each decl into a VAR_DECL,
-+ push all of those decls and give each one the corresponding home. */
-+
-+static void
-+integrate_parm_decls (args, map, arg_vector)
-+ tree args;
-+ struct inline_remap *map;
-+ rtvec arg_vector;
-+{
-+ tree tail;
-+ int i;
-+
-+ for (tail = args, i = 0; tail; tail = TREE_CHAIN (tail), i++)
-+ {
-+ tree decl = copy_decl_for_inlining (tail, map->fndecl,
-+ current_function_decl);
-+ rtx new_decl_rtl
-+ = copy_rtx_and_substitute (RTVEC_ELT (arg_vector, i), map, 1);
-+
-+ /* We really should be setting DECL_INCOMING_RTL to something reasonable
-+ here, but that's going to require some more work. */
-+ /* DECL_INCOMING_RTL (decl) = ?; */
-+ /* Fully instantiate the address with the equivalent form so that the
-+ debugging information contains the actual register, instead of the
-+ virtual register. Do this by not passing an insn to
-+ subst_constants. */
-+ subst_constants (&new_decl_rtl, NULL_RTX, map, 1);
-+ apply_change_group ();
-+ SET_DECL_RTL (decl, new_decl_rtl);
-+ }
-+}
-+
-+/* Given a BLOCK node LET, push decls and levels so as to construct in the
-+ current function a tree of contexts isomorphic to the one that is given.
-+
-+ MAP, if nonzero, is a pointer to an inline_remap map which indicates how
-+ registers used in the DECL_RTL field should be remapped. If it is zero,
-+ no mapping is necessary. */
-+
-+static tree
-+integrate_decl_tree (let, map)
-+ tree let;
-+ struct inline_remap *map;
-+{
-+ tree t;
-+ tree new_block;
-+ tree *next;
-+
-+ new_block = make_node (BLOCK);
-+ VARRAY_PUSH_TREE (map->block_map, new_block);
-+ next = &BLOCK_VARS (new_block);
-+
-+ for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
-+ {
-+ tree d;
-+
-+ d = copy_decl_for_inlining (t, map->fndecl, current_function_decl);
-+
-+ if (DECL_RTL_SET_P (t))
-+ {
-+ rtx r;
-+
-+ SET_DECL_RTL (d, copy_rtx_and_substitute (DECL_RTL (t), map, 1));
-+
-+ /* Fully instantiate the address with the equivalent form so that the
-+ debugging information contains the actual register, instead of the
-+ virtual register. Do this by not passing an insn to
-+ subst_constants. */
-+ r = DECL_RTL (d);
-+ subst_constants (&r, NULL_RTX, map, 1);
-+ SET_DECL_RTL (d, r);
-+
-+ if (GET_CODE (r) == REG)
-+ REGNO_DECL (REGNO (r)) = d;
-+ else if (GET_CODE (r) == CONCAT)
-+ {
-+ REGNO_DECL (REGNO (XEXP (r, 0))) = d;
-+ REGNO_DECL (REGNO (XEXP (r, 1))) = d;
-+ }
-+
-+ apply_change_group ();
-+ }
-+
-+ /* Add this declaration to the list of variables in the new
-+ block. */
-+ *next = d;
-+ next = &TREE_CHAIN (d);
-+ }
-+
-+ next = &BLOCK_SUBBLOCKS (new_block);
-+ for (t = BLOCK_SUBBLOCKS (let); t; t = BLOCK_CHAIN (t))
-+ {
-+ *next = integrate_decl_tree (t, map);
-+ BLOCK_SUPERCONTEXT (*next) = new_block;
-+ next = &BLOCK_CHAIN (*next);
-+ }
-+
-+ TREE_USED (new_block) = TREE_USED (let);
-+ BLOCK_ABSTRACT_ORIGIN (new_block) = let;
-+
-+ return new_block;
-+}
-+\f
-+/* Create a new copy of an rtx. Recursively copies the operands of the rtx,
-+ except for those few rtx codes that are sharable.
-+
-+ We always return an rtx that is similar to that incoming rtx, with the
-+ exception of possibly changing a REG to a SUBREG or vice versa. No
-+ rtl is ever emitted.
-+
-+ If FOR_LHS is nonzero, if means we are processing something that will
-+ be the LHS of a SET. In that case, we copy RTX_UNCHANGING_P even if
-+ inlining since we need to be conservative in how it is set for
-+ such cases.
-+
-+ Handle constants that need to be placed in the constant pool by
-+ calling `force_const_mem'. */
-+
-+rtx
-+copy_rtx_and_substitute (orig, map, for_lhs)
-+ rtx orig;
-+ struct inline_remap *map;
-+ int for_lhs;
-+{
-+ rtx copy, temp;
-+ int i, j;
-+ RTX_CODE code;
-+ enum machine_mode mode;
-+ const char *format_ptr;
-+ int regno;
-+
-+ if (orig == 0)
-+ return 0;
-+
-+ code = GET_CODE (orig);
-+ mode = GET_MODE (orig);
-+
-+ switch (code)
-+ {
-+ case REG:
-+ /* If the stack pointer register shows up, it must be part of
-+ stack-adjustments (*not* because we eliminated the frame pointer!).
-+ Small hard registers are returned as-is. Pseudo-registers
-+ go through their `reg_map'. */
-+ regno = REGNO (orig);
-+ if (regno <= LAST_VIRTUAL_REGISTER
-+ || (map->integrating
-+ && DECL_SAVED_INSNS (map->fndecl)->internal_arg_pointer == orig))
-+ {
-+ /* Some hard registers are also mapped,
-+ but others are not translated. */
-+ if (map->reg_map[regno] != 0)
-+ return map->reg_map[regno];
-+
-+ /* If this is the virtual frame pointer, make space in current
-+ function's stack frame for the stack frame of the inline function.
-+
-+ Copy the address of this area into a pseudo. Map
-+ virtual_stack_vars_rtx to this pseudo and set up a constant
-+ equivalence for it to be the address. This will substitute the
-+ address into insns where it can be substituted and use the new
-+ pseudo where it can't. */
-+ else if (regno == VIRTUAL_STACK_VARS_REGNUM)
-+ {
-+ rtx loc, seq;
-+ int size = get_func_frame_size (DECL_SAVED_INSNS (map->fndecl));
-+#ifdef FRAME_GROWS_DOWNWARD
-+ int alignment
-+ = (DECL_SAVED_INSNS (map->fndecl)->stack_alignment_needed
-+ / BITS_PER_UNIT);
-+
-+ /* In this case, virtual_stack_vars_rtx points to one byte
-+ higher than the top of the frame area. So make sure we
-+ allocate a big enough chunk to keep the frame pointer
-+ aligned like a real one. */
-+ if (alignment)
-+ size = CEIL_ROUND (size, alignment);
-+#endif
-+ start_sequence ();
-+ loc = assign_stack_temp (BLKmode, size, 1);
-+ loc = XEXP (loc, 0);
-+#ifdef FRAME_GROWS_DOWNWARD
-+ /* In this case, virtual_stack_vars_rtx points to one byte
-+ higher than the top of the frame area. So compute the offset
-+ to one byte higher than our substitute frame. */
-+ loc = plus_constant (loc, size);
-+#endif
-+ map->reg_map[regno] = temp
-+ = force_reg (Pmode, force_operand (loc, NULL_RTX));
-+
-+#ifdef STACK_BOUNDARY
-+ mark_reg_pointer (map->reg_map[regno], STACK_BOUNDARY);
-+#endif
-+
-+ SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
-+
-+ seq = get_insns ();
-+ end_sequence ();
-+ emit_insn_after (seq, map->insns_at_start);
-+ return temp;
-+ }
-+ else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM
-+ || (map->integrating
-+ && (DECL_SAVED_INSNS (map->fndecl)->internal_arg_pointer
-+ == orig)))
-+ {
-+ /* Do the same for a block to contain any arguments referenced
-+ in memory. */
-+ rtx loc, seq;
-+ int size = DECL_SAVED_INSNS (map->fndecl)->args_size;
-+
-+ start_sequence ();
-+ loc = assign_stack_temp (BLKmode, size, 1);
-+ loc = XEXP (loc, 0);
-+ /* When arguments grow downward, the virtual incoming
-+ args pointer points to the top of the argument block,
-+ so the remapped location better do the same. */
-+#ifdef ARGS_GROW_DOWNWARD
-+ loc = plus_constant (loc, size);
-+#endif
-+ map->reg_map[regno] = temp
-+ = force_reg (Pmode, force_operand (loc, NULL_RTX));
-+
-+#ifdef STACK_BOUNDARY
-+ mark_reg_pointer (map->reg_map[regno], STACK_BOUNDARY);
-+#endif
-+
-+ SET_CONST_EQUIV_DATA (map, temp, loc, CONST_AGE_PARM);
-+
-+ seq = get_insns ();
-+ end_sequence ();
-+ emit_insn_after (seq, map->insns_at_start);
-+ return temp;
-+ }
-+ else if (REG_FUNCTION_VALUE_P (orig))
-+ {
-+ /* This is a reference to the function return value. If
-+ the function doesn't have a return value, error. If the
-+ mode doesn't agree, and it ain't BLKmode, make a SUBREG. */
-+ if (map->inline_target == 0)
-+ {
-+ if (rtx_equal_function_value_matters)
-+ /* This is an ignored return value. We must not
-+ leave it in with REG_FUNCTION_VALUE_P set, since
-+ that would confuse subsequent inlining of the
-+ current function into a later function. */
-+ return gen_rtx_REG (GET_MODE (orig), regno);
-+ else
-+ /* Must be unrolling loops or replicating code if we
-+ reach here, so return the register unchanged. */
-+ return orig;
-+ }
-+ else if (GET_MODE (map->inline_target) != BLKmode
-+ && mode != GET_MODE (map->inline_target))
-+ return gen_lowpart (mode, map->inline_target);
-+ else
-+ return map->inline_target;
-+ }
-+#if defined (LEAF_REGISTERS) && defined (LEAF_REG_REMAP)
-+ /* If leaf_renumber_regs_insn() might remap this register to
-+ some other number, make sure we don't share it with the
-+ inlined function, otherwise delayed optimization of the
-+ inlined function may change it in place, breaking our
-+ reference to it. We may still shared it within the
-+ function, so create an entry for this register in the
-+ reg_map. */
-+ if (map->integrating && regno < FIRST_PSEUDO_REGISTER
-+ && LEAF_REGISTERS[regno] && LEAF_REG_REMAP (regno) != regno)
-+ {
-+ if (!map->leaf_reg_map[regno][mode])
-+ map->leaf_reg_map[regno][mode] = gen_rtx_REG (mode, regno);
-+ return map->leaf_reg_map[regno][mode];
-+ }
-+#endif
-+ else
-+ return orig;
-+
-+ abort ();
-+ }
-+ if (map->reg_map[regno] == NULL)
-+ {
-+ map->reg_map[regno] = gen_reg_rtx (mode);
-+ REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (orig);
-+ REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (orig);
-+ RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
-+ /* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
-+
-+ if (REG_POINTER (map->x_regno_reg_rtx[regno]))
-+ mark_reg_pointer (map->reg_map[regno],
-+ map->regno_pointer_align[regno]);
-+ }
-+ return map->reg_map[regno];
-+
-+ case SUBREG:
-+ copy = copy_rtx_and_substitute (SUBREG_REG (orig), map, for_lhs);
-+ return simplify_gen_subreg (GET_MODE (orig), copy,
-+ GET_MODE (SUBREG_REG (orig)),
-+ SUBREG_BYTE (orig));
-+
-+ case ADDRESSOF:
-+ copy = gen_rtx_ADDRESSOF (mode,
-+ copy_rtx_and_substitute (XEXP (orig, 0),
-+ map, for_lhs),
-+ 0, ADDRESSOF_DECL (orig));
-+ regno = ADDRESSOF_REGNO (orig);
-+ if (map->reg_map[regno])
-+ regno = REGNO (map->reg_map[regno]);
-+ else if (regno > LAST_VIRTUAL_REGISTER)
-+ {
-+ temp = XEXP (orig, 0);
-+ map->reg_map[regno] = gen_reg_rtx (GET_MODE (temp));
-+ REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (temp);
-+ REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (temp);
-+ RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (temp);
-+ /* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
-+
-+ /* Objects may initially be represented as registers, but
-+ but turned into a MEM if their address is taken by
-+ put_var_into_stack. Therefore, the register table may have
-+ entries which are MEMs.
-+
-+ We briefly tried to clear such entries, but that ended up
-+ cascading into many changes due to the optimizers not being
-+ prepared for empty entries in the register table. So we've
-+ decided to allow the MEMs in the register table for now. */
-+ if (REG_P (map->x_regno_reg_rtx[regno])
-+ && REG_POINTER (map->x_regno_reg_rtx[regno]))
-+ mark_reg_pointer (map->reg_map[regno],
-+ map->regno_pointer_align[regno]);
-+ regno = REGNO (map->reg_map[regno]);
-+ }
-+ ADDRESSOF_REGNO (copy) = regno;
-+ return copy;
-+
-+ case USE:
-+ case CLOBBER:
-+ /* USE and CLOBBER are ordinary, but we convert (use (subreg foo))
-+ to (use foo) if the original insn didn't have a subreg.
-+ Removing the subreg distorts the VAX movstrhi pattern
-+ by changing the mode of an operand. */
-+ copy = copy_rtx_and_substitute (XEXP (orig, 0), map, code == CLOBBER);
-+ if (GET_CODE (copy) == SUBREG && GET_CODE (XEXP (orig, 0)) != SUBREG)
-+ copy = SUBREG_REG (copy);
-+ return gen_rtx_fmt_e (code, VOIDmode, copy);
-+
-+ /* We need to handle "deleted" labels that appear in the DECL_RTL
-+ of a LABEL_DECL. */
-+ case NOTE:
-+ if (NOTE_LINE_NUMBER (orig) != NOTE_INSN_DELETED_LABEL)
-+ break;
-+
-+ /* ... FALLTHRU ... */
-+ case CODE_LABEL:
-+ LABEL_PRESERVE_P (get_label_from_map (map, CODE_LABEL_NUMBER (orig)))
-+ = LABEL_PRESERVE_P (orig);
-+ return get_label_from_map (map, CODE_LABEL_NUMBER (orig));
-+
-+ case LABEL_REF:
-+ copy
-+ = gen_rtx_LABEL_REF
-+ (mode,
-+ LABEL_REF_NONLOCAL_P (orig) ? XEXP (orig, 0)
-+ : get_label_from_map (map, CODE_LABEL_NUMBER (XEXP (orig, 0))));
-+
-+ LABEL_OUTSIDE_LOOP_P (copy) = LABEL_OUTSIDE_LOOP_P (orig);
-+
-+ /* The fact that this label was previously nonlocal does not mean
-+ it still is, so we must check if it is within the range of
-+ this function's labels. */
-+ LABEL_REF_NONLOCAL_P (copy)
-+ = (LABEL_REF_NONLOCAL_P (orig)
-+ && ! (CODE_LABEL_NUMBER (XEXP (copy, 0)) >= get_first_label_num ()
-+ && CODE_LABEL_NUMBER (XEXP (copy, 0)) < max_label_num ()));
-+
-+ /* If we have made a nonlocal label local, it means that this
-+ inlined call will be referring to our nonlocal goto handler.
-+ So make sure we create one for this block; we normally would
-+ not since this is not otherwise considered a "call". */
-+ if (LABEL_REF_NONLOCAL_P (orig) && ! LABEL_REF_NONLOCAL_P (copy))
-+ function_call_count++;
-+
-+ return copy;
-+
-+ case PC:
-+ case CC0:
-+ case CONST_INT:
-+ case CONST_VECTOR:
-+ return orig;
-+
-+ case SYMBOL_REF:
-+ /* Symbols which represent the address of a label stored in the constant
-+ pool must be modified to point to a constant pool entry for the
-+ remapped label. Otherwise, symbols are returned unchanged. */
-+ if (CONSTANT_POOL_ADDRESS_P (orig))
-+ {
-+ struct function *f = inlining ? inlining : cfun;
-+ rtx constant = get_pool_constant_for_function (f, orig);
-+ enum machine_mode const_mode = get_pool_mode_for_function (f, orig);
-+ if (inlining)
-+ {
-+ rtx temp = force_const_mem (const_mode,
-+ copy_rtx_and_substitute (constant,
-+ map, 0));
-+
-+#if 0
-+ /* Legitimizing the address here is incorrect.
-+
-+ Since we had a SYMBOL_REF before, we can assume it is valid
-+ to have one in this position in the insn.
-+
-+ Also, change_address may create new registers. These
-+ registers will not have valid reg_map entries. This can
-+ cause try_constants() to fail because assumes that all
-+ registers in the rtx have valid reg_map entries, and it may
-+ end up replacing one of these new registers with junk. */
-+
-+ if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
-+ temp = change_address (temp, GET_MODE (temp), XEXP (temp, 0));
-+#endif
-+
-+ temp = XEXP (temp, 0);
-+
-+#ifdef POINTERS_EXTEND_UNSIGNED
-+ if (GET_MODE (temp) != GET_MODE (orig))
-+ temp = convert_memory_address (GET_MODE (orig), temp);
-+#endif
-+ return temp;
-+ }
-+ else if (GET_CODE (constant) == LABEL_REF)
-+ return XEXP (force_const_mem
-+ (GET_MODE (orig),
-+ copy_rtx_and_substitute (constant, map, for_lhs)),
-+ 0);
-+ }
-+
-+ return orig;
-+
-+ case CONST_DOUBLE:
-+ /* We have to make a new copy of this CONST_DOUBLE because don't want
-+ to use the old value of CONST_DOUBLE_MEM. Also, this may be a
-+ duplicate of a CONST_DOUBLE we have already seen. */
-+ if (GET_MODE_CLASS (GET_MODE (orig)) == MODE_FLOAT)
-+ {
-+ REAL_VALUE_TYPE d;
-+
-+ REAL_VALUE_FROM_CONST_DOUBLE (d, orig);
-+ return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (orig));
-+ }
-+ else
-+ return immed_double_const (CONST_DOUBLE_LOW (orig),
-+ CONST_DOUBLE_HIGH (orig), VOIDmode);
-+
-+ case CONST:
-+ /* Make new constant pool entry for a constant
-+ that was in the pool of the inline function. */
-+ if (RTX_INTEGRATED_P (orig))
-+ abort ();
-+ break;
-+
-+ case ASM_OPERANDS:
-+ /* If a single asm insn contains multiple output operands then
-+ it contains multiple ASM_OPERANDS rtx's that share the input
-+ and constraint vecs. We must make sure that the copied insn
-+ continues to share it. */
-+ if (map->orig_asm_operands_vector == ASM_OPERANDS_INPUT_VEC (orig))
-+ {
-+ copy = rtx_alloc (ASM_OPERANDS);
-+ RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
-+ PUT_MODE (copy, GET_MODE (orig));
-+ ASM_OPERANDS_TEMPLATE (copy) = ASM_OPERANDS_TEMPLATE (orig);
-+ ASM_OPERANDS_OUTPUT_CONSTRAINT (copy)
-+ = ASM_OPERANDS_OUTPUT_CONSTRAINT (orig);
-+ ASM_OPERANDS_OUTPUT_IDX (copy) = ASM_OPERANDS_OUTPUT_IDX (orig);
-+ ASM_OPERANDS_INPUT_VEC (copy) = map->copy_asm_operands_vector;
-+ ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy)
-+ = map->copy_asm_constraints_vector;
-+ ASM_OPERANDS_SOURCE_FILE (copy) = ASM_OPERANDS_SOURCE_FILE (orig);
-+ ASM_OPERANDS_SOURCE_LINE (copy) = ASM_OPERANDS_SOURCE_LINE (orig);
-+ return copy;
-+ }
-+ break;
-+
-+ case CALL:
-+ /* This is given special treatment because the first
-+ operand of a CALL is a (MEM ...) which may get
-+ forced into a register for cse. This is undesirable
-+ if function-address cse isn't wanted or if we won't do cse. */
-+#ifndef NO_FUNCTION_CSE
-+ if (! (optimize && ! flag_no_function_cse))
-+#endif
-+ {
-+ rtx copy
-+ = gen_rtx_MEM (GET_MODE (XEXP (orig, 0)),
-+ copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0),
-+ map, 0));
-+
-+ MEM_COPY_ATTRIBUTES (copy, XEXP (orig, 0));
-+
-+ return
-+ gen_rtx_CALL (GET_MODE (orig), copy,
-+ copy_rtx_and_substitute (XEXP (orig, 1), map, 0));
-+ }
-+ break;
-+
-+#if 0
-+ /* Must be ifdefed out for loop unrolling to work. */
-+ case RETURN:
-+ abort ();
-+#endif
-+
-+ case SET:
-+ /* If this is setting fp or ap, it means that we have a nonlocal goto.
-+ Adjust the setting by the offset of the area we made.
-+ If the nonlocal goto is into the current function,
-+ this will result in unnecessarily bad code, but should work. */
-+ if (SET_DEST (orig) == virtual_stack_vars_rtx
-+ || SET_DEST (orig) == virtual_incoming_args_rtx)
-+ {
-+ /* In case a translation hasn't occurred already, make one now. */
-+ rtx equiv_reg;
-+ rtx equiv_loc;
-+ HOST_WIDE_INT loc_offset;
-+
-+ copy_rtx_and_substitute (SET_DEST (orig), map, for_lhs);
-+ equiv_reg = map->reg_map[REGNO (SET_DEST (orig))];
-+ equiv_loc = VARRAY_CONST_EQUIV (map->const_equiv_varray,
-+ REGNO (equiv_reg)).rtx;
-+ loc_offset
-+ = GET_CODE (equiv_loc) == REG ? 0 : INTVAL (XEXP (equiv_loc, 1));
-+
-+ return gen_rtx_SET (VOIDmode, SET_DEST (orig),
-+ force_operand
-+ (plus_constant
-+ (copy_rtx_and_substitute (SET_SRC (orig),
-+ map, 0),
-+ - loc_offset),
-+ NULL_RTX));
-+ }
-+ else
-+ return gen_rtx_SET (VOIDmode,
-+ copy_rtx_and_substitute (SET_DEST (orig), map, 1),
-+ copy_rtx_and_substitute (SET_SRC (orig), map, 0));
-+ break;
-+
-+ case MEM:
-+ if (inlining
-+ && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
-+ && CONSTANT_POOL_ADDRESS_P (XEXP (orig, 0)))
-+ {
-+ enum machine_mode const_mode
-+ = get_pool_mode_for_function (inlining, XEXP (orig, 0));
-+ rtx constant
-+ = get_pool_constant_for_function (inlining, XEXP (orig, 0));
-+
-+ constant = copy_rtx_and_substitute (constant, map, 0);
-+
-+ /* If this was an address of a constant pool entry that itself
-+ had to be placed in the constant pool, it might not be a
-+ valid address. So the recursive call might have turned it
-+ into a register. In that case, it isn't a constant any
-+ more, so return it. This has the potential of changing a
-+ MEM into a REG, but we'll assume that it safe. */
-+ if (! CONSTANT_P (constant))
-+ return constant;
-+
-+ return validize_mem (force_const_mem (const_mode, constant));
-+ }
-+
-+ copy = gen_rtx_MEM (mode, copy_rtx_and_substitute (XEXP (orig, 0),
-+ map, 0));
-+ MEM_COPY_ATTRIBUTES (copy, orig);
-+
-+ /* If inlining and this is not for the LHS, turn off RTX_UNCHANGING_P
-+ since this may be an indirect reference to a parameter and the
-+ actual may not be readonly. */
-+ if (inlining && !for_lhs)
-+ RTX_UNCHANGING_P (copy) = 0;
-+
-+ /* If inlining, squish aliasing data that references the subroutine's
-+ parameter list, since that's no longer applicable. */
-+ if (inlining && MEM_EXPR (copy)
-+ && TREE_CODE (MEM_EXPR (copy)) == INDIRECT_REF
-+ && TREE_CODE (TREE_OPERAND (MEM_EXPR (copy), 0)) == PARM_DECL)
-+ set_mem_expr (copy, NULL_TREE);
-+
-+ return copy;
-+
-+ default:
-+ break;
-+ }
-+
-+ copy = rtx_alloc (code);
-+ PUT_MODE (copy, mode);
-+ RTX_FLAG (copy, in_struct) = RTX_FLAG (orig, in_struct);
-+ RTX_FLAG (copy, volatil) = RTX_FLAG (orig, volatil);
-+ RTX_FLAG (copy, unchanging) = RTX_FLAG (orig, unchanging);
-+
-+ format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
-+
-+ for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
-+ {
-+ switch (*format_ptr++)
-+ {
-+ case '0':
-+ /* Copy this through the wide int field; that's safest. */
-+ X0WINT (copy, i) = X0WINT (orig, i);
-+ break;
-+
-+ case 'e':
-+ XEXP (copy, i)
-+ = copy_rtx_and_substitute (XEXP (orig, i), map, for_lhs);
-+ break;
-+
-+ case 'u':
-+ /* Change any references to old-insns to point to the
-+ corresponding copied insns. */
-+ XEXP (copy, i) = map->insn_map[INSN_UID (XEXP (orig, i))];
-+ break;
-+
-+ case 'E':
-+ XVEC (copy, i) = XVEC (orig, i);
-+ if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)
-+ {
-+ XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
-+ for (j = 0; j < XVECLEN (copy, i); j++)
-+ XVECEXP (copy, i, j)
-+ = copy_rtx_and_substitute (XVECEXP (orig, i, j),
-+ map, for_lhs);
-+ }
-+ break;
-+
-+ case 'w':
-+ XWINT (copy, i) = XWINT (orig, i);
-+ break;
-+
-+ case 'i':
-+ XINT (copy, i) = XINT (orig, i);
-+ break;
-+
-+ case 's':
-+ XSTR (copy, i) = XSTR (orig, i);
-+ break;
-+
-+ case 't':
-+ XTREE (copy, i) = XTREE (orig, i);
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+ }
-+
-+ if (code == ASM_OPERANDS && map->orig_asm_operands_vector == 0)
-+ {
-+ map->orig_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (orig);
-+ map->copy_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (copy);
-+ map->copy_asm_constraints_vector
-+ = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy);
-+ }
-+
-+ return copy;
-+}
-+\f
-+/* Substitute known constant values into INSN, if that is valid. */
-+
-+void
-+try_constants (insn, map)
-+ rtx insn;
-+ struct inline_remap *map;
-+{
-+ int i;
-+
-+ map->num_sets = 0;
-+
-+ /* First try just updating addresses, then other things. This is
-+ important when we have something like the store of a constant
-+ into memory and we can update the memory address but the machine
-+ does not support a constant source. */
-+ subst_constants (&PATTERN (insn), insn, map, 1);
-+ apply_change_group ();
-+ subst_constants (&PATTERN (insn), insn, map, 0);
-+ apply_change_group ();
-+
-+ /* Show we don't know the value of anything stored or clobbered. */
-+ note_stores (PATTERN (insn), mark_stores, NULL);
-+ map->last_pc_value = 0;
-+#ifdef HAVE_cc0
-+ map->last_cc0_value = 0;
-+#endif
-+
-+ /* Set up any constant equivalences made in this insn. */
-+ for (i = 0; i < map->num_sets; i++)
-+ {
-+ if (GET_CODE (map->equiv_sets[i].dest) == REG)
-+ {
-+ int regno = REGNO (map->equiv_sets[i].dest);
-+
-+ MAYBE_EXTEND_CONST_EQUIV_VARRAY (map, regno);
-+ if (VARRAY_CONST_EQUIV (map->const_equiv_varray, regno).rtx == 0
-+ /* Following clause is a hack to make case work where GNU C++
-+ reassigns a variable to make cse work right. */
-+ || ! rtx_equal_p (VARRAY_CONST_EQUIV (map->const_equiv_varray,
-+ regno).rtx,
-+ map->equiv_sets[i].equiv))
-+ SET_CONST_EQUIV_DATA (map, map->equiv_sets[i].dest,
-+ map->equiv_sets[i].equiv, map->const_age);
-+ }
-+ else if (map->equiv_sets[i].dest == pc_rtx)
-+ map->last_pc_value = map->equiv_sets[i].equiv;
-+#ifdef HAVE_cc0
-+ else if (map->equiv_sets[i].dest == cc0_rtx)
-+ map->last_cc0_value = map->equiv_sets[i].equiv;
-+#endif
-+ }
-+}
-+\f
-+/* Substitute known constants for pseudo regs in the contents of LOC,
-+ which are part of INSN.
-+ If INSN is zero, the substitution should always be done (this is used to
-+ update DECL_RTL).
-+ These changes are taken out by try_constants if the result is not valid.
-+
-+ Note that we are more concerned with determining when the result of a SET
-+ is a constant, for further propagation, than actually inserting constants
-+ into insns; cse will do the latter task better.
-+
-+ This function is also used to adjust address of items previously addressed
-+ via the virtual stack variable or virtual incoming arguments registers.
-+
-+ If MEMONLY is nonzero, only make changes inside a MEM. */
-+
-+static void
-+subst_constants (loc, insn, map, memonly)
-+ rtx *loc;
-+ rtx insn;
-+ struct inline_remap *map;
-+ int memonly;
-+{
-+ rtx x = *loc;
-+ int i, j;
-+ enum rtx_code code;
-+ const char *format_ptr;
-+ int num_changes = num_validated_changes ();
-+ rtx new = 0;
-+ enum machine_mode op0_mode = MAX_MACHINE_MODE;
-+
-+ code = GET_CODE (x);
-+
-+ switch (code)
-+ {
-+ case PC:
-+ case CONST_INT:
-+ case CONST_DOUBLE:
-+ case CONST_VECTOR:
-+ case SYMBOL_REF:
-+ case CONST:
-+ case LABEL_REF:
-+ case ADDRESS:
-+ return;
-+
-+#ifdef HAVE_cc0
-+ case CC0:
-+ if (! memonly)
-+ validate_change (insn, loc, map->last_cc0_value, 1);
-+ return;
-+#endif
-+
-+ case USE:
-+ case CLOBBER:
-+ /* The only thing we can do with a USE or CLOBBER is possibly do
-+ some substitutions in a MEM within it. */
-+ if (GET_CODE (XEXP (x, 0)) == MEM)
-+ subst_constants (&XEXP (XEXP (x, 0), 0), insn, map, 0);
-+ return;
-+
-+ case REG:
-+ /* Substitute for parms and known constants. Don't replace
-+ hard regs used as user variables with constants. */
-+ if (! memonly)
-+ {
-+ int regno = REGNO (x);
-+ struct const_equiv_data *p;
-+
-+ if (! (regno < FIRST_PSEUDO_REGISTER && REG_USERVAR_P (x))
-+ && (size_t) regno < VARRAY_SIZE (map->const_equiv_varray)
-+ && (p = &VARRAY_CONST_EQUIV (map->const_equiv_varray, regno),
-+ p->rtx != 0)
-+ && p->age >= map->const_age)
-+ validate_change (insn, loc, p->rtx, 1);
-+ }
-+ return;
-+
-+ case SUBREG:
-+ /* SUBREG applied to something other than a reg
-+ should be treated as ordinary, since that must
-+ be a special hack and we don't know how to treat it specially.
-+ Consider for example mulsidi3 in m68k.md.
-+ Ordinary SUBREG of a REG needs this special treatment. */
-+ if (! memonly && GET_CODE (SUBREG_REG (x)) == REG)
-+ {
-+ rtx inner = SUBREG_REG (x);
-+ rtx new = 0;
-+
-+ /* We can't call subst_constants on &SUBREG_REG (x) because any
-+ constant or SUBREG wouldn't be valid inside our SUBEG. Instead,
-+ see what is inside, try to form the new SUBREG and see if that is
-+ valid. We handle two cases: extracting a full word in an
-+ integral mode and extracting the low part. */
-+ subst_constants (&inner, NULL_RTX, map, 0);
-+ new = simplify_gen_subreg (GET_MODE (x), inner,
-+ GET_MODE (SUBREG_REG (x)),
-+ SUBREG_BYTE (x));
-+
-+ if (new)
-+ validate_change (insn, loc, new, 1);
-+ else
-+ cancel_changes (num_changes);
-+
-+ return;
-+ }
-+ break;
-+
-+ case MEM:
-+ subst_constants (&XEXP (x, 0), insn, map, 0);
-+
-+ /* If a memory address got spoiled, change it back. */
-+ if (! memonly && insn != 0 && num_validated_changes () != num_changes
-+ && ! memory_address_p (GET_MODE (x), XEXP (x, 0)))
-+ cancel_changes (num_changes);
-+ return;
-+
-+ case SET:
-+ {
-+ /* Substitute constants in our source, and in any arguments to a
-+ complex (e..g, ZERO_EXTRACT) destination, but not in the destination
-+ itself. */
-+ rtx *dest_loc = &SET_DEST (x);
-+ rtx dest = *dest_loc;
-+ rtx src, tem;
-+ enum machine_mode compare_mode = VOIDmode;
-+
-+ /* If SET_SRC is a COMPARE which subst_constants would turn into
-+ COMPARE of 2 VOIDmode constants, note the mode in which comparison
-+ is to be done. */
-+ if (GET_CODE (SET_SRC (x)) == COMPARE)
-+ {
-+ src = SET_SRC (x);
-+ if (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
-+#ifdef HAVE_cc0
-+ || dest == cc0_rtx
-+#endif
-+ )
-+ {
-+ compare_mode = GET_MODE (XEXP (src, 0));
-+ if (compare_mode == VOIDmode)
-+ compare_mode = GET_MODE (XEXP (src, 1));
-+ }
-+ }
-+
-+ subst_constants (&SET_SRC (x), insn, map, memonly);
-+ src = SET_SRC (x);
-+
-+ while (GET_CODE (*dest_loc) == ZERO_EXTRACT
-+ || GET_CODE (*dest_loc) == SUBREG
-+ || GET_CODE (*dest_loc) == STRICT_LOW_PART)
-+ {
-+ if (GET_CODE (*dest_loc) == ZERO_EXTRACT)
-+ {
-+ subst_constants (&XEXP (*dest_loc, 1), insn, map, memonly);
-+ subst_constants (&XEXP (*dest_loc, 2), insn, map, memonly);
-+ }
-+ dest_loc = &XEXP (*dest_loc, 0);
-+ }
-+
-+ /* Do substitute in the address of a destination in memory. */
-+ if (GET_CODE (*dest_loc) == MEM)
-+ subst_constants (&XEXP (*dest_loc, 0), insn, map, 0);
-+
-+ /* Check for the case of DEST a SUBREG, both it and the underlying
-+ register are less than one word, and the SUBREG has the wider mode.
-+ In the case, we are really setting the underlying register to the
-+ source converted to the mode of DEST. So indicate that. */
-+ if (GET_CODE (dest) == SUBREG
-+ && GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD
-+ && GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) <= UNITS_PER_WORD
-+ && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
-+ <= GET_MODE_SIZE (GET_MODE (dest)))
-+ && (tem = gen_lowpart_if_possible (GET_MODE (SUBREG_REG (dest)),
-+ src)))
-+ src = tem, dest = SUBREG_REG (dest);
-+
-+ /* If storing a recognizable value save it for later recording. */
-+ if ((map->num_sets < MAX_RECOG_OPERANDS)
-+ && (CONSTANT_P (src)
-+ || (GET_CODE (src) == REG
-+ && (REGNO (src) == VIRTUAL_INCOMING_ARGS_REGNUM
-+ || REGNO (src) == VIRTUAL_STACK_VARS_REGNUM))
-+ || (GET_CODE (src) == PLUS
-+ && GET_CODE (XEXP (src, 0)) == REG
-+ && (REGNO (XEXP (src, 0)) == VIRTUAL_INCOMING_ARGS_REGNUM
-+ || REGNO (XEXP (src, 0)) == VIRTUAL_STACK_VARS_REGNUM)
-+ && CONSTANT_P (XEXP (src, 1)))
-+ || GET_CODE (src) == COMPARE
-+#ifdef HAVE_cc0
-+ || dest == cc0_rtx
-+#endif
-+ || (dest == pc_rtx
-+ && (src == pc_rtx || GET_CODE (src) == RETURN
-+ || GET_CODE (src) == LABEL_REF))))
-+ {
-+ /* Normally, this copy won't do anything. But, if SRC is a COMPARE
-+ it will cause us to save the COMPARE with any constants
-+ substituted, which is what we want for later. */
-+ rtx src_copy = copy_rtx (src);
-+ map->equiv_sets[map->num_sets].equiv = src_copy;
-+ map->equiv_sets[map->num_sets++].dest = dest;
-+ if (compare_mode != VOIDmode
-+ && GET_CODE (src) == COMPARE
-+ && (GET_MODE_CLASS (GET_MODE (src)) == MODE_CC
-+#ifdef HAVE_cc0
-+ || dest == cc0_rtx
-+#endif
-+ )
-+ && GET_MODE (XEXP (src, 0)) == VOIDmode
-+ && GET_MODE (XEXP (src, 1)) == VOIDmode)
-+ {
-+ map->compare_src = src_copy;
-+ map->compare_mode = compare_mode;
-+ }
-+ }
-+ }
-+ return;
-+
-+ default:
-+ break;
-+ }
-+
-+ format_ptr = GET_RTX_FORMAT (code);
-+
-+ /* If the first operand is an expression, save its mode for later. */
-+ if (*format_ptr == 'e')
-+ op0_mode = GET_MODE (XEXP (x, 0));
-+
-+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
-+ {
-+ switch (*format_ptr++)
-+ {
-+ case '0':
-+ break;
-+
-+ case 'e':
-+ if (XEXP (x, i))
-+ subst_constants (&XEXP (x, i), insn, map, memonly);
-+ break;
-+
-+ case 'u':
-+ case 'i':
-+ case 's':
-+ case 'w':
-+ case 'n':
-+ case 't':
-+ case 'B':
-+ break;
-+
-+ case 'E':
-+ if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
-+ for (j = 0; j < XVECLEN (x, i); j++)
-+ subst_constants (&XVECEXP (x, i, j), insn, map, memonly);
-+
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+ }
-+
-+ /* If this is a commutative operation, move a constant to the second
-+ operand unless the second operand is already a CONST_INT. */
-+ if (! memonly
-+ && (GET_RTX_CLASS (code) == 'c' || code == NE || code == EQ)
-+ && CONSTANT_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) != CONST_INT)
-+ {
-+ rtx tem = XEXP (x, 0);
-+ validate_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
-+ validate_change (insn, &XEXP (x, 1), tem, 1);
-+ }
-+
-+ /* Simplify the expression in case we put in some constants. */
-+ if (! memonly)
-+ switch (GET_RTX_CLASS (code))
-+ {
-+ case '1':
-+ if (op0_mode == MAX_MACHINE_MODE)
-+ abort ();
-+ new = simplify_unary_operation (code, GET_MODE (x),
-+ XEXP (x, 0), op0_mode);
-+ break;
-+
-+ case '<':
-+ {
-+ enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
-+
-+ if (op_mode == VOIDmode)
-+ op_mode = GET_MODE (XEXP (x, 1));
-+ new = simplify_relational_operation (code, op_mode,
-+ XEXP (x, 0), XEXP (x, 1));
-+#ifdef FLOAT_STORE_FLAG_VALUE
-+ if (new != 0 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-+ {
-+ enum machine_mode mode = GET_MODE (x);
-+ if (new == const0_rtx)
-+ new = CONST0_RTX (mode);
-+ else
-+ {
-+ REAL_VALUE_TYPE val;
-+
-+ /* Avoid automatic aggregate initialization. */
-+ val = FLOAT_STORE_FLAG_VALUE (mode);
-+ new = CONST_DOUBLE_FROM_REAL_VALUE (val, mode);
-+ }
-+ }
-+#endif
-+ break;
-+ }
-+
-+ case '2':
-+ case 'c':
-+ new = simplify_binary_operation (code, GET_MODE (x),
-+ XEXP (x, 0), XEXP (x, 1));
-+ break;
-+
-+ case 'b':
-+ case '3':
-+ if (op0_mode == MAX_MACHINE_MODE)
-+ abort ();
-+
-+ if (code == IF_THEN_ELSE)
-+ {
-+ rtx op0 = XEXP (x, 0);
-+
-+ if (GET_RTX_CLASS (GET_CODE (op0)) == '<'
-+ && GET_MODE (op0) == VOIDmode
-+ && ! side_effects_p (op0)
-+ && XEXP (op0, 0) == map->compare_src
-+ && GET_MODE (XEXP (op0, 1)) == VOIDmode)
-+ {
-+ /* We have compare of two VOIDmode constants for which
-+ we recorded the comparison mode. */
-+ rtx temp =
-+ simplify_relational_operation (GET_CODE (op0),
-+ map->compare_mode,
-+ XEXP (op0, 0),
-+ XEXP (op0, 1));
-+
-+ if (temp == const0_rtx)
-+ new = XEXP (x, 2);
-+ else if (temp == const1_rtx)
-+ new = XEXP (x, 1);
-+ }
-+ }
-+ if (!new)
-+ new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
-+ XEXP (x, 0), XEXP (x, 1),
-+ XEXP (x, 2));
-+ break;
-+ }
-+
-+ if (new)
-+ validate_change (insn, loc, new, 1);
-+}
-+
-+/* Show that register modified no longer contain known constants. We are
-+ called from note_stores with parts of the new insn. */
-+
-+static void
-+mark_stores (dest, x, data)
-+ rtx dest;
-+ rtx x ATTRIBUTE_UNUSED;
-+ void *data ATTRIBUTE_UNUSED;
-+{
-+ int regno = -1;
-+ enum machine_mode mode = VOIDmode;
-+
-+ /* DEST is always the innermost thing set, except in the case of
-+ SUBREGs of hard registers. */
-+
-+ if (GET_CODE (dest) == REG)
-+ regno = REGNO (dest), mode = GET_MODE (dest);
-+ else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
-+ {
-+ regno = REGNO (SUBREG_REG (dest));
-+ if (regno < FIRST_PSEUDO_REGISTER)
-+ regno += subreg_regno_offset (REGNO (SUBREG_REG (dest)),
-+ GET_MODE (SUBREG_REG (dest)),
-+ SUBREG_BYTE (dest),
-+ GET_MODE (dest));
-+ mode = GET_MODE (SUBREG_REG (dest));
-+ }
-+
-+ if (regno >= 0)
-+ {
-+ unsigned int uregno = regno;
-+ unsigned int last_reg = (uregno >= FIRST_PSEUDO_REGISTER ? uregno
-+ : uregno + HARD_REGNO_NREGS (uregno, mode) - 1);
-+ unsigned int i;
-+
-+ /* Ignore virtual stack var or virtual arg register since those
-+ are handled separately. */
-+ if (uregno != VIRTUAL_INCOMING_ARGS_REGNUM
-+ && uregno != VIRTUAL_STACK_VARS_REGNUM)
-+ for (i = uregno; i <= last_reg; i++)
-+ if ((size_t) i < VARRAY_SIZE (global_const_equiv_varray))
-+ VARRAY_CONST_EQUIV (global_const_equiv_varray, i).rtx = 0;
-+ }
-+}
-+\f
-+/* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
-+ given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
-+ that it points to the node itself, thus indicating that the node is its
-+ own (abstract) origin. Additionally, if the BLOCK_ABSTRACT_ORIGIN for
-+ the given node is NULL, recursively descend the decl/block tree which
-+ it is the root of, and for each other ..._DECL or BLOCK node contained
-+ therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also
-+ still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN
-+ values to point to themselves. */
-+
-+static void
-+set_block_origin_self (stmt)
-+ tree stmt;
-+{
-+ if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE)
-+ {
-+ BLOCK_ABSTRACT_ORIGIN (stmt) = stmt;
-+
-+ {
-+ tree local_decl;
-+
-+ for (local_decl = BLOCK_VARS (stmt);
-+ local_decl != NULL_TREE;
-+ local_decl = TREE_CHAIN (local_decl))
-+ set_decl_origin_self (local_decl); /* Potential recursion. */
-+ }
-+
-+ {
-+ tree subblock;
-+
-+ for (subblock = BLOCK_SUBBLOCKS (stmt);
-+ subblock != NULL_TREE;
-+ subblock = BLOCK_CHAIN (subblock))
-+ set_block_origin_self (subblock); /* Recurse. */
-+ }
-+ }
-+}
-+
-+/* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for
-+ the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the
-+ node to so that it points to the node itself, thus indicating that the
-+ node represents its own (abstract) origin. Additionally, if the
-+ DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend
-+ the decl/block tree of which the given node is the root of, and for
-+ each other ..._DECL or BLOCK node contained therein whose
-+ DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL,
-+ set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to
-+ point to themselves. */
-+
-+void
-+set_decl_origin_self (decl)
-+ tree decl;
-+{
-+ if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE)
-+ {
-+ DECL_ABSTRACT_ORIGIN (decl) = decl;
-+ if (TREE_CODE (decl) == FUNCTION_DECL)
-+ {
-+ tree arg;
-+
-+ for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
-+ DECL_ABSTRACT_ORIGIN (arg) = arg;
-+ if (DECL_INITIAL (decl) != NULL_TREE
-+ && DECL_INITIAL (decl) != error_mark_node)
-+ set_block_origin_self (DECL_INITIAL (decl));
-+ }
-+ }
-+}
-+\f
-+/* Given a pointer to some BLOCK node, and a boolean value to set the
-+ "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for
-+ the given block, and for all local decls and all local sub-blocks
-+ (recursively) which are contained therein. */
-+
-+static void
-+set_block_abstract_flags (stmt, setting)
-+ tree stmt;
-+ int setting;
-+{
-+ tree local_decl;
-+ tree subblock;
-+
-+ BLOCK_ABSTRACT (stmt) = setting;
-+
-+ for (local_decl = BLOCK_VARS (stmt);
-+ local_decl != NULL_TREE;
-+ local_decl = TREE_CHAIN (local_decl))
-+ set_decl_abstract_flags (local_decl, setting);
-+
-+ for (subblock = BLOCK_SUBBLOCKS (stmt);
-+ subblock != NULL_TREE;
-+ subblock = BLOCK_CHAIN (subblock))
-+ set_block_abstract_flags (subblock, setting);
-+}
-+
-+/* Given a pointer to some ..._DECL node, and a boolean value to set the
-+ "abstract" flags to, set that value into the DECL_ABSTRACT flag for the
-+ given decl, and (in the case where the decl is a FUNCTION_DECL) also
-+ set the abstract flags for all of the parameters, local vars, local
-+ blocks and sub-blocks (recursively) to the same setting. */
-+
-+void
-+set_decl_abstract_flags (decl, setting)
-+ tree decl;
-+ int setting;
-+{
-+ DECL_ABSTRACT (decl) = setting;
-+ if (TREE_CODE (decl) == FUNCTION_DECL)
-+ {
-+ tree arg;
-+
-+ for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg))
-+ DECL_ABSTRACT (arg) = setting;
-+ if (DECL_INITIAL (decl) != NULL_TREE
-+ && DECL_INITIAL (decl) != error_mark_node)
-+ set_block_abstract_flags (DECL_INITIAL (decl), setting);
-+ }
-+}
-+\f
-+/* Output the assembly language code for the function FNDECL
-+ from its DECL_SAVED_INSNS. Used for inline functions that are output
-+ at end of compilation instead of where they came in the source. */
-+
-+static GTY(()) struct function *old_cfun;
-+
-+void
-+output_inline_function (fndecl)
-+ tree fndecl;
-+{
-+ enum debug_info_type old_write_symbols = write_symbols;
-+ const struct gcc_debug_hooks *const old_debug_hooks = debug_hooks;
-+ struct function *f = DECL_SAVED_INSNS (fndecl);
-+
-+ old_cfun = cfun;
-+ cfun = f;
-+ current_function_decl = fndecl;
-+
-+ set_new_last_label_num (f->inl_max_label_num);
-+
-+ /* We're not deferring this any longer. */
-+ DECL_DEFER_OUTPUT (fndecl) = 0;
-+
-+ /* If requested, suppress debugging information. */
-+ if (f->no_debugging_symbols)
-+ {
-+ write_symbols = NO_DEBUG;
-+ debug_hooks = &do_nothing_debug_hooks;
-+ }
-+
-+ /* Make sure warnings emitted by the optimizers (e.g. control reaches
-+ end of non-void function) is not wildly incorrect. */
-+ input_filename = DECL_SOURCE_FILE (fndecl);
-+ lineno = DECL_SOURCE_LINE (fndecl);
-+
-+ /* Compile this function all the way down to assembly code. As a
-+ side effect this destroys the saved RTL representation, but
-+ that's okay, because we don't need to inline this anymore. */
-+ rest_of_compilation (fndecl);
-+ DECL_INLINE (fndecl) = 0;
-+
-+ cfun = old_cfun;
-+ current_function_decl = old_cfun ? old_cfun->decl : 0;
-+ write_symbols = old_write_symbols;
-+ debug_hooks = old_debug_hooks;
-+}
-+
-+\f
-+/* Functions to keep track of the values hard regs had at the start of
-+ the function. */
-+
-+rtx
-+get_hard_reg_initial_reg (fun, reg)
-+ struct function *fun;
-+ rtx reg;
-+{
-+ struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
-+ int i;
-+
-+ if (ivs == 0)
-+ return NULL_RTX;
-+
-+ for (i = 0; i < ivs->num_entries; i++)
-+ if (rtx_equal_p (ivs->entries[i].pseudo, reg))
-+ return ivs->entries[i].hard_reg;
-+
-+ return NULL_RTX;
-+}
-+
-+rtx
-+has_func_hard_reg_initial_val (fun, reg)
-+ struct function *fun;
-+ rtx reg;
-+{
-+ struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
-+ int i;
-+
-+ if (ivs == 0)
-+ return NULL_RTX;
-+
-+ for (i = 0; i < ivs->num_entries; i++)
-+ if (rtx_equal_p (ivs->entries[i].hard_reg, reg))
-+ return ivs->entries[i].pseudo;
-+
-+ return NULL_RTX;
-+}
-+
-+rtx
-+get_func_hard_reg_initial_val (fun, reg)
-+ struct function *fun;
-+ rtx reg;
-+{
-+ struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
-+ rtx rv = has_func_hard_reg_initial_val (fun, reg);
-+
-+ if (rv)
-+ return rv;
-+
-+ if (ivs == 0)
-+ {
-+ fun->hard_reg_initial_vals = (void *) ggc_alloc (sizeof (initial_value_struct));
-+ ivs = fun->hard_reg_initial_vals;
-+ ivs->num_entries = 0;
-+ ivs->max_entries = 5;
-+ ivs->entries = (initial_value_pair *) ggc_alloc (5 * sizeof (initial_value_pair));
-+ }
-+
-+ if (ivs->num_entries >= ivs->max_entries)
-+ {
-+ ivs->max_entries += 5;
-+ ivs->entries =
-+ (initial_value_pair *) ggc_realloc (ivs->entries,
-+ ivs->max_entries
-+ * sizeof (initial_value_pair));
-+ }
-+
-+ ivs->entries[ivs->num_entries].hard_reg = reg;
-+ ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (GET_MODE (reg));
-+
-+ return ivs->entries[ivs->num_entries++].pseudo;
-+}
-+
-+rtx
-+get_hard_reg_initial_val (mode, regno)
-+ enum machine_mode mode;
-+ int regno;
-+{
-+ return get_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
-+}
-+
-+rtx
-+has_hard_reg_initial_val (mode, regno)
-+ enum machine_mode mode;
-+ int regno;
-+{
-+ return has_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
-+}
-+
-+static void
-+setup_initial_hard_reg_value_integration (inl_f, remap)
-+ struct function *inl_f;
-+ struct inline_remap *remap;
-+{
-+ struct initial_value_struct *ivs = inl_f->hard_reg_initial_vals;
-+ int i;
-+
-+ if (ivs == 0)
-+ return;
-+
-+ for (i = 0; i < ivs->num_entries; i ++)
-+ remap->reg_map[REGNO (ivs->entries[i].pseudo)]
-+ = get_func_hard_reg_initial_val (cfun, ivs->entries[i].hard_reg);
-+}
-+
-+
-+void
-+emit_initial_value_sets ()
-+{
-+ struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
-+ int i;
-+ rtx seq;
-+
-+ if (ivs == 0)
-+ return;
-+
-+ start_sequence ();
-+ for (i = 0; i < ivs->num_entries; i++)
-+ emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
-+ seq = get_insns ();
-+ end_sequence ();
-+
-+ emit_insn_after (seq, get_insns ());
-+}
-+
-+/* If the backend knows where to allocate pseudos for hard
-+ register initial values, register these allocations now. */
-+void
-+allocate_initial_values (reg_equiv_memory_loc)
-+ rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED;
-+{
-+#ifdef ALLOCATE_INITIAL_VALUE
-+ struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
-+ int i;
-+
-+ if (ivs == 0)
-+ return;
-+
-+ for (i = 0; i < ivs->num_entries; i++)
-+ {
-+ int regno = REGNO (ivs->entries[i].pseudo);
-+ rtx x = ALLOCATE_INITIAL_VALUE (ivs->entries[i].hard_reg);
-+
-+ if (x == NULL_RTX || REG_N_SETS (REGNO (ivs->entries[i].pseudo)) > 1)
-+ ; /* Do nothing. */
-+ else if (GET_CODE (x) == MEM)
-+ reg_equiv_memory_loc[regno] = x;
-+ else if (GET_CODE (x) == REG)
-+ {
-+ reg_renumber[regno] = REGNO (x);
-+ /* Poke the regno right into regno_reg_rtx
-+ so that even fixed regs are accepted. */
-+ REGNO (ivs->entries[i].pseudo) = REGNO (x);
-+ }
-+ else abort ();
-+ }
-+#endif
-+}
-+
-+#include "gt-integrate.h"
-diff -ruN gcc-3.3.1/gcc/libgcc-std.ver gcc-3.3.1.pp/gcc/libgcc-std.ver
---- gcc-3.3.1/gcc/libgcc-std.ver 2003-07-13 21:25:09.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/libgcc-std.ver 2003-09-05 11:58:59.000000000 +0000
-@@ -174,6 +174,10 @@
- _Unwind_SjLj_RaiseException
- _Unwind_SjLj_ForcedUnwind
- _Unwind_SjLj_Resume
-+
-+ # stack smash handler symbols
-+ __guard
-+ __stack_smash_handler
- }
-
- %inherit GCC_3.3 GCC_3.0
-diff -ruN gcc-3.3.1/gcc/libgcc2.c gcc-3.3.1.pp/gcc/libgcc2.c
---- gcc-3.3.1/gcc/libgcc2.c 2002-10-23 10:47:24.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/libgcc2.c 2003-09-05 11:58:59.000000000 +0000
-@@ -1993,3 +1993,102 @@
- #endif /* NEED_ATEXIT */
-
- #endif /* L_exit */
-+\f
-+#ifdef L_stack_smash_handler
-+#include <stdio.h>
-+#include <string.h>
-+#include <fcntl.h>
-+#include <unistd.h>
-+
-+#ifdef _POSIX_SOURCE
-+#include <signal.h>
-+#endif
-+
-+#if defined(HAVE_SYSLOG)
-+#include <sys/types.h>
-+#include <sys/socket.h>
-+#include <sys/un.h>
-+
-+#include <sys/syslog.h>
-+#ifndef _PATH_LOG
-+#define _PATH_LOG "/dev/log"
-+#endif
-+#endif
-+
-+long __guard[8] = {0,0,0,0,0,0,0,0};
-+static void __guard_setup (void) __attribute__ ((constructor)) ;
-+static void __guard_setup (void)
-+{
-+ int fd;
-+ if (__guard[0]!=0) return;
-+ fd = open ("/dev/urandom", 0);
-+ if (fd != -1) {
-+ ssize_t size = read (fd, (char*)&__guard, sizeof(__guard));
-+ close (fd) ;
-+ if (size == sizeof(__guard)) return;
-+ }
-+ /* If a random generator can't be used, the protector switches the guard
-+ to the "terminator canary" */
-+ ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
-+ ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
-+}
-+void __stack_smash_handler (char func[], int damaged ATTRIBUTE_UNUSED)
-+{
-+#if defined (__GNU_LIBRARY__)
-+ extern char * __progname;
-+#endif
-+ const char message[] = ": stack smashing attack in function ";
-+ int bufsz = 256, len;
-+ char buf[bufsz];
-+#if defined(HAVE_SYSLOG)
-+ int LogFile;
-+ struct sockaddr_un SyslogAddr; /* AF_UNIX address of local logger */
-+#endif
-+#ifdef _POSIX_SOURCE
-+ {
-+ sigset_t mask;
-+ sigfillset(&mask);
-+ sigdelset(&mask, SIGABRT); /* Block all signal handlers */
-+ sigprocmask(SIG_BLOCK, &mask, NULL); /* except SIGABRT */
-+ }
-+#endif
-+
-+ strcpy(buf, "<2>"); len=3; /* send LOG_CRIT */
-+#if defined (__GNU_LIBRARY__)
-+ strncat(buf, __progname, bufsz-len-1); len = strlen(buf);
-+#endif
-+ if (bufsz>len) {strncat(buf, message, bufsz-len-1); len = strlen(buf);}
-+ if (bufsz>len) {strncat(buf, func, bufsz-len-1); len = strlen(buf);}
-+
-+ /* print error message */
-+ write (STDERR_FILENO, buf+3, len-3);
-+#if defined(HAVE_SYSLOG)
-+ if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) != -1) {
-+
-+ /*
-+ * Send "found" message to the "/dev/log" path
-+ */
-+ SyslogAddr.sun_family = AF_UNIX;
-+ (void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
-+ sizeof(SyslogAddr.sun_path) - 1);
-+ SyslogAddr.sun_path[sizeof(SyslogAddr.sun_path) - 1] = '\0';
-+ sendto(LogFile, buf, len, 0, (struct sockaddr *)&SyslogAddr,
-+ sizeof(SyslogAddr));
-+ }
-+#endif
-+
-+#ifdef _POSIX_SOURCE
-+ { /* Make sure the default handler is associated with SIGABRT */
-+ struct sigaction sa;
-+
-+ memset(&sa, 0, sizeof(struct sigaction));
-+ sigfillset(&sa.sa_mask); /* Block all signals */
-+ sa.sa_flags = 0;
-+ sa.sa_handler = SIG_DFL;
-+ sigaction(SIGABRT, &sa, NULL);
-+ (void)kill(getpid(), SIGABRT);
-+ }
-+#endif
-+ _exit(127);
-+}
-+#endif
-diff -ruN gcc-3.3.1/gcc/loop.c gcc-3.3.1.pp/gcc/loop.c
---- gcc-3.3.1/gcc/loop.c 2003-07-11 06:47:05.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/loop.c 2003-09-05 11:58:59.000000000 +0000
-@@ -6516,6 +6516,14 @@
- if (GET_CODE (*mult_val) == USE)
- *mult_val = XEXP (*mult_val, 0);
-
-+#ifndef FRAME_GROWS_DOWNWARD
-+ if (flag_propolice_protection
-+ && GET_CODE (*add_val) == PLUS
-+ && (XEXP (*add_val, 0) == frame_pointer_rtx
-+ || XEXP (*add_val, 1) == frame_pointer_rtx))
-+ return 0;
-+#endif
-+
- if (is_addr)
- *pbenefit += address_cost (orig_x, addr_mode) - reg_address_cost;
- else
-diff -ruN gcc-3.3.1/gcc/optabs.c gcc-3.3.1.pp/gcc/optabs.c
---- gcc-3.3.1/gcc/optabs.c 2003-07-19 00:25:25.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/optabs.c 2003-09-05 11:58:59.000000000 +0000
-@@ -703,6 +703,26 @@
- if (target)
- target = protect_from_queue (target, 1);
-
-+ if (flag_propolice_protection
-+ && binoptab->code == PLUS
-+ && op0 == virtual_stack_vars_rtx
-+ && GET_CODE(op1) == CONST_INT)
-+ {
-+ int icode = (int) binoptab->handlers[(int) mode].insn_code;
-+ if (target)
-+ temp = target;
-+ else
-+ temp = gen_reg_rtx (mode);
-+
-+ if (! (*insn_data[icode].operand[0].predicate) (temp, mode)
-+ || GET_CODE (temp) != REG)
-+ temp = gen_reg_rtx (mode);
-+
-+ emit_insn (gen_rtx_SET (VOIDmode, temp,
-+ gen_rtx_PLUS (GET_MODE (op0), op0, op1)));
-+ return temp;
-+ }
-+
- if (flag_force_mem)
- {
- op0 = force_not_mem (op0);
-diff -ruN gcc-3.3.1/gcc/optabs.c.orig gcc-3.3.1.pp/gcc/optabs.c.orig
---- gcc-3.3.1/gcc/optabs.c.orig 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/optabs.c.orig 2003-07-19 00:25:25.000000000 +0000
-@@ -0,0 +1,5511 @@
-+/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
-+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-+
-+This file is part of GCC.
-+
-+GCC is free software; you can redistribute it and/or modify it under
-+the terms of the GNU General Public License as published by the Free
-+Software Foundation; either version 2, or (at your option) any later
-+version.
-+
-+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-+WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+for more details.
-+
-+You should have received a copy of the GNU General Public License
-+along with GCC; see the file COPYING. If not, write to the Free
-+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-+02111-1307, USA. */
-+
-+
-+#include "config.h"
-+#include "system.h"
-+#include "toplev.h"
-+
-+/* Include insn-config.h before expr.h so that HAVE_conditional_move
-+ is properly defined. */
-+#include "insn-config.h"
-+#include "rtl.h"
-+#include "tree.h"
-+#include "tm_p.h"
-+#include "flags.h"
-+#include "function.h"
-+#include "except.h"
-+#include "expr.h"
-+#include "optabs.h"
-+#include "libfuncs.h"
-+#include "recog.h"
-+#include "reload.h"
-+#include "ggc.h"
-+#include "real.h"
-+#include "basic-block.h"
-+
-+/* Each optab contains info on how this target machine
-+ can perform a particular operation
-+ for all sizes and kinds of operands.
-+
-+ The operation to be performed is often specified
-+ by passing one of these optabs as an argument.
-+
-+ See expr.h for documentation of these optabs. */
-+
-+optab optab_table[OTI_MAX];
-+
-+rtx libfunc_table[LTI_MAX];
-+
-+/* Tables of patterns for extending one integer mode to another. */
-+enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
-+
-+/* Tables of patterns for converting between fixed and floating point. */
-+enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
-+enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
-+enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
-+
-+/* Contains the optab used for each rtx code. */
-+optab code_to_optab[NUM_RTX_CODE + 1];
-+
-+/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
-+ gives the gen_function to make a branch to test that condition. */
-+
-+rtxfun bcc_gen_fctn[NUM_RTX_CODE];
-+
-+/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
-+ gives the insn code to make a store-condition insn
-+ to test that condition. */
-+
-+enum insn_code setcc_gen_code[NUM_RTX_CODE];
-+
-+#ifdef HAVE_conditional_move
-+/* Indexed by the machine mode, gives the insn code to make a conditional
-+ move insn. This is not indexed by the rtx-code like bcc_gen_fctn and
-+ setcc_gen_code to cut down on the number of named patterns. Consider a day
-+ when a lot more rtx codes are conditional (eg: for the ARM). */
-+
-+enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
-+#endif
-+
-+/* The insn generating function can not take an rtx_code argument.
-+ TRAP_RTX is used as an rtx argument. Its code is replaced with
-+ the code to be used in the trap insn and all other fields are ignored. */
-+static GTY(()) rtx trap_rtx;
-+
-+static int add_equal_note PARAMS ((rtx, rtx, enum rtx_code, rtx, rtx));
-+static rtx widen_operand PARAMS ((rtx, enum machine_mode,
-+ enum machine_mode, int, int));
-+static int expand_cmplxdiv_straight PARAMS ((rtx, rtx, rtx, rtx,
-+ rtx, rtx, enum machine_mode,
-+ int, enum optab_methods,
-+ enum mode_class, optab));
-+static int expand_cmplxdiv_wide PARAMS ((rtx, rtx, rtx, rtx,
-+ rtx, rtx, enum machine_mode,
-+ int, enum optab_methods,
-+ enum mode_class, optab));
-+static void prepare_cmp_insn PARAMS ((rtx *, rtx *, enum rtx_code *, rtx,
-+ enum machine_mode *, int *,
-+ enum can_compare_purpose));
-+static enum insn_code can_fix_p PARAMS ((enum machine_mode, enum machine_mode,
-+ int, int *));
-+static enum insn_code can_float_p PARAMS ((enum machine_mode,
-+ enum machine_mode,
-+ int));
-+static rtx ftruncify PARAMS ((rtx));
-+static optab new_optab PARAMS ((void));
-+static inline optab init_optab PARAMS ((enum rtx_code));
-+static inline optab init_optabv PARAMS ((enum rtx_code));
-+static void init_libfuncs PARAMS ((optab, int, int, const char *, int));
-+static void init_integral_libfuncs PARAMS ((optab, const char *, int));
-+static void init_floating_libfuncs PARAMS ((optab, const char *, int));
-+static void emit_cmp_and_jump_insn_1 PARAMS ((rtx, rtx, enum machine_mode,
-+ enum rtx_code, int, rtx));
-+static void prepare_float_lib_cmp PARAMS ((rtx *, rtx *, enum rtx_code *,
-+ enum machine_mode *, int *));
-+static rtx expand_vector_binop PARAMS ((enum machine_mode, optab,
-+ rtx, rtx, rtx, int,
-+ enum optab_methods));
-+static rtx expand_vector_unop PARAMS ((enum machine_mode, optab, rtx, rtx,
-+ int));
-+
-+#ifndef HAVE_conditional_trap
-+#define HAVE_conditional_trap 0
-+#define gen_conditional_trap(a,b) (abort (), NULL_RTX)
-+#endif
-+\f
-+/* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
-+ the result of operation CODE applied to OP0 (and OP1 if it is a binary
-+ operation).
-+
-+ If the last insn does not set TARGET, don't do anything, but return 1.
-+
-+ If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
-+ don't add the REG_EQUAL note but return 0. Our caller can then try
-+ again, ensuring that TARGET is not one of the operands. */
-+
-+static int
-+add_equal_note (insns, target, code, op0, op1)
-+ rtx insns;
-+ rtx target;
-+ enum rtx_code code;
-+ rtx op0, op1;
-+{
-+ rtx last_insn, insn, set;
-+ rtx note;
-+
-+ if (! insns
-+ || ! INSN_P (insns)
-+ || NEXT_INSN (insns) == NULL_RTX)
-+ abort ();
-+
-+ if (GET_RTX_CLASS (code) != '1' && GET_RTX_CLASS (code) != '2'
-+ && GET_RTX_CLASS (code) != 'c' && GET_RTX_CLASS (code) != '<')
-+ return 1;
-+
-+ if (GET_CODE (target) == ZERO_EXTRACT)
-+ return 1;
-+
-+ for (last_insn = insns;
-+ NEXT_INSN (last_insn) != NULL_RTX;
-+ last_insn = NEXT_INSN (last_insn))
-+ ;
-+
-+ set = single_set (last_insn);
-+ if (set == NULL_RTX)
-+ return 1;
-+
-+ if (! rtx_equal_p (SET_DEST (set), target)
-+ /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside the
-+ SUBREG. */
-+ && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
-+ || ! rtx_equal_p (SUBREG_REG (XEXP (SET_DEST (set), 0)),
-+ target)))
-+ return 1;
-+
-+ /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
-+ besides the last insn. */
-+ if (reg_overlap_mentioned_p (target, op0)
-+ || (op1 && reg_overlap_mentioned_p (target, op1)))
-+ {
-+ insn = PREV_INSN (last_insn);
-+ while (insn != NULL_RTX)
-+ {
-+ if (reg_set_p (target, insn))
-+ return 0;
-+
-+ insn = PREV_INSN (insn);
-+ }
-+ }
-+
-+ if (GET_RTX_CLASS (code) == '1')
-+ note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
-+ else
-+ note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
-+
-+ set_unique_reg_note (last_insn, REG_EQUAL, note);
-+
-+ return 1;
-+}
-+\f
-+/* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
-+ says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
-+ not actually do a sign-extend or zero-extend, but can leave the
-+ higher-order bits of the result rtx undefined, for example, in the case
-+ of logical operations, but not right shifts. */
-+
-+static rtx
-+widen_operand (op, mode, oldmode, unsignedp, no_extend)
-+ rtx op;
-+ enum machine_mode mode, oldmode;
-+ int unsignedp;
-+ int no_extend;
-+{
-+ rtx result;
-+
-+ /* If we don't have to extend and this is a constant, return it. */
-+ if (no_extend && GET_MODE (op) == VOIDmode)
-+ return op;
-+
-+ /* If we must extend do so. If OP is a SUBREG for a promoted object, also
-+ extend since it will be more efficient to do so unless the signedness of
-+ a promoted object differs from our extension. */
-+ if (! no_extend
-+ || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
-+ && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
-+ return convert_modes (mode, oldmode, op, unsignedp);
-+
-+ /* If MODE is no wider than a single word, we return a paradoxical
-+ SUBREG. */
-+ if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
-+ return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
-+
-+ /* Otherwise, get an object of MODE, clobber it, and set the low-order
-+ part to OP. */
-+
-+ result = gen_reg_rtx (mode);
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
-+ emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
-+ return result;
-+}
-+\f
-+/* Generate code to perform a straightforward complex divide. */
-+
-+static int
-+expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
-+ unsignedp, methods, class, binoptab)
-+ rtx real0, real1, imag0, imag1, realr, imagr;
-+ enum machine_mode submode;
-+ int unsignedp;
-+ enum optab_methods methods;
-+ enum mode_class class;
-+ optab binoptab;
-+{
-+ rtx divisor;
-+ rtx real_t, imag_t;
-+ rtx temp1, temp2;
-+ rtx res;
-+ optab this_add_optab = add_optab;
-+ optab this_sub_optab = sub_optab;
-+ optab this_neg_optab = neg_optab;
-+ optab this_mul_optab = smul_optab;
-+
-+ if (binoptab == sdivv_optab)
-+ {
-+ this_add_optab = addv_optab;
-+ this_sub_optab = subv_optab;
-+ this_neg_optab = negv_optab;
-+ this_mul_optab = smulv_optab;
-+ }
-+
-+ /* Don't fetch these from memory more than once. */
-+ real0 = force_reg (submode, real0);
-+ real1 = force_reg (submode, real1);
-+
-+ if (imag0 != 0)
-+ imag0 = force_reg (submode, imag0);
-+
-+ imag1 = force_reg (submode, imag1);
-+
-+ /* Divisor: c*c + d*d. */
-+ temp1 = expand_binop (submode, this_mul_optab, real1, real1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ temp2 = expand_binop (submode, this_mul_optab, imag1, imag1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0 || temp2 == 0)
-+ return 0;
-+
-+ divisor = expand_binop (submode, this_add_optab, temp1, temp2,
-+ NULL_RTX, unsignedp, methods);
-+ if (divisor == 0)
-+ return 0;
-+
-+ if (imag0 == 0)
-+ {
-+ /* Mathematically, ((a)(c-id))/divisor. */
-+ /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
-+
-+ /* Calculate the dividend. */
-+ real_t = expand_binop (submode, this_mul_optab, real0, real1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ imag_t = expand_binop (submode, this_mul_optab, real0, imag1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (real_t == 0 || imag_t == 0)
-+ return 0;
-+
-+ imag_t = expand_unop (submode, this_neg_optab, imag_t,
-+ NULL_RTX, unsignedp);
-+ }
-+ else
-+ {
-+ /* Mathematically, ((a+ib)(c-id))/divider. */
-+ /* Calculate the dividend. */
-+ temp1 = expand_binop (submode, this_mul_optab, real0, real1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ temp2 = expand_binop (submode, this_mul_optab, imag0, imag1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0 || temp2 == 0)
-+ return 0;
-+
-+ real_t = expand_binop (submode, this_add_optab, temp1, temp2,
-+ NULL_RTX, unsignedp, methods);
-+
-+ temp1 = expand_binop (submode, this_mul_optab, imag0, real1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ temp2 = expand_binop (submode, this_mul_optab, real0, imag1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0 || temp2 == 0)
-+ return 0;
-+
-+ imag_t = expand_binop (submode, this_sub_optab, temp1, temp2,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (real_t == 0 || imag_t == 0)
-+ return 0;
-+ }
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ res = expand_binop (submode, binoptab, real_t, divisor,
-+ realr, unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ real_t, divisor, realr, unsignedp);
-+
-+ if (res == 0)
-+ return 0;
-+
-+ if (res != realr)
-+ emit_move_insn (realr, res);
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ res = expand_binop (submode, binoptab, imag_t, divisor,
-+ imagr, unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ imag_t, divisor, imagr, unsignedp);
-+
-+ if (res == 0)
-+ return 0;
-+
-+ if (res != imagr)
-+ emit_move_insn (imagr, res);
-+
-+ return 1;
-+}
-+\f
-+/* Generate code to perform a wide-input-range-acceptable complex divide. */
-+
-+static int
-+expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
-+ unsignedp, methods, class, binoptab)
-+ rtx real0, real1, imag0, imag1, realr, imagr;
-+ enum machine_mode submode;
-+ int unsignedp;
-+ enum optab_methods methods;
-+ enum mode_class class;
-+ optab binoptab;
-+{
-+ rtx ratio, divisor;
-+ rtx real_t, imag_t;
-+ rtx temp1, temp2, lab1, lab2;
-+ enum machine_mode mode;
-+ rtx res;
-+ optab this_add_optab = add_optab;
-+ optab this_sub_optab = sub_optab;
-+ optab this_neg_optab = neg_optab;
-+ optab this_mul_optab = smul_optab;
-+
-+ if (binoptab == sdivv_optab)
-+ {
-+ this_add_optab = addv_optab;
-+ this_sub_optab = subv_optab;
-+ this_neg_optab = negv_optab;
-+ this_mul_optab = smulv_optab;
-+ }
-+
-+ /* Don't fetch these from memory more than once. */
-+ real0 = force_reg (submode, real0);
-+ real1 = force_reg (submode, real1);
-+
-+ if (imag0 != 0)
-+ imag0 = force_reg (submode, imag0);
-+
-+ imag1 = force_reg (submode, imag1);
-+
-+ /* XXX What's an "unsigned" complex number? */
-+ if (unsignedp)
-+ {
-+ temp1 = real1;
-+ temp2 = imag1;
-+ }
-+ else
-+ {
-+ temp1 = expand_abs (submode, real1, NULL_RTX, unsignedp, 1);
-+ temp2 = expand_abs (submode, imag1, NULL_RTX, unsignedp, 1);
-+ }
-+
-+ if (temp1 == 0 || temp2 == 0)
-+ return 0;
-+
-+ mode = GET_MODE (temp1);
-+ lab1 = gen_label_rtx ();
-+ emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
-+ mode, unsignedp, lab1);
-+
-+ /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ ratio = expand_binop (submode, binoptab, imag1, real1,
-+ NULL_RTX, unsignedp, methods);
-+ else
-+ ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ imag1, real1, NULL_RTX, unsignedp);
-+
-+ if (ratio == 0)
-+ return 0;
-+
-+ /* Calculate divisor. */
-+
-+ temp1 = expand_binop (submode, this_mul_optab, imag1, ratio,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0)
-+ return 0;
-+
-+ divisor = expand_binop (submode, this_add_optab, temp1, real1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (divisor == 0)
-+ return 0;
-+
-+ /* Calculate dividend. */
-+
-+ if (imag0 == 0)
-+ {
-+ real_t = real0;
-+
-+ /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
-+
-+ imag_t = expand_binop (submode, this_mul_optab, real0, ratio,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (imag_t == 0)
-+ return 0;
-+
-+ imag_t = expand_unop (submode, this_neg_optab, imag_t,
-+ NULL_RTX, unsignedp);
-+
-+ if (real_t == 0 || imag_t == 0)
-+ return 0;
-+ }
-+ else
-+ {
-+ /* Compute (a+ib)/(c+id) as
-+ (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
-+
-+ temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0)
-+ return 0;
-+
-+ real_t = expand_binop (submode, this_add_optab, temp1, real0,
-+ NULL_RTX, unsignedp, methods);
-+
-+ temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0)
-+ return 0;
-+
-+ imag_t = expand_binop (submode, this_sub_optab, imag0, temp1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (real_t == 0 || imag_t == 0)
-+ return 0;
-+ }
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ res = expand_binop (submode, binoptab, real_t, divisor,
-+ realr, unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ real_t, divisor, realr, unsignedp);
-+
-+ if (res == 0)
-+ return 0;
-+
-+ if (res != realr)
-+ emit_move_insn (realr, res);
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ res = expand_binop (submode, binoptab, imag_t, divisor,
-+ imagr, unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ imag_t, divisor, imagr, unsignedp);
-+
-+ if (res == 0)
-+ return 0;
-+
-+ if (res != imagr)
-+ emit_move_insn (imagr, res);
-+
-+ lab2 = gen_label_rtx ();
-+ emit_jump_insn (gen_jump (lab2));
-+ emit_barrier ();
-+
-+ emit_label (lab1);
-+
-+ /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ ratio = expand_binop (submode, binoptab, real1, imag1,
-+ NULL_RTX, unsignedp, methods);
-+ else
-+ ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ real1, imag1, NULL_RTX, unsignedp);
-+
-+ if (ratio == 0)
-+ return 0;
-+
-+ /* Calculate divisor. */
-+
-+ temp1 = expand_binop (submode, this_mul_optab, real1, ratio,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0)
-+ return 0;
-+
-+ divisor = expand_binop (submode, this_add_optab, temp1, imag1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (divisor == 0)
-+ return 0;
-+
-+ /* Calculate dividend. */
-+
-+ if (imag0 == 0)
-+ {
-+ /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
-+
-+ real_t = expand_binop (submode, this_mul_optab, real0, ratio,
-+ NULL_RTX, unsignedp, methods);
-+
-+ imag_t = expand_unop (submode, this_neg_optab, real0,
-+ NULL_RTX, unsignedp);
-+
-+ if (real_t == 0 || imag_t == 0)
-+ return 0;
-+ }
-+ else
-+ {
-+ /* Compute (a+ib)/(c+id) as
-+ (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
-+
-+ temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0)
-+ return 0;
-+
-+ real_t = expand_binop (submode, this_add_optab, temp1, imag0,
-+ NULL_RTX, unsignedp, methods);
-+
-+ temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0)
-+ return 0;
-+
-+ imag_t = expand_binop (submode, this_sub_optab, temp1, real0,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (real_t == 0 || imag_t == 0)
-+ return 0;
-+ }
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ res = expand_binop (submode, binoptab, real_t, divisor,
-+ realr, unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ real_t, divisor, realr, unsignedp);
-+
-+ if (res == 0)
-+ return 0;
-+
-+ if (res != realr)
-+ emit_move_insn (realr, res);
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ res = expand_binop (submode, binoptab, imag_t, divisor,
-+ imagr, unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ imag_t, divisor, imagr, unsignedp);
-+
-+ if (res == 0)
-+ return 0;
-+
-+ if (res != imagr)
-+ emit_move_insn (imagr, res);
-+
-+ emit_label (lab2);
-+
-+ return 1;
-+}
-+\f
-+/* Wrapper around expand_binop which takes an rtx code to specify
-+ the operation to perform, not an optab pointer. All other
-+ arguments are the same. */
-+rtx
-+expand_simple_binop (mode, code, op0, op1, target, unsignedp, methods)
-+ enum machine_mode mode;
-+ enum rtx_code code;
-+ rtx op0, op1;
-+ rtx target;
-+ int unsignedp;
-+ enum optab_methods methods;
-+{
-+ optab binop = code_to_optab[(int) code];
-+ if (binop == 0)
-+ abort ();
-+
-+ return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
-+}
-+
-+/* Generate code to perform an operation specified by BINOPTAB
-+ on operands OP0 and OP1, with result having machine-mode MODE.
-+
-+ UNSIGNEDP is for the case where we have to widen the operands
-+ to perform the operation. It says to use zero-extension.
-+
-+ If TARGET is nonzero, the value
-+ is generated there, if it is convenient to do so.
-+ In all cases an rtx is returned for the locus of the value;
-+ this may or may not be TARGET. */
-+
-+rtx
-+expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
-+ enum machine_mode mode;
-+ optab binoptab;
-+ rtx op0, op1;
-+ rtx target;
-+ int unsignedp;
-+ enum optab_methods methods;
-+{
-+ enum optab_methods next_methods
-+ = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
-+ ? OPTAB_WIDEN : methods);
-+ enum mode_class class;
-+ enum machine_mode wider_mode;
-+ rtx temp;
-+ int commutative_op = 0;
-+ int shift_op = (binoptab->code == ASHIFT
-+ || binoptab->code == ASHIFTRT
-+ || binoptab->code == LSHIFTRT
-+ || binoptab->code == ROTATE
-+ || binoptab->code == ROTATERT);
-+ rtx entry_last = get_last_insn ();
-+ rtx last;
-+
-+ class = GET_MODE_CLASS (mode);
-+
-+ op0 = protect_from_queue (op0, 0);
-+ op1 = protect_from_queue (op1, 0);
-+ if (target)
-+ target = protect_from_queue (target, 1);
-+
-+ if (flag_force_mem)
-+ {
-+ op0 = force_not_mem (op0);
-+ op1 = force_not_mem (op1);
-+ }
-+
-+ /* If subtracting an integer constant, convert this into an addition of
-+ the negated constant. */
-+
-+ if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
-+ {
-+ op1 = negate_rtx (mode, op1);
-+ binoptab = add_optab;
-+ }
-+
-+ /* If we are inside an appropriately-short loop and one operand is an
-+ expensive constant, force it into a register. */
-+ if (CONSTANT_P (op0) && preserve_subexpressions_p ()
-+ && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
-+ op0 = force_reg (mode, op0);
-+
-+ if (CONSTANT_P (op1) && preserve_subexpressions_p ()
-+ && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
-+ op1 = force_reg (mode, op1);
-+
-+ /* Record where to delete back to if we backtrack. */
-+ last = get_last_insn ();
-+
-+ /* If operation is commutative,
-+ try to make the first operand a register.
-+ Even better, try to make it the same as the target.
-+ Also try to make the last operand a constant. */
-+ if (GET_RTX_CLASS (binoptab->code) == 'c'
-+ || binoptab == smul_widen_optab
-+ || binoptab == umul_widen_optab
-+ || binoptab == smul_highpart_optab
-+ || binoptab == umul_highpart_optab)
-+ {
-+ commutative_op = 1;
-+
-+ if (((target == 0 || GET_CODE (target) == REG)
-+ ? ((GET_CODE (op1) == REG
-+ && GET_CODE (op0) != REG)
-+ || target == op1)
-+ : rtx_equal_p (op1, target))
-+ || GET_CODE (op0) == CONST_INT)
-+ {
-+ temp = op1;
-+ op1 = op0;
-+ op0 = temp;
-+ }
-+ }
-+
-+ /* If we can do it with a three-operand insn, do so. */
-+
-+ if (methods != OPTAB_MUST_WIDEN
-+ && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ int icode = (int) binoptab->handlers[(int) mode].insn_code;
-+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
-+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
-+ rtx pat;
-+ rtx xop0 = op0, xop1 = op1;
-+
-+ if (target)
-+ temp = target;
-+ else
-+ temp = gen_reg_rtx (mode);
-+
-+ /* If it is a commutative operator and the modes would match
-+ if we would swap the operands, we can save the conversions. */
-+ if (commutative_op)
-+ {
-+ if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
-+ && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
-+ {
-+ rtx tmp;
-+
-+ tmp = op0; op0 = op1; op1 = tmp;
-+ tmp = xop0; xop0 = xop1; xop1 = tmp;
-+ }
-+ }
-+
-+ /* In case the insn wants input operands in modes different from
-+ those of the actual operands, convert the operands. It would
-+ seem that we don't need to convert CONST_INTs, but we do, so
-+ that they're properly zero-extended, sign-extended or truncated
-+ for their mode. */
-+
-+ if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
-+ xop0 = convert_modes (mode0,
-+ GET_MODE (op0) != VOIDmode
-+ ? GET_MODE (op0)
-+ : mode,
-+ xop0, unsignedp);
-+
-+ if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
-+ xop1 = convert_modes (mode1,
-+ GET_MODE (op1) != VOIDmode
-+ ? GET_MODE (op1)
-+ : mode,
-+ xop1, unsignedp);
-+
-+ /* Now, if insn's predicates don't allow our operands, put them into
-+ pseudo regs. */
-+
-+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0)
-+ && mode0 != VOIDmode)
-+ xop0 = copy_to_mode_reg (mode0, xop0);
-+
-+ if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1)
-+ && mode1 != VOIDmode)
-+ xop1 = copy_to_mode_reg (mode1, xop1);
-+
-+ if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
-+ temp = gen_reg_rtx (mode);
-+
-+ pat = GEN_FCN (icode) (temp, xop0, xop1);
-+ if (pat)
-+ {
-+ /* If PAT is composed of more than one insn, try to add an appropriate
-+ REG_EQUAL note to it. If we can't because TEMP conflicts with an
-+ operand, call ourselves again, this time without a target. */
-+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
-+ && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
-+ {
-+ delete_insns_since (last);
-+ return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
-+ unsignedp, methods);
-+ }
-+
-+ emit_insn (pat);
-+ return temp;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+
-+ /* If this is a multiply, see if we can do a widening operation that
-+ takes operands of this mode and makes a wider mode. */
-+
-+ if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
-+ && (((unsignedp ? umul_widen_optab : smul_widen_optab)
-+ ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
-+ != CODE_FOR_nothing))
-+ {
-+ temp = expand_binop (GET_MODE_WIDER_MODE (mode),
-+ unsignedp ? umul_widen_optab : smul_widen_optab,
-+ op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
-+
-+ if (temp != 0)
-+ {
-+ if (GET_MODE_CLASS (mode) == MODE_INT)
-+ return gen_lowpart (mode, temp);
-+ else
-+ return convert_to_mode (mode, temp, unsignedp);
-+ }
-+ }
-+
-+ /* Look for a wider mode of the same class for which we think we
-+ can open-code the operation. Check for a widening multiply at the
-+ wider mode as well. */
-+
-+ if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
-+ && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
-+ for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode))
-+ {
-+ if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
-+ || (binoptab == smul_optab
-+ && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
-+ && (((unsignedp ? umul_widen_optab : smul_widen_optab)
-+ ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
-+ != CODE_FOR_nothing)))
-+ {
-+ rtx xop0 = op0, xop1 = op1;
-+ int no_extend = 0;
-+
-+ /* For certain integer operations, we need not actually extend
-+ the narrow operands, as long as we will truncate
-+ the results to the same narrowness. */
-+
-+ if ((binoptab == ior_optab || binoptab == and_optab
-+ || binoptab == xor_optab
-+ || binoptab == add_optab || binoptab == sub_optab
-+ || binoptab == smul_optab || binoptab == ashl_optab)
-+ && class == MODE_INT)
-+ no_extend = 1;
-+
-+ xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
-+
-+ /* The second operand of a shift must always be extended. */
-+ xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
-+ no_extend && binoptab != ashl_optab);
-+
-+ temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
-+ unsignedp, OPTAB_DIRECT);
-+ if (temp)
-+ {
-+ if (class != MODE_INT)
-+ {
-+ if (target == 0)
-+ target = gen_reg_rtx (mode);
-+ convert_move (target, temp, 0);
-+ return target;
-+ }
-+ else
-+ return gen_lowpart (mode, temp);
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+
-+ /* These can be done a word at a time. */
-+ if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
-+ && class == MODE_INT
-+ && GET_MODE_SIZE (mode) > UNITS_PER_WORD
-+ && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
-+ {
-+ int i;
-+ rtx insns;
-+ rtx equiv_value;
-+
-+ /* If TARGET is the same as one of the operands, the REG_EQUAL note
-+ won't be accurate, so use a new target. */
-+ if (target == 0 || target == op0 || target == op1)
-+ target = gen_reg_rtx (mode);
-+
-+ start_sequence ();
-+
-+ /* Do the actual arithmetic. */
-+ for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
-+ {
-+ rtx target_piece = operand_subword (target, i, 1, mode);
-+ rtx x = expand_binop (word_mode, binoptab,
-+ operand_subword_force (op0, i, mode),
-+ operand_subword_force (op1, i, mode),
-+ target_piece, unsignedp, next_methods);
-+
-+ if (x == 0)
-+ break;
-+
-+ if (target_piece != x)
-+ emit_move_insn (target_piece, x);
-+ }
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
-+ {
-+ if (binoptab->code != UNKNOWN)
-+ equiv_value
-+ = gen_rtx_fmt_ee (binoptab->code, mode,
-+ copy_rtx (op0), copy_rtx (op1));
-+ else
-+ equiv_value = 0;
-+
-+ emit_no_conflict_block (insns, target, op0, op1, equiv_value);
-+ return target;
-+ }
-+ }
-+
-+ /* Synthesize double word shifts from single word shifts. */
-+ if ((binoptab == lshr_optab || binoptab == ashl_optab
-+ || binoptab == ashr_optab)
-+ && class == MODE_INT
-+ && GET_CODE (op1) == CONST_INT
-+ && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
-+ && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
-+ && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
-+ && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
-+ {
-+ rtx insns, inter, equiv_value;
-+ rtx into_target, outof_target;
-+ rtx into_input, outof_input;
-+ int shift_count, left_shift, outof_word;
-+
-+ /* If TARGET is the same as one of the operands, the REG_EQUAL note
-+ won't be accurate, so use a new target. */
-+ if (target == 0 || target == op0 || target == op1)
-+ target = gen_reg_rtx (mode);
-+
-+ start_sequence ();
-+
-+ shift_count = INTVAL (op1);
-+
-+ /* OUTOF_* is the word we are shifting bits away from, and
-+ INTO_* is the word that we are shifting bits towards, thus
-+ they differ depending on the direction of the shift and
-+ WORDS_BIG_ENDIAN. */
-+
-+ left_shift = binoptab == ashl_optab;
-+ outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
-+
-+ outof_target = operand_subword (target, outof_word, 1, mode);
-+ into_target = operand_subword (target, 1 - outof_word, 1, mode);
-+
-+ outof_input = operand_subword_force (op0, outof_word, mode);
-+ into_input = operand_subword_force (op0, 1 - outof_word, mode);
-+
-+ if (shift_count >= BITS_PER_WORD)
-+ {
-+ inter = expand_binop (word_mode, binoptab,
-+ outof_input,
-+ GEN_INT (shift_count - BITS_PER_WORD),
-+ into_target, unsignedp, next_methods);
-+
-+ if (inter != 0 && inter != into_target)
-+ emit_move_insn (into_target, inter);
-+
-+ /* For a signed right shift, we must fill the word we are shifting
-+ out of with copies of the sign bit. Otherwise it is zeroed. */
-+ if (inter != 0 && binoptab != ashr_optab)
-+ inter = CONST0_RTX (word_mode);
-+ else if (inter != 0)
-+ inter = expand_binop (word_mode, binoptab,
-+ outof_input,
-+ GEN_INT (BITS_PER_WORD - 1),
-+ outof_target, unsignedp, next_methods);
-+
-+ if (inter != 0 && inter != outof_target)
-+ emit_move_insn (outof_target, inter);
-+ }
-+ else
-+ {
-+ rtx carries;
-+ optab reverse_unsigned_shift, unsigned_shift;
-+
-+ /* For a shift of less then BITS_PER_WORD, to compute the carry,
-+ we must do a logical shift in the opposite direction of the
-+ desired shift. */
-+
-+ reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab);
-+
-+ /* For a shift of less than BITS_PER_WORD, to compute the word
-+ shifted towards, we need to unsigned shift the orig value of
-+ that word. */
-+
-+ unsigned_shift = (left_shift ? ashl_optab : lshr_optab);
-+
-+ carries = expand_binop (word_mode, reverse_unsigned_shift,
-+ outof_input,
-+ GEN_INT (BITS_PER_WORD - shift_count),
-+ 0, unsignedp, next_methods);
-+
-+ if (carries == 0)
-+ inter = 0;
-+ else
-+ inter = expand_binop (word_mode, unsigned_shift, into_input,
-+ op1, 0, unsignedp, next_methods);
-+
-+ if (inter != 0)
-+ inter = expand_binop (word_mode, ior_optab, carries, inter,
-+ into_target, unsignedp, next_methods);
-+
-+ if (inter != 0 && inter != into_target)
-+ emit_move_insn (into_target, inter);
-+
-+ if (inter != 0)
-+ inter = expand_binop (word_mode, binoptab, outof_input,
-+ op1, outof_target, unsignedp, next_methods);
-+
-+ if (inter != 0 && inter != outof_target)
-+ emit_move_insn (outof_target, inter);
-+ }
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ if (inter != 0)
-+ {
-+ if (binoptab->code != UNKNOWN)
-+ equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
-+ else
-+ equiv_value = 0;
-+
-+ emit_no_conflict_block (insns, target, op0, op1, equiv_value);
-+ return target;
-+ }
-+ }
-+
-+ /* Synthesize double word rotates from single word shifts. */
-+ if ((binoptab == rotl_optab || binoptab == rotr_optab)
-+ && class == MODE_INT
-+ && GET_CODE (op1) == CONST_INT
-+ && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
-+ && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
-+ && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
-+ {
-+ rtx insns, equiv_value;
-+ rtx into_target, outof_target;
-+ rtx into_input, outof_input;
-+ rtx inter;
-+ int shift_count, left_shift, outof_word;
-+
-+ /* If TARGET is the same as one of the operands, the REG_EQUAL note
-+ won't be accurate, so use a new target. */
-+ if (target == 0 || target == op0 || target == op1)
-+ target = gen_reg_rtx (mode);
-+
-+ start_sequence ();
-+
-+ shift_count = INTVAL (op1);
-+
-+ /* OUTOF_* is the word we are shifting bits away from, and
-+ INTO_* is the word that we are shifting bits towards, thus
-+ they differ depending on the direction of the shift and
-+ WORDS_BIG_ENDIAN. */
-+
-+ left_shift = (binoptab == rotl_optab);
-+ outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
-+
-+ outof_target = operand_subword (target, outof_word, 1, mode);
-+ into_target = operand_subword (target, 1 - outof_word, 1, mode);
-+
-+ outof_input = operand_subword_force (op0, outof_word, mode);
-+ into_input = operand_subword_force (op0, 1 - outof_word, mode);
-+
-+ if (shift_count == BITS_PER_WORD)
-+ {
-+ /* This is just a word swap. */
-+ emit_move_insn (outof_target, into_input);
-+ emit_move_insn (into_target, outof_input);
-+ inter = const0_rtx;
-+ }
-+ else
-+ {
-+ rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
-+ rtx first_shift_count, second_shift_count;
-+ optab reverse_unsigned_shift, unsigned_shift;
-+
-+ reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
-+ ? lshr_optab : ashl_optab);
-+
-+ unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
-+ ? ashl_optab : lshr_optab);
-+
-+ if (shift_count > BITS_PER_WORD)
-+ {
-+ first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
-+ second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
-+ }
-+ else
-+ {
-+ first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
-+ second_shift_count = GEN_INT (shift_count);
-+ }
-+
-+ into_temp1 = expand_binop (word_mode, unsigned_shift,
-+ outof_input, first_shift_count,
-+ NULL_RTX, unsignedp, next_methods);
-+ into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
-+ into_input, second_shift_count,
-+ NULL_RTX, unsignedp, next_methods);
-+
-+ if (into_temp1 != 0 && into_temp2 != 0)
-+ inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
-+ into_target, unsignedp, next_methods);
-+ else
-+ inter = 0;
-+
-+ if (inter != 0 && inter != into_target)
-+ emit_move_insn (into_target, inter);
-+
-+ outof_temp1 = expand_binop (word_mode, unsigned_shift,
-+ into_input, first_shift_count,
-+ NULL_RTX, unsignedp, next_methods);
-+ outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
-+ outof_input, second_shift_count,
-+ NULL_RTX, unsignedp, next_methods);
-+
-+ if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
-+ inter = expand_binop (word_mode, ior_optab,
-+ outof_temp1, outof_temp2,
-+ outof_target, unsignedp, next_methods);
-+
-+ if (inter != 0 && inter != outof_target)
-+ emit_move_insn (outof_target, inter);
-+ }
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ if (inter != 0)
-+ {
-+ if (binoptab->code != UNKNOWN)
-+ equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
-+ else
-+ equiv_value = 0;
-+
-+ /* We can't make this a no conflict block if this is a word swap,
-+ because the word swap case fails if the input and output values
-+ are in the same register. */
-+ if (shift_count != BITS_PER_WORD)
-+ emit_no_conflict_block (insns, target, op0, op1, equiv_value);
-+ else
-+ emit_insn (insns);
-+
-+
-+ return target;
-+ }
-+ }
-+
-+ /* These can be done a word at a time by propagating carries. */
-+ if ((binoptab == add_optab || binoptab == sub_optab)
-+ && class == MODE_INT
-+ && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
-+ && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
-+ {
-+ unsigned int i;
-+ optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
-+ const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
-+ rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
-+ rtx xop0, xop1, xtarget;
-+
-+ /* We can handle either a 1 or -1 value for the carry. If STORE_FLAG
-+ value is one of those, use it. Otherwise, use 1 since it is the
-+ one easiest to get. */
-+#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
-+ int normalizep = STORE_FLAG_VALUE;
-+#else
-+ int normalizep = 1;
-+#endif
-+
-+ /* Prepare the operands. */
-+ xop0 = force_reg (mode, op0);
-+ xop1 = force_reg (mode, op1);
-+
-+ xtarget = gen_reg_rtx (mode);
-+
-+ if (target == 0 || GET_CODE (target) != REG)
-+ target = xtarget;
-+
-+ /* Indicate for flow that the entire target reg is being set. */
-+ if (GET_CODE (target) == REG)
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, xtarget));
-+
-+ /* Do the actual arithmetic. */
-+ for (i = 0; i < nwords; i++)
-+ {
-+ int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
-+ rtx target_piece = operand_subword (xtarget, index, 1, mode);
-+ rtx op0_piece = operand_subword_force (xop0, index, mode);
-+ rtx op1_piece = operand_subword_force (xop1, index, mode);
-+ rtx x;
-+
-+ /* Main add/subtract of the input operands. */
-+ x = expand_binop (word_mode, binoptab,
-+ op0_piece, op1_piece,
-+ target_piece, unsignedp, next_methods);
-+ if (x == 0)
-+ break;
-+
-+ if (i + 1 < nwords)
-+ {
-+ /* Store carry from main add/subtract. */
-+ carry_out = gen_reg_rtx (word_mode);
-+ carry_out = emit_store_flag_force (carry_out,
-+ (binoptab == add_optab
-+ ? LT : GT),
-+ x, op0_piece,
-+ word_mode, 1, normalizep);
-+ }
-+
-+ if (i > 0)
-+ {
-+ rtx newx;
-+
-+ /* Add/subtract previous carry to main result. */
-+ newx = expand_binop (word_mode,
-+ normalizep == 1 ? binoptab : otheroptab,
-+ x, carry_in,
-+ NULL_RTX, 1, next_methods);
-+
-+ if (i + 1 < nwords)
-+ {
-+ /* Get out carry from adding/subtracting carry in. */
-+ rtx carry_tmp = gen_reg_rtx (word_mode);
-+ carry_tmp = emit_store_flag_force (carry_tmp,
-+ (binoptab == add_optab
-+ ? LT : GT),
-+ newx, x,
-+ word_mode, 1, normalizep);
-+
-+ /* Logical-ior the two poss. carry together. */
-+ carry_out = expand_binop (word_mode, ior_optab,
-+ carry_out, carry_tmp,
-+ carry_out, 0, next_methods);
-+ if (carry_out == 0)
-+ break;
-+ }
-+ emit_move_insn (target_piece, newx);
-+ }
-+
-+ carry_in = carry_out;
-+ }
-+
-+ if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
-+ {
-+ if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ rtx temp = emit_move_insn (target, xtarget);
-+
-+ set_unique_reg_note (temp,
-+ REG_EQUAL,
-+ gen_rtx_fmt_ee (binoptab->code, mode,
-+ copy_rtx (xop0),
-+ copy_rtx (xop1)));
-+ }
-+ else
-+ target = xtarget;
-+
-+ return target;
-+ }
-+
-+ else
-+ delete_insns_since (last);
-+ }
-+
-+ /* If we want to multiply two two-word values and have normal and widening
-+ multiplies of single-word values, we can do this with three smaller
-+ multiplications. Note that we do not make a REG_NO_CONFLICT block here
-+ because we are not operating on one word at a time.
-+
-+ The multiplication proceeds as follows:
-+ _______________________
-+ [__op0_high_|__op0_low__]
-+ _______________________
-+ * [__op1_high_|__op1_low__]
-+ _______________________________________________
-+ _______________________
-+ (1) [__op0_low__*__op1_low__]
-+ _______________________
-+ (2a) [__op0_low__*__op1_high_]
-+ _______________________
-+ (2b) [__op0_high_*__op1_low__]
-+ _______________________
-+ (3) [__op0_high_*__op1_high_]
-+
-+
-+ This gives a 4-word result. Since we are only interested in the
-+ lower 2 words, partial result (3) and the upper words of (2a) and
-+ (2b) don't need to be calculated. Hence (2a) and (2b) can be
-+ calculated using non-widening multiplication.
-+
-+ (1), however, needs to be calculated with an unsigned widening
-+ multiplication. If this operation is not directly supported we
-+ try using a signed widening multiplication and adjust the result.
-+ This adjustment works as follows:
-+
-+ If both operands are positive then no adjustment is needed.
-+
-+ If the operands have different signs, for example op0_low < 0 and
-+ op1_low >= 0, the instruction treats the most significant bit of
-+ op0_low as a sign bit instead of a bit with significance
-+ 2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
-+ with 2**BITS_PER_WORD - op0_low, and two's complements the
-+ result. Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
-+ the result.
-+
-+ Similarly, if both operands are negative, we need to add
-+ (op0_low + op1_low) * 2**BITS_PER_WORD.
-+
-+ We use a trick to adjust quickly. We logically shift op0_low right
-+ (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
-+ op0_high (op1_high) before it is used to calculate 2b (2a). If no
-+ logical shift exists, we do an arithmetic right shift and subtract
-+ the 0 or -1. */
-+
-+ if (binoptab == smul_optab
-+ && class == MODE_INT
-+ && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
-+ && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
-+ && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
-+ && ((umul_widen_optab->handlers[(int) mode].insn_code
-+ != CODE_FOR_nothing)
-+ || (smul_widen_optab->handlers[(int) mode].insn_code
-+ != CODE_FOR_nothing)))
-+ {
-+ int low = (WORDS_BIG_ENDIAN ? 1 : 0);
-+ int high = (WORDS_BIG_ENDIAN ? 0 : 1);
-+ rtx op0_high = operand_subword_force (op0, high, mode);
-+ rtx op0_low = operand_subword_force (op0, low, mode);
-+ rtx op1_high = operand_subword_force (op1, high, mode);
-+ rtx op1_low = operand_subword_force (op1, low, mode);
-+ rtx product = 0;
-+ rtx op0_xhigh = NULL_RTX;
-+ rtx op1_xhigh = NULL_RTX;
-+
-+ /* If the target is the same as one of the inputs, don't use it. This
-+ prevents problems with the REG_EQUAL note. */
-+ if (target == op0 || target == op1
-+ || (target != 0 && GET_CODE (target) != REG))
-+ target = 0;
-+
-+ /* Multiply the two lower words to get a double-word product.
-+ If unsigned widening multiplication is available, use that;
-+ otherwise use the signed form and compensate. */
-+
-+ if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
-+ target, 1, OPTAB_DIRECT);
-+
-+ /* If we didn't succeed, delete everything we did so far. */
-+ if (product == 0)
-+ delete_insns_since (last);
-+ else
-+ op0_xhigh = op0_high, op1_xhigh = op1_high;
-+ }
-+
-+ if (product == 0
-+ && smul_widen_optab->handlers[(int) mode].insn_code
-+ != CODE_FOR_nothing)
-+ {
-+ rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
-+ product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
-+ target, 1, OPTAB_DIRECT);
-+ op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
-+ NULL_RTX, 1, next_methods);
-+ if (op0_xhigh)
-+ op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
-+ op0_xhigh, op0_xhigh, 0, next_methods);
-+ else
-+ {
-+ op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
-+ NULL_RTX, 0, next_methods);
-+ if (op0_xhigh)
-+ op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
-+ op0_xhigh, op0_xhigh, 0,
-+ next_methods);
-+ }
-+
-+ op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
-+ NULL_RTX, 1, next_methods);
-+ if (op1_xhigh)
-+ op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
-+ op1_xhigh, op1_xhigh, 0, next_methods);
-+ else
-+ {
-+ op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
-+ NULL_RTX, 0, next_methods);
-+ if (op1_xhigh)
-+ op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
-+ op1_xhigh, op1_xhigh, 0,
-+ next_methods);
-+ }
-+ }
-+
-+ /* If we have been able to directly compute the product of the
-+ low-order words of the operands and perform any required adjustments
-+ of the operands, we proceed by trying two more multiplications
-+ and then computing the appropriate sum.
-+
-+ We have checked above that the required addition is provided.
-+ Full-word addition will normally always succeed, especially if
-+ it is provided at all, so we don't worry about its failure. The
-+ multiplication may well fail, however, so we do handle that. */
-+
-+ if (product && op0_xhigh && op1_xhigh)
-+ {
-+ rtx product_high = operand_subword (product, high, 1, mode);
-+ rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
-+ NULL_RTX, 0, OPTAB_DIRECT);
-+
-+ if (!REG_P (product_high))
-+ product_high = force_reg (word_mode, product_high);
-+
-+ if (temp != 0)
-+ temp = expand_binop (word_mode, add_optab, temp, product_high,
-+ product_high, 0, next_methods);
-+
-+ if (temp != 0 && temp != product_high)
-+ emit_move_insn (product_high, temp);
-+
-+ if (temp != 0)
-+ temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
-+ NULL_RTX, 0, OPTAB_DIRECT);
-+
-+ if (temp != 0)
-+ temp = expand_binop (word_mode, add_optab, temp,
-+ product_high, product_high,
-+ 0, next_methods);
-+
-+ if (temp != 0 && temp != product_high)
-+ emit_move_insn (product_high, temp);
-+
-+ emit_move_insn (operand_subword (product, high, 1, mode), product_high);
-+
-+ if (temp != 0)
-+ {
-+ if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ temp = emit_move_insn (product, product);
-+ set_unique_reg_note (temp,
-+ REG_EQUAL,
-+ gen_rtx_fmt_ee (MULT, mode,
-+ copy_rtx (op0),
-+ copy_rtx (op1)));
-+ }
-+
-+ return product;
-+ }
-+ }
-+
-+ /* If we get here, we couldn't do it for some reason even though we
-+ originally thought we could. Delete anything we've emitted in
-+ trying to do it. */
-+
-+ delete_insns_since (last);
-+ }
-+
-+ /* Open-code the vector operations if we have no hardware support
-+ for them. */
-+ if (class == MODE_VECTOR_INT || class == MODE_VECTOR_FLOAT)
-+ return expand_vector_binop (mode, binoptab, op0, op1, target,
-+ unsignedp, methods);
-+
-+ /* We need to open-code the complex type operations: '+, -, * and /' */
-+
-+ /* At this point we allow operations between two similar complex
-+ numbers, and also if one of the operands is not a complex number
-+ but rather of MODE_FLOAT or MODE_INT. However, the caller
-+ must make sure that the MODE of the non-complex operand matches
-+ the SUBMODE of the complex operand. */
-+
-+ if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
-+ {
-+ rtx real0 = 0, imag0 = 0;
-+ rtx real1 = 0, imag1 = 0;
-+ rtx realr, imagr, res;
-+ rtx seq;
-+ rtx equiv_value;
-+ int ok = 0;
-+
-+ /* Find the correct mode for the real and imaginary parts */
-+ enum machine_mode submode = GET_MODE_INNER(mode);
-+
-+ if (submode == BLKmode)
-+ abort ();
-+
-+ if (! target)
-+ target = gen_reg_rtx (mode);
-+
-+ start_sequence ();
-+
-+ realr = gen_realpart (submode, target);
-+ imagr = gen_imagpart (submode, target);
-+
-+ if (GET_MODE (op0) == mode)
-+ {
-+ real0 = gen_realpart (submode, op0);
-+ imag0 = gen_imagpart (submode, op0);
-+ }
-+ else
-+ real0 = op0;
-+
-+ if (GET_MODE (op1) == mode)
-+ {
-+ real1 = gen_realpart (submode, op1);
-+ imag1 = gen_imagpart (submode, op1);
-+ }
-+ else
-+ real1 = op1;
-+
-+ if (real0 == 0 || real1 == 0 || ! (imag0 != 0 || imag1 != 0))
-+ abort ();
-+
-+ switch (binoptab->code)
-+ {
-+ case PLUS:
-+ /* (a+ib) + (c+id) = (a+c) + i(b+d) */
-+ case MINUS:
-+ /* (a+ib) - (c+id) = (a-c) + i(b-d) */
-+ res = expand_binop (submode, binoptab, real0, real1,
-+ realr, unsignedp, methods);
-+
-+ if (res == 0)
-+ break;
-+ else if (res != realr)
-+ emit_move_insn (realr, res);
-+
-+ if (imag0 != 0 && imag1 != 0)
-+ res = expand_binop (submode, binoptab, imag0, imag1,
-+ imagr, unsignedp, methods);
-+ else if (imag0 != 0)
-+ res = imag0;
-+ else if (binoptab->code == MINUS)
-+ res = expand_unop (submode,
-+ binoptab == subv_optab ? negv_optab : neg_optab,
-+ imag1, imagr, unsignedp);
-+ else
-+ res = imag1;
-+
-+ if (res == 0)
-+ break;
-+ else if (res != imagr)
-+ emit_move_insn (imagr, res);
-+
-+ ok = 1;
-+ break;
-+
-+ case MULT:
-+ /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */
-+
-+ if (imag0 != 0 && imag1 != 0)
-+ {
-+ rtx temp1, temp2;
-+
-+ /* Don't fetch these from memory more than once. */
-+ real0 = force_reg (submode, real0);
-+ real1 = force_reg (submode, real1);
-+ imag0 = force_reg (submode, imag0);
-+ imag1 = force_reg (submode, imag1);
-+
-+ temp1 = expand_binop (submode, binoptab, real0, real1, NULL_RTX,
-+ unsignedp, methods);
-+
-+ temp2 = expand_binop (submode, binoptab, imag0, imag1, NULL_RTX,
-+ unsignedp, methods);
-+
-+ if (temp1 == 0 || temp2 == 0)
-+ break;
-+
-+ res = (expand_binop
-+ (submode,
-+ binoptab == smulv_optab ? subv_optab : sub_optab,
-+ temp1, temp2, realr, unsignedp, methods));
-+
-+ if (res == 0)
-+ break;
-+ else if (res != realr)
-+ emit_move_insn (realr, res);
-+
-+ temp1 = expand_binop (submode, binoptab, real0, imag1,
-+ NULL_RTX, unsignedp, methods);
-+
-+ temp2 = expand_binop (submode, binoptab, real1, imag0,
-+ NULL_RTX, unsignedp, methods);
-+
-+ if (temp1 == 0 || temp2 == 0)
-+ break;
-+
-+ res = (expand_binop
-+ (submode,
-+ binoptab == smulv_optab ? addv_optab : add_optab,
-+ temp1, temp2, imagr, unsignedp, methods));
-+
-+ if (res == 0)
-+ break;
-+ else if (res != imagr)
-+ emit_move_insn (imagr, res);
-+
-+ ok = 1;
-+ }
-+ else
-+ {
-+ /* Don't fetch these from memory more than once. */
-+ real0 = force_reg (submode, real0);
-+ real1 = force_reg (submode, real1);
-+
-+ res = expand_binop (submode, binoptab, real0, real1,
-+ realr, unsignedp, methods);
-+ if (res == 0)
-+ break;
-+ else if (res != realr)
-+ emit_move_insn (realr, res);
-+
-+ if (imag0 != 0)
-+ res = expand_binop (submode, binoptab,
-+ real1, imag0, imagr, unsignedp, methods);
-+ else
-+ res = expand_binop (submode, binoptab,
-+ real0, imag1, imagr, unsignedp, methods);
-+
-+ if (res == 0)
-+ break;
-+ else if (res != imagr)
-+ emit_move_insn (imagr, res);
-+
-+ ok = 1;
-+ }
-+ break;
-+
-+ case DIV:
-+ /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
-+
-+ if (imag1 == 0)
-+ {
-+ /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
-+
-+ /* Don't fetch these from memory more than once. */
-+ real1 = force_reg (submode, real1);
-+
-+ /* Simply divide the real and imaginary parts by `c' */
-+ if (class == MODE_COMPLEX_FLOAT)
-+ res = expand_binop (submode, binoptab, real0, real1,
-+ realr, unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ real0, real1, realr, unsignedp);
-+
-+ if (res == 0)
-+ break;
-+ else if (res != realr)
-+ emit_move_insn (realr, res);
-+
-+ if (class == MODE_COMPLEX_FLOAT)
-+ res = expand_binop (submode, binoptab, imag0, real1,
-+ imagr, unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ imag0, real1, imagr, unsignedp);
-+
-+ if (res == 0)
-+ break;
-+ else if (res != imagr)
-+ emit_move_insn (imagr, res);
-+
-+ ok = 1;
-+ }
-+ else
-+ {
-+ switch (flag_complex_divide_method)
-+ {
-+ case 0:
-+ ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
-+ realr, imagr, submode,
-+ unsignedp, methods,
-+ class, binoptab);
-+ break;
-+
-+ case 1:
-+ ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
-+ realr, imagr, submode,
-+ unsignedp, methods,
-+ class, binoptab);
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+ }
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+
-+ seq = get_insns ();
-+ end_sequence ();
-+
-+ if (ok)
-+ {
-+ if (binoptab->code != UNKNOWN)
-+ equiv_value
-+ = gen_rtx_fmt_ee (binoptab->code, mode,
-+ copy_rtx (op0), copy_rtx (op1));
-+ else
-+ equiv_value = 0;
-+
-+ emit_no_conflict_block (seq, target, op0, op1, equiv_value);
-+
-+ return target;
-+ }
-+ }
-+
-+ /* It can't be open-coded in this mode.
-+ Use a library call if one is available and caller says that's ok. */
-+
-+ if (binoptab->handlers[(int) mode].libfunc
-+ && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
-+ {
-+ rtx insns;
-+ rtx op1x = op1;
-+ enum machine_mode op1_mode = mode;
-+ rtx value;
-+
-+ start_sequence ();
-+
-+ if (shift_op)
-+ {
-+ op1_mode = word_mode;
-+ /* Specify unsigned here,
-+ since negative shift counts are meaningless. */
-+ op1x = convert_to_mode (word_mode, op1, 1);
-+ }
-+
-+ if (GET_MODE (op0) != VOIDmode
-+ && GET_MODE (op0) != mode)
-+ op0 = convert_to_mode (mode, op0, unsignedp);
-+
-+ /* Pass 1 for NO_QUEUE so we don't lose any increments
-+ if the libcall is cse'd or moved. */
-+ value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
-+ NULL_RTX, LCT_CONST, mode, 2,
-+ op0, mode, op1x, op1_mode);
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ target = gen_reg_rtx (mode);
-+ emit_libcall_block (insns, target, value,
-+ gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
-+
-+ return target;
-+ }
-+
-+ delete_insns_since (last);
-+
-+ /* It can't be done in this mode. Can we do it in a wider mode? */
-+
-+ if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
-+ || methods == OPTAB_MUST_WIDEN))
-+ {
-+ /* Caller says, don't even try. */
-+ delete_insns_since (entry_last);
-+ return 0;
-+ }
-+
-+ /* Compute the value of METHODS to pass to recursive calls.
-+ Don't allow widening to be tried recursively. */
-+
-+ methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
-+
-+ /* Look for a wider mode of the same class for which it appears we can do
-+ the operation. */
-+
-+ if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
-+ {
-+ for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode))
-+ {
-+ if ((binoptab->handlers[(int) wider_mode].insn_code
-+ != CODE_FOR_nothing)
-+ || (methods == OPTAB_LIB
-+ && binoptab->handlers[(int) wider_mode].libfunc))
-+ {
-+ rtx xop0 = op0, xop1 = op1;
-+ int no_extend = 0;
-+
-+ /* For certain integer operations, we need not actually extend
-+ the narrow operands, as long as we will truncate
-+ the results to the same narrowness. */
-+
-+ if ((binoptab == ior_optab || binoptab == and_optab
-+ || binoptab == xor_optab
-+ || binoptab == add_optab || binoptab == sub_optab
-+ || binoptab == smul_optab || binoptab == ashl_optab)
-+ && class == MODE_INT)
-+ no_extend = 1;
-+
-+ xop0 = widen_operand (xop0, wider_mode, mode,
-+ unsignedp, no_extend);
-+
-+ /* The second operand of a shift must always be extended. */
-+ xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
-+ no_extend && binoptab != ashl_optab);
-+
-+ temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
-+ unsignedp, methods);
-+ if (temp)
-+ {
-+ if (class != MODE_INT)
-+ {
-+ if (target == 0)
-+ target = gen_reg_rtx (mode);
-+ convert_move (target, temp, 0);
-+ return target;
-+ }
-+ else
-+ return gen_lowpart (mode, temp);
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+ }
-+
-+ delete_insns_since (entry_last);
-+ return 0;
-+}
-+
-+/* Like expand_binop, but for open-coding vectors binops. */
-+
-+static rtx
-+expand_vector_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
-+ enum machine_mode mode;
-+ optab binoptab;
-+ rtx op0, op1;
-+ rtx target;
-+ int unsignedp;
-+ enum optab_methods methods;
-+{
-+ enum machine_mode submode, tmode;
-+ int size, elts, subsize, subbitsize, i;
-+ rtx t, a, b, res, seq;
-+ enum mode_class class;
-+
-+ class = GET_MODE_CLASS (mode);
-+
-+ size = GET_MODE_SIZE (mode);
-+ submode = GET_MODE_INNER (mode);
-+
-+ /* Search for the widest vector mode with the same inner mode that is
-+ still narrower than MODE and that allows to open-code this operator.
-+ Note, if we find such a mode and the handler later decides it can't
-+ do the expansion, we'll be called recursively with the narrower mode. */
-+ for (tmode = GET_CLASS_NARROWEST_MODE (class);
-+ GET_MODE_SIZE (tmode) < GET_MODE_SIZE (mode);
-+ tmode = GET_MODE_WIDER_MODE (tmode))
-+ {
-+ if (GET_MODE_INNER (tmode) == GET_MODE_INNER (mode)
-+ && binoptab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
-+ submode = tmode;
-+ }
-+
-+ switch (binoptab->code)
-+ {
-+ case AND:
-+ case IOR:
-+ case XOR:
-+ tmode = int_mode_for_mode (mode);
-+ if (tmode != BLKmode)
-+ submode = tmode;
-+ case PLUS:
-+ case MINUS:
-+ case MULT:
-+ case DIV:
-+ subsize = GET_MODE_SIZE (submode);
-+ subbitsize = GET_MODE_BITSIZE (submode);
-+ elts = size / subsize;
-+
-+ /* If METHODS is OPTAB_DIRECT, we don't insist on the exact mode,
-+ but that we operate on more than one element at a time. */
-+ if (subsize == GET_MODE_UNIT_SIZE (mode) && methods == OPTAB_DIRECT)
-+ return 0;
-+
-+ start_sequence ();
-+
-+ /* Errors can leave us with a const0_rtx as operand. */
-+ if (GET_MODE (op0) != mode)
-+ op0 = copy_to_mode_reg (mode, op0);
-+ if (GET_MODE (op1) != mode)
-+ op1 = copy_to_mode_reg (mode, op1);
-+
-+ if (!target)
-+ target = gen_reg_rtx (mode);
-+
-+ for (i = 0; i < elts; ++i)
-+ {
-+ /* If this is part of a register, and not the first item in the
-+ word, we can't store using a SUBREG - that would clobber
-+ previous results.
-+ And storing with a SUBREG is only possible for the least
-+ significant part, hence we can't do it for big endian
-+ (unless we want to permute the evaluation order. */
-+ if (GET_CODE (target) == REG
-+ && (BYTES_BIG_ENDIAN
-+ ? subsize < UNITS_PER_WORD
-+ : ((i * subsize) % UNITS_PER_WORD) != 0))
-+ t = NULL_RTX;
-+ else
-+ t = simplify_gen_subreg (submode, target, mode, i * subsize);
-+ if (CONSTANT_P (op0))
-+ a = simplify_gen_subreg (submode, op0, mode, i * subsize);
-+ else
-+ a = extract_bit_field (op0, subbitsize, i * subbitsize, unsignedp,
-+ NULL_RTX, submode, submode, size);
-+ if (CONSTANT_P (op1))
-+ b = simplify_gen_subreg (submode, op1, mode, i * subsize);
-+ else
-+ b = extract_bit_field (op1, subbitsize, i * subbitsize, unsignedp,
-+ NULL_RTX, submode, submode, size);
-+
-+ if (binoptab->code == DIV)
-+ {
-+ if (class == MODE_VECTOR_FLOAT)
-+ res = expand_binop (submode, binoptab, a, b, t,
-+ unsignedp, methods);
-+ else
-+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
-+ a, b, t, unsignedp);
-+ }
-+ else
-+ res = expand_binop (submode, binoptab, a, b, t,
-+ unsignedp, methods);
-+
-+ if (res == 0)
-+ break;
-+
-+ if (t)
-+ emit_move_insn (t, res);
-+ else
-+ store_bit_field (target, subbitsize, i * subbitsize, submode, res,
-+ size);
-+ }
-+ break;
-+
-+ default:
-+ abort ();
-+ }
-+
-+ seq = get_insns ();
-+ end_sequence ();
-+ emit_insn (seq);
-+
-+ return target;
-+}
-+
-+/* Like expand_unop but for open-coding vector unops. */
-+
-+static rtx
-+expand_vector_unop (mode, unoptab, op0, target, unsignedp)
-+ enum machine_mode mode;
-+ optab unoptab;
-+ rtx op0;
-+ rtx target;
-+ int unsignedp;
-+{
-+ enum machine_mode submode, tmode;
-+ int size, elts, subsize, subbitsize, i;
-+ rtx t, a, res, seq;
-+
-+ size = GET_MODE_SIZE (mode);
-+ submode = GET_MODE_INNER (mode);
-+
-+ /* Search for the widest vector mode with the same inner mode that is
-+ still narrower than MODE and that allows to open-code this operator.
-+ Note, if we find such a mode and the handler later decides it can't
-+ do the expansion, we'll be called recursively with the narrower mode. */
-+ for (tmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (mode));
-+ GET_MODE_SIZE (tmode) < GET_MODE_SIZE (mode);
-+ tmode = GET_MODE_WIDER_MODE (tmode))
-+ {
-+ if (GET_MODE_INNER (tmode) == GET_MODE_INNER (mode)
-+ && unoptab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
-+ submode = tmode;
-+ }
-+ /* If there is no negate operation, try doing a subtract from zero. */
-+ if (unoptab == neg_optab && GET_MODE_CLASS (submode) == MODE_INT
-+ /* Avoid infinite recursion when an
-+ error has left us with the wrong mode. */
-+ && GET_MODE (op0) == mode)
-+ {
-+ rtx temp;
-+ temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
-+ target, unsignedp, OPTAB_DIRECT);
-+ if (temp)
-+ return temp;
-+ }
-+
-+ if (unoptab == one_cmpl_optab)
-+ {
-+ tmode = int_mode_for_mode (mode);
-+ if (tmode != BLKmode)
-+ submode = tmode;
-+ }
-+
-+ subsize = GET_MODE_SIZE (submode);
-+ subbitsize = GET_MODE_BITSIZE (submode);
-+ elts = size / subsize;
-+
-+ /* Errors can leave us with a const0_rtx as operand. */
-+ if (GET_MODE (op0) != mode)
-+ op0 = copy_to_mode_reg (mode, op0);
-+
-+ if (!target)
-+ target = gen_reg_rtx (mode);
-+
-+ start_sequence ();
-+
-+ for (i = 0; i < elts; ++i)
-+ {
-+ /* If this is part of a register, and not the first item in the
-+ word, we can't store using a SUBREG - that would clobber
-+ previous results.
-+ And storing with a SUBREG is only possible for the least
-+ significant part, hence we can't do it for big endian
-+ (unless we want to permute the evaluation order. */
-+ if (GET_CODE (target) == REG
-+ && (BYTES_BIG_ENDIAN
-+ ? subsize < UNITS_PER_WORD
-+ : ((i * subsize) % UNITS_PER_WORD) != 0))
-+ t = NULL_RTX;
-+ else
-+ t = simplify_gen_subreg (submode, target, mode, i * subsize);
-+ if (CONSTANT_P (op0))
-+ a = simplify_gen_subreg (submode, op0, mode, i * subsize);
-+ else
-+ a = extract_bit_field (op0, subbitsize, i * subbitsize, unsignedp,
-+ t, submode, submode, size);
-+
-+ res = expand_unop (submode, unoptab, a, t, unsignedp);
-+
-+ if (t)
-+ emit_move_insn (t, res);
-+ else
-+ store_bit_field (target, subbitsize, i * subbitsize, submode, res,
-+ size);
-+ }
-+
-+ seq = get_insns ();
-+ end_sequence ();
-+ emit_insn (seq);
-+
-+ return target;
-+}
-+\f
-+/* Expand a binary operator which has both signed and unsigned forms.
-+ UOPTAB is the optab for unsigned operations, and SOPTAB is for
-+ signed operations.
-+
-+ If we widen unsigned operands, we may use a signed wider operation instead
-+ of an unsigned wider operation, since the result would be the same. */
-+
-+rtx
-+sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
-+ enum machine_mode mode;
-+ optab uoptab, soptab;
-+ rtx op0, op1, target;
-+ int unsignedp;
-+ enum optab_methods methods;
-+{
-+ rtx temp;
-+ optab direct_optab = unsignedp ? uoptab : soptab;
-+ struct optab wide_soptab;
-+
-+ /* Do it without widening, if possible. */
-+ temp = expand_binop (mode, direct_optab, op0, op1, target,
-+ unsignedp, OPTAB_DIRECT);
-+ if (temp || methods == OPTAB_DIRECT)
-+ return temp;
-+
-+ /* Try widening to a signed int. Make a fake signed optab that
-+ hides any signed insn for direct use. */
-+ wide_soptab = *soptab;
-+ wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
-+ wide_soptab.handlers[(int) mode].libfunc = 0;
-+
-+ temp = expand_binop (mode, &wide_soptab, op0, op1, target,
-+ unsignedp, OPTAB_WIDEN);
-+
-+ /* For unsigned operands, try widening to an unsigned int. */
-+ if (temp == 0 && unsignedp)
-+ temp = expand_binop (mode, uoptab, op0, op1, target,
-+ unsignedp, OPTAB_WIDEN);
-+ if (temp || methods == OPTAB_WIDEN)
-+ return temp;
-+
-+ /* Use the right width lib call if that exists. */
-+ temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
-+ if (temp || methods == OPTAB_LIB)
-+ return temp;
-+
-+ /* Must widen and use a lib call, use either signed or unsigned. */
-+ temp = expand_binop (mode, &wide_soptab, op0, op1, target,
-+ unsignedp, methods);
-+ if (temp != 0)
-+ return temp;
-+ if (unsignedp)
-+ return expand_binop (mode, uoptab, op0, op1, target,
-+ unsignedp, methods);
-+ return 0;
-+}
-+\f
-+/* Generate code to perform an operation specified by BINOPTAB
-+ on operands OP0 and OP1, with two results to TARG1 and TARG2.
-+ We assume that the order of the operands for the instruction
-+ is TARG0, OP0, OP1, TARG1, which would fit a pattern like
-+ [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
-+
-+ Either TARG0 or TARG1 may be zero, but what that means is that
-+ the result is not actually wanted. We will generate it into
-+ a dummy pseudo-reg and discard it. They may not both be zero.
-+
-+ Returns 1 if this operation can be performed; 0 if not. */
-+
-+int
-+expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
-+ optab binoptab;
-+ rtx op0, op1;
-+ rtx targ0, targ1;
-+ int unsignedp;
-+{
-+ enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
-+ enum mode_class class;
-+ enum machine_mode wider_mode;
-+ rtx entry_last = get_last_insn ();
-+ rtx last;
-+
-+ class = GET_MODE_CLASS (mode);
-+
-+ op0 = protect_from_queue (op0, 0);
-+ op1 = protect_from_queue (op1, 0);
-+
-+ if (flag_force_mem)
-+ {
-+ op0 = force_not_mem (op0);
-+ op1 = force_not_mem (op1);
-+ }
-+
-+ /* If we are inside an appropriately-short loop and one operand is an
-+ expensive constant, force it into a register. */
-+ if (CONSTANT_P (op0) && preserve_subexpressions_p ()
-+ && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
-+ op0 = force_reg (mode, op0);
-+
-+ if (CONSTANT_P (op1) && preserve_subexpressions_p ()
-+ && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
-+ op1 = force_reg (mode, op1);
-+
-+ if (targ0)
-+ targ0 = protect_from_queue (targ0, 1);
-+ else
-+ targ0 = gen_reg_rtx (mode);
-+ if (targ1)
-+ targ1 = protect_from_queue (targ1, 1);
-+ else
-+ targ1 = gen_reg_rtx (mode);
-+
-+ /* Record where to go back to if we fail. */
-+ last = get_last_insn ();
-+
-+ if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ int icode = (int) binoptab->handlers[(int) mode].insn_code;
-+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
-+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
-+ rtx pat;
-+ rtx xop0 = op0, xop1 = op1;
-+
-+ /* In case the insn wants input operands in modes different from
-+ those of the actual operands, convert the operands. It would
-+ seem that we don't need to convert CONST_INTs, but we do, so
-+ that they're properly zero-extended, sign-extended or truncated
-+ for their mode. */
-+
-+ if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
-+ xop0 = convert_modes (mode0,
-+ GET_MODE (op0) != VOIDmode
-+ ? GET_MODE (op0)
-+ : mode,
-+ xop0, unsignedp);
-+
-+ if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
-+ xop1 = convert_modes (mode1,
-+ GET_MODE (op1) != VOIDmode
-+ ? GET_MODE (op1)
-+ : mode,
-+ xop1, unsignedp);
-+
-+ /* Now, if insn doesn't accept these operands, put them into pseudos. */
-+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
-+ xop0 = copy_to_mode_reg (mode0, xop0);
-+
-+ if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1))
-+ xop1 = copy_to_mode_reg (mode1, xop1);
-+
-+ /* We could handle this, but we should always be called with a pseudo
-+ for our targets and all insns should take them as outputs. */
-+ if (! (*insn_data[icode].operand[0].predicate) (targ0, mode)
-+ || ! (*insn_data[icode].operand[3].predicate) (targ1, mode))
-+ abort ();
-+
-+ pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
-+ if (pat)
-+ {
-+ emit_insn (pat);
-+ return 1;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+
-+ /* It can't be done in this mode. Can we do it in a wider mode? */
-+
-+ if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
-+ {
-+ for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode))
-+ {
-+ if (binoptab->handlers[(int) wider_mode].insn_code
-+ != CODE_FOR_nothing)
-+ {
-+ rtx t0 = gen_reg_rtx (wider_mode);
-+ rtx t1 = gen_reg_rtx (wider_mode);
-+ rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
-+ rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
-+
-+ if (expand_twoval_binop (binoptab, cop0, cop1,
-+ t0, t1, unsignedp))
-+ {
-+ convert_move (targ0, t0, unsignedp);
-+ convert_move (targ1, t1, unsignedp);
-+ return 1;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+ }
-+
-+ delete_insns_since (entry_last);
-+ return 0;
-+}
-+\f
-+/* Wrapper around expand_unop which takes an rtx code to specify
-+ the operation to perform, not an optab pointer. All other
-+ arguments are the same. */
-+rtx
-+expand_simple_unop (mode, code, op0, target, unsignedp)
-+ enum machine_mode mode;
-+ enum rtx_code code;
-+ rtx op0;
-+ rtx target;
-+ int unsignedp;
-+{
-+ optab unop = code_to_optab[(int) code];
-+ if (unop == 0)
-+ abort ();
-+
-+ return expand_unop (mode, unop, op0, target, unsignedp);
-+}
-+
-+/* Generate code to perform an operation specified by UNOPTAB
-+ on operand OP0, with result having machine-mode MODE.
-+
-+ UNSIGNEDP is for the case where we have to widen the operands
-+ to perform the operation. It says to use zero-extension.
-+
-+ If TARGET is nonzero, the value
-+ is generated there, if it is convenient to do so.
-+ In all cases an rtx is returned for the locus of the value;
-+ this may or may not be TARGET. */
-+
-+rtx
-+expand_unop (mode, unoptab, op0, target, unsignedp)
-+ enum machine_mode mode;
-+ optab unoptab;
-+ rtx op0;
-+ rtx target;
-+ int unsignedp;
-+{
-+ enum mode_class class;
-+ enum machine_mode wider_mode;
-+ rtx temp;
-+ rtx last = get_last_insn ();
-+ rtx pat;
-+
-+ class = GET_MODE_CLASS (mode);
-+
-+ op0 = protect_from_queue (op0, 0);
-+
-+ if (flag_force_mem)
-+ {
-+ op0 = force_not_mem (op0);
-+ }
-+
-+ if (target)
-+ target = protect_from_queue (target, 1);
-+
-+ if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ int icode = (int) unoptab->handlers[(int) mode].insn_code;
-+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
-+ rtx xop0 = op0;
-+
-+ if (target)
-+ temp = target;
-+ else
-+ temp = gen_reg_rtx (mode);
-+
-+ if (GET_MODE (xop0) != VOIDmode
-+ && GET_MODE (xop0) != mode0)
-+ xop0 = convert_to_mode (mode0, xop0, unsignedp);
-+
-+ /* Now, if insn doesn't accept our operand, put it into a pseudo. */
-+
-+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
-+ xop0 = copy_to_mode_reg (mode0, xop0);
-+
-+ if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
-+ temp = gen_reg_rtx (mode);
-+
-+ pat = GEN_FCN (icode) (temp, xop0);
-+ if (pat)
-+ {
-+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
-+ && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
-+ {
-+ delete_insns_since (last);
-+ return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
-+ }
-+
-+ emit_insn (pat);
-+
-+ return temp;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+
-+ /* It can't be done in this mode. Can we open-code it in a wider mode? */
-+
-+ if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
-+ for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode))
-+ {
-+ if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
-+ {
-+ rtx xop0 = op0;
-+
-+ /* For certain operations, we need not actually extend
-+ the narrow operand, as long as we will truncate the
-+ results to the same narrowness. */
-+
-+ xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
-+ (unoptab == neg_optab
-+ || unoptab == one_cmpl_optab)
-+ && class == MODE_INT);
-+
-+ temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
-+ unsignedp);
-+
-+ if (temp)
-+ {
-+ if (class != MODE_INT)
-+ {
-+ if (target == 0)
-+ target = gen_reg_rtx (mode);
-+ convert_move (target, temp, 0);
-+ return target;
-+ }
-+ else
-+ return gen_lowpart (mode, temp);
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+
-+ /* These can be done a word at a time. */
-+ if (unoptab == one_cmpl_optab
-+ && class == MODE_INT
-+ && GET_MODE_SIZE (mode) > UNITS_PER_WORD
-+ && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
-+ {
-+ int i;
-+ rtx insns;
-+
-+ if (target == 0 || target == op0)
-+ target = gen_reg_rtx (mode);
-+
-+ start_sequence ();
-+
-+ /* Do the actual arithmetic. */
-+ for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
-+ {
-+ rtx target_piece = operand_subword (target, i, 1, mode);
-+ rtx x = expand_unop (word_mode, unoptab,
-+ operand_subword_force (op0, i, mode),
-+ target_piece, unsignedp);
-+
-+ if (target_piece != x)
-+ emit_move_insn (target_piece, x);
-+ }
-+
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ emit_no_conflict_block (insns, target, op0, NULL_RTX,
-+ gen_rtx_fmt_e (unoptab->code, mode,
-+ copy_rtx (op0)));
-+ return target;
-+ }
-+
-+ /* Open-code the complex negation operation. */
-+ else if (unoptab->code == NEG
-+ && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
-+ {
-+ rtx target_piece;
-+ rtx x;
-+ rtx seq;
-+
-+ /* Find the correct mode for the real and imaginary parts */
-+ enum machine_mode submode = GET_MODE_INNER (mode);
-+
-+ if (submode == BLKmode)
-+ abort ();
-+
-+ if (target == 0)
-+ target = gen_reg_rtx (mode);
-+
-+ start_sequence ();
-+
-+ target_piece = gen_imagpart (submode, target);
-+ x = expand_unop (submode, unoptab,
-+ gen_imagpart (submode, op0),
-+ target_piece, unsignedp);
-+ if (target_piece != x)
-+ emit_move_insn (target_piece, x);
-+
-+ target_piece = gen_realpart (submode, target);
-+ x = expand_unop (submode, unoptab,
-+ gen_realpart (submode, op0),
-+ target_piece, unsignedp);
-+ if (target_piece != x)
-+ emit_move_insn (target_piece, x);
-+
-+ seq = get_insns ();
-+ end_sequence ();
-+
-+ emit_no_conflict_block (seq, target, op0, 0,
-+ gen_rtx_fmt_e (unoptab->code, mode,
-+ copy_rtx (op0)));
-+ return target;
-+ }
-+
-+ /* Now try a library call in this mode. */
-+ if (unoptab->handlers[(int) mode].libfunc)
-+ {
-+ rtx insns;
-+ rtx value;
-+
-+ start_sequence ();
-+
-+ /* Pass 1 for NO_QUEUE so we don't lose any increments
-+ if the libcall is cse'd or moved. */
-+ value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
-+ NULL_RTX, LCT_CONST, mode, 1, op0, mode);
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ target = gen_reg_rtx (mode);
-+ emit_libcall_block (insns, target, value,
-+ gen_rtx_fmt_e (unoptab->code, mode, op0));
-+
-+ return target;
-+ }
-+
-+ if (class == MODE_VECTOR_FLOAT || class == MODE_VECTOR_INT)
-+ return expand_vector_unop (mode, unoptab, op0, target, unsignedp);
-+
-+ /* It can't be done in this mode. Can we do it in a wider mode? */
-+
-+ if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
-+ {
-+ for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode))
-+ {
-+ if ((unoptab->handlers[(int) wider_mode].insn_code
-+ != CODE_FOR_nothing)
-+ || unoptab->handlers[(int) wider_mode].libfunc)
-+ {
-+ rtx xop0 = op0;
-+
-+ /* For certain operations, we need not actually extend
-+ the narrow operand, as long as we will truncate the
-+ results to the same narrowness. */
-+
-+ xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
-+ (unoptab == neg_optab
-+ || unoptab == one_cmpl_optab)
-+ && class == MODE_INT);
-+
-+ temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
-+ unsignedp);
-+
-+ if (temp)
-+ {
-+ if (class != MODE_INT)
-+ {
-+ if (target == 0)
-+ target = gen_reg_rtx (mode);
-+ convert_move (target, temp, 0);
-+ return target;
-+ }
-+ else
-+ return gen_lowpart (mode, temp);
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+ }
-+
-+ /* If there is no negate operation, try doing a subtract from zero.
-+ The US Software GOFAST library needs this. */
-+ if (unoptab->code == NEG)
-+ {
-+ rtx temp;
-+ temp = expand_binop (mode,
-+ unoptab == negv_optab ? subv_optab : sub_optab,
-+ CONST0_RTX (mode), op0,
-+ target, unsignedp, OPTAB_LIB_WIDEN);
-+ if (temp)
-+ return temp;
-+ }
-+
-+ return 0;
-+}
-+\f
-+/* Emit code to compute the absolute value of OP0, with result to
-+ TARGET if convenient. (TARGET may be 0.) The return value says
-+ where the result actually is to be found.
-+
-+ MODE is the mode of the operand; the mode of the result is
-+ different but can be deduced from MODE.
-+
-+ */
-+
-+rtx
-+expand_abs (mode, op0, target, result_unsignedp, safe)
-+ enum machine_mode mode;
-+ rtx op0;
-+ rtx target;
-+ int result_unsignedp;
-+ int safe;
-+{
-+ rtx temp, op1;
-+
-+ if (! flag_trapv)
-+ result_unsignedp = 1;
-+
-+ /* First try to do it with a special abs instruction. */
-+ temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
-+ op0, target, 0);
-+ if (temp != 0)
-+ return temp;
-+
-+ /* If we have a MAX insn, we can do this as MAX (x, -x). */
-+ if (smax_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ rtx last = get_last_insn ();
-+
-+ temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
-+ if (temp != 0)
-+ temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
-+ OPTAB_WIDEN);
-+
-+ if (temp != 0)
-+ return temp;
-+
-+ delete_insns_since (last);
-+ }
-+
-+ /* If this machine has expensive jumps, we can do integer absolute
-+ value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
-+ where W is the width of MODE. */
-+
-+ if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
-+ {
-+ rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
-+ size_int (GET_MODE_BITSIZE (mode) - 1),
-+ NULL_RTX, 0);
-+
-+ temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
-+ OPTAB_LIB_WIDEN);
-+ if (temp != 0)
-+ temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
-+ temp, extended, target, 0, OPTAB_LIB_WIDEN);
-+
-+ if (temp != 0)
-+ return temp;
-+ }
-+
-+ /* If that does not win, use conditional jump and negate. */
-+
-+ /* It is safe to use the target if it is the same
-+ as the source if this is also a pseudo register */
-+ if (op0 == target && GET_CODE (op0) == REG
-+ && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
-+ safe = 1;
-+
-+ op1 = gen_label_rtx ();
-+ if (target == 0 || ! safe
-+ || GET_MODE (target) != mode
-+ || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
-+ || (GET_CODE (target) == REG
-+ && REGNO (target) < FIRST_PSEUDO_REGISTER))
-+ target = gen_reg_rtx (mode);
-+
-+ emit_move_insn (target, op0);
-+ NO_DEFER_POP;
-+
-+ /* If this mode is an integer too wide to compare properly,
-+ compare word by word. Rely on CSE to optimize constant cases. */
-+ if (GET_MODE_CLASS (mode) == MODE_INT
-+ && ! can_compare_p (GE, mode, ccp_jump))
-+ do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx,
-+ NULL_RTX, op1);
-+ else
-+ do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
-+ NULL_RTX, NULL_RTX, op1);
-+
-+ op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
-+ target, target, 0);
-+ if (op0 != target)
-+ emit_move_insn (target, op0);
-+ emit_label (op1);
-+ OK_DEFER_POP;
-+ return target;
-+}
-+\f
-+/* Emit code to compute the absolute value of OP0, with result to
-+ TARGET if convenient. (TARGET may be 0.) The return value says
-+ where the result actually is to be found.
-+
-+ MODE is the mode of the operand; the mode of the result is
-+ different but can be deduced from MODE.
-+
-+ UNSIGNEDP is relevant for complex integer modes. */
-+
-+rtx
-+expand_complex_abs (mode, op0, target, unsignedp)
-+ enum machine_mode mode;
-+ rtx op0;
-+ rtx target;
-+ int unsignedp;
-+{
-+ enum mode_class class = GET_MODE_CLASS (mode);
-+ enum machine_mode wider_mode;
-+ rtx temp;
-+ rtx entry_last = get_last_insn ();
-+ rtx last;
-+ rtx pat;
-+ optab this_abs_optab;
-+
-+ /* Find the correct mode for the real and imaginary parts. */
-+ enum machine_mode submode = GET_MODE_INNER (mode);
-+
-+ if (submode == BLKmode)
-+ abort ();
-+
-+ op0 = protect_from_queue (op0, 0);
-+
-+ if (flag_force_mem)
-+ {
-+ op0 = force_not_mem (op0);
-+ }
-+
-+ last = get_last_insn ();
-+
-+ if (target)
-+ target = protect_from_queue (target, 1);
-+
-+ this_abs_optab = ! unsignedp && flag_trapv
-+ && (GET_MODE_CLASS(mode) == MODE_INT)
-+ ? absv_optab : abs_optab;
-+
-+ if (this_abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ int icode = (int) this_abs_optab->handlers[(int) mode].insn_code;
-+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
-+ rtx xop0 = op0;
-+
-+ if (target)
-+ temp = target;
-+ else
-+ temp = gen_reg_rtx (submode);
-+
-+ if (GET_MODE (xop0) != VOIDmode
-+ && GET_MODE (xop0) != mode0)
-+ xop0 = convert_to_mode (mode0, xop0, unsignedp);
-+
-+ /* Now, if insn doesn't accept our operand, put it into a pseudo. */
-+
-+ if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
-+ xop0 = copy_to_mode_reg (mode0, xop0);
-+
-+ if (! (*insn_data[icode].operand[0].predicate) (temp, submode))
-+ temp = gen_reg_rtx (submode);
-+
-+ pat = GEN_FCN (icode) (temp, xop0);
-+ if (pat)
-+ {
-+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
-+ && ! add_equal_note (pat, temp, this_abs_optab->code, xop0,
-+ NULL_RTX))
-+ {
-+ delete_insns_since (last);
-+ return expand_unop (mode, this_abs_optab, op0, NULL_RTX,
-+ unsignedp);
-+ }
-+
-+ emit_insn (pat);
-+
-+ return temp;
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+
-+ /* It can't be done in this mode. Can we open-code it in a wider mode? */
-+
-+ for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode))
-+ {
-+ if (this_abs_optab->handlers[(int) wider_mode].insn_code
-+ != CODE_FOR_nothing)
-+ {
-+ rtx xop0 = op0;
-+
-+ xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
-+ temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
-+
-+ if (temp)
-+ {
-+ if (class != MODE_COMPLEX_INT)
-+ {
-+ if (target == 0)
-+ target = gen_reg_rtx (submode);
-+ convert_move (target, temp, 0);
-+ return target;
-+ }
-+ else
-+ return gen_lowpart (submode, temp);
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+
-+ /* Open-code the complex absolute-value operation
-+ if we can open-code sqrt. Otherwise it's not worth while. */
-+ if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing
-+ && ! flag_trapv)
-+ {
-+ rtx real, imag, total;
-+
-+ real = gen_realpart (submode, op0);
-+ imag = gen_imagpart (submode, op0);
-+
-+ /* Square both parts. */
-+ real = expand_mult (submode, real, real, NULL_RTX, 0);
-+ imag = expand_mult (submode, imag, imag, NULL_RTX, 0);
-+
-+ /* Sum the parts. */
-+ total = expand_binop (submode, add_optab, real, imag, NULL_RTX,
-+ 0, OPTAB_LIB_WIDEN);
-+
-+ /* Get sqrt in TARGET. Set TARGET to where the result is. */
-+ target = expand_unop (submode, sqrt_optab, total, target, 0);
-+ if (target == 0)
-+ delete_insns_since (last);
-+ else
-+ return target;
-+ }
-+
-+ /* Now try a library call in this mode. */
-+ if (this_abs_optab->handlers[(int) mode].libfunc)
-+ {
-+ rtx insns;
-+ rtx value;
-+
-+ start_sequence ();
-+
-+ /* Pass 1 for NO_QUEUE so we don't lose any increments
-+ if the libcall is cse'd or moved. */
-+ value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
-+ NULL_RTX, LCT_CONST, submode, 1, op0, mode);
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ target = gen_reg_rtx (submode);
-+ emit_libcall_block (insns, target, value,
-+ gen_rtx_fmt_e (this_abs_optab->code, mode, op0));
-+
-+ return target;
-+ }
-+
-+ /* It can't be done in this mode. Can we do it in a wider mode? */
-+
-+ for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode))
-+ {
-+ if ((this_abs_optab->handlers[(int) wider_mode].insn_code
-+ != CODE_FOR_nothing)
-+ || this_abs_optab->handlers[(int) wider_mode].libfunc)
-+ {
-+ rtx xop0 = op0;
-+
-+ xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
-+
-+ temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);
-+
-+ if (temp)
-+ {
-+ if (class != MODE_COMPLEX_INT)
-+ {
-+ if (target == 0)
-+ target = gen_reg_rtx (submode);
-+ convert_move (target, temp, 0);
-+ return target;
-+ }
-+ else
-+ return gen_lowpart (submode, temp);
-+ }
-+ else
-+ delete_insns_since (last);
-+ }
-+ }
-+
-+ delete_insns_since (entry_last);
-+ return 0;
-+}
-+\f
-+/* Generate an instruction whose insn-code is INSN_CODE,
-+ with two operands: an output TARGET and an input OP0.
-+ TARGET *must* be nonzero, and the output is always stored there.
-+ CODE is an rtx code such that (CODE OP0) is an rtx that describes
-+ the value that is stored into TARGET. */
-+
-+void
-+emit_unop_insn (icode, target, op0, code)
-+ int icode;
-+ rtx target;
-+ rtx op0;
-+ enum rtx_code code;
-+{
-+ rtx temp;
-+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
-+ rtx pat;
-+
-+ temp = target = protect_from_queue (target, 1);
-+
-+ op0 = protect_from_queue (op0, 0);
-+
-+ /* Sign and zero extension from memory is often done specially on
-+ RISC machines, so forcing into a register here can pessimize
-+ code. */
-+ if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
-+ op0 = force_not_mem (op0);
-+
-+ /* Now, if insn does not accept our operands, put them into pseudos. */
-+
-+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
-+ op0 = copy_to_mode_reg (mode0, op0);
-+
-+ if (! (*insn_data[icode].operand[0].predicate) (temp, GET_MODE (temp))
-+ || (flag_force_mem && GET_CODE (temp) == MEM))
-+ temp = gen_reg_rtx (GET_MODE (temp));
-+
-+ pat = GEN_FCN (icode) (temp, op0);
-+
-+ if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
-+ add_equal_note (pat, temp, code, op0, NULL_RTX);
-+
-+ emit_insn (pat);
-+
-+ if (temp != target)
-+ emit_move_insn (target, temp);
-+}
-+\f
-+/* Emit code to perform a series of operations on a multi-word quantity, one
-+ word at a time.
-+
-+ Such a block is preceded by a CLOBBER of the output, consists of multiple
-+ insns, each setting one word of the output, and followed by a SET copying
-+ the output to itself.
-+
-+ Each of the insns setting words of the output receives a REG_NO_CONFLICT
-+ note indicating that it doesn't conflict with the (also multi-word)
-+ inputs. The entire block is surrounded by REG_LIBCALL and REG_RETVAL
-+ notes.
-+
-+ INSNS is a block of code generated to perform the operation, not including
-+ the CLOBBER and final copy. All insns that compute intermediate values
-+ are first emitted, followed by the block as described above.
-+
-+ TARGET, OP0, and OP1 are the output and inputs of the operations,
-+ respectively. OP1 may be zero for a unary operation.
-+
-+ EQUIV, if nonzero, is an expression to be placed into a REG_EQUAL note
-+ on the last insn.
-+
-+ If TARGET is not a register, INSNS is simply emitted with no special
-+ processing. Likewise if anything in INSNS is not an INSN or if
-+ there is a libcall block inside INSNS.
-+
-+ The final insn emitted is returned. */
-+
-+rtx
-+emit_no_conflict_block (insns, target, op0, op1, equiv)
-+ rtx insns;
-+ rtx target;
-+ rtx op0, op1;
-+ rtx equiv;
-+{
-+ rtx prev, next, first, last, insn;
-+
-+ if (GET_CODE (target) != REG || reload_in_progress)
-+ return emit_insn (insns);
-+ else
-+ for (insn = insns; insn; insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) != INSN
-+ || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
-+ return emit_insn (insns);
-+
-+ /* First emit all insns that do not store into words of the output and remove
-+ these from the list. */
-+ for (insn = insns; insn; insn = next)
-+ {
-+ rtx set = 0, note;
-+ int i;
-+
-+ next = NEXT_INSN (insn);
-+
-+ /* Some ports (cris) create an libcall regions at their own. We must
-+ avoid any potential nesting of LIBCALLs. */
-+ if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
-+ remove_note (insn, note);
-+ if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
-+ remove_note (insn, note);
-+
-+ if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE
-+ || GET_CODE (PATTERN (insn)) == CLOBBER)
-+ set = PATTERN (insn);
-+ else if (GET_CODE (PATTERN (insn)) == PARALLEL)
-+ {
-+ for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
-+ if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
-+ {
-+ set = XVECEXP (PATTERN (insn), 0, i);
-+ break;
-+ }
-+ }
-+
-+ if (set == 0)
-+ abort ();
-+
-+ if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
-+ {
-+ if (PREV_INSN (insn))
-+ NEXT_INSN (PREV_INSN (insn)) = next;
-+ else
-+ insns = next;
-+
-+ if (next)
-+ PREV_INSN (next) = PREV_INSN (insn);
-+
-+ add_insn (insn);
-+ }
-+ }
-+
-+ prev = get_last_insn ();
-+
-+ /* Now write the CLOBBER of the output, followed by the setting of each
-+ of the words, followed by the final copy. */
-+ if (target != op0 && target != op1)
-+ emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
-+
-+ for (insn = insns; insn; insn = next)
-+ {
-+ next = NEXT_INSN (insn);
-+ add_insn (insn);
-+
-+ if (op1 && GET_CODE (op1) == REG)
-+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
-+ REG_NOTES (insn));
-+
-+ if (op0 && GET_CODE (op0) == REG)
-+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
-+ REG_NOTES (insn));
-+ }
-+
-+ if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
-+ != CODE_FOR_nothing)
-+ {
-+ last = emit_move_insn (target, target);
-+ if (equiv)
-+ set_unique_reg_note (last, REG_EQUAL, equiv);
-+ }
-+ else
-+ {
-+ last = get_last_insn ();
-+
-+ /* Remove any existing REG_EQUAL note from "last", or else it will
-+ be mistaken for a note referring to the full contents of the
-+ alleged libcall value when found together with the REG_RETVAL
-+ note added below. An existing note can come from an insn
-+ expansion at "last". */
-+ remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
-+ }
-+
-+ if (prev == 0)
-+ first = get_insns ();
-+ else
-+ first = NEXT_INSN (prev);
-+
-+ /* Encapsulate the block so it gets manipulated as a unit. */
-+ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
-+ REG_NOTES (first));
-+ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
-+
-+ return last;
-+}
-+\f
-+/* Emit code to make a call to a constant function or a library call.
-+
-+ INSNS is a list containing all insns emitted in the call.
-+ These insns leave the result in RESULT. Our block is to copy RESULT
-+ to TARGET, which is logically equivalent to EQUIV.
-+
-+ We first emit any insns that set a pseudo on the assumption that these are
-+ loading constants into registers; doing so allows them to be safely cse'ed
-+ between blocks. Then we emit all the other insns in the block, followed by
-+ an insn to move RESULT to TARGET. This last insn will have a REQ_EQUAL
-+ note with an operand of EQUIV.
-+
-+ Moving assignments to pseudos outside of the block is done to improve
-+ the generated code, but is not required to generate correct code,
-+ hence being unable to move an assignment is not grounds for not making
-+ a libcall block. There are two reasons why it is safe to leave these
-+ insns inside the block: First, we know that these pseudos cannot be
-+ used in generated RTL outside the block since they are created for
-+ temporary purposes within the block. Second, CSE will not record the
-+ values of anything set inside a libcall block, so we know they must
-+ be dead at the end of the block.
-+
-+ Except for the first group of insns (the ones setting pseudos), the
-+ block is delimited by REG_RETVAL and REG_LIBCALL notes. */
-+
-+void
-+emit_libcall_block (insns, target, result, equiv)
-+ rtx insns;
-+ rtx target;
-+ rtx result;
-+ rtx equiv;
-+{
-+ rtx final_dest = target;
-+ rtx prev, next, first, last, insn;
-+
-+ /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
-+ into a MEM later. Protect the libcall block from this change. */
-+ if (! REG_P (target) || REG_USERVAR_P (target))
-+ target = gen_reg_rtx (GET_MODE (target));
-+
-+ /* If we're using non-call exceptions, a libcall corresponding to an
-+ operation that may trap may also trap. */
-+ if (flag_non_call_exceptions && may_trap_p (equiv))
-+ {
-+ for (insn = insns; insn; insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) == CALL_INSN)
-+ {
-+ rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-+
-+ if (note != 0 && INTVAL (XEXP (note, 0)) <= 0)
-+ remove_note (insn, note);
-+ }
-+ }
-+ else
-+ /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
-+ reg note to indicate that this call cannot throw or execute a nonlocal
-+ goto (unless there is already a REG_EH_REGION note, in which case
-+ we update it). */
-+ for (insn = insns; insn; insn = NEXT_INSN (insn))
-+ if (GET_CODE (insn) == CALL_INSN)
-+ {
-+ rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-+
-+ if (note != 0)
-+ XEXP (note, 0) = GEN_INT (-1);
-+ else
-+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (-1),
-+ REG_NOTES (insn));
-+ }
-+
-+ /* First emit all insns that set pseudos. Remove them from the list as
-+ we go. Avoid insns that set pseudos which were referenced in previous
-+ insns. These can be generated by move_by_pieces, for example,
-+ to update an address. Similarly, avoid insns that reference things
-+ set in previous insns. */
-+
-+ for (insn = insns; insn; insn = next)
-+ {
-+ rtx set = single_set (insn);
-+ rtx note;
-+
-+ /* Some ports (cris) create an libcall regions at their own. We must
-+ avoid any potential nesting of LIBCALLs. */
-+ if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
-+ remove_note (insn, note);
-+ if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
-+ remove_note (insn, note);
-+
-+ next = NEXT_INSN (insn);
-+
-+ if (set != 0 && GET_CODE (SET_DEST (set)) == REG
-+ && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
-+ && (insn == insns
-+ || ((! INSN_P(insns)
-+ || ! reg_mentioned_p (SET_DEST (set), PATTERN (insns)))
-+ && ! reg_used_between_p (SET_DEST (set), insns, insn)
-+ && ! modified_in_p (SET_SRC (set), insns)
-+ && ! modified_between_p (SET_SRC (set), insns, insn))))
-+ {
-+ if (PREV_INSN (insn))
-+ NEXT_INSN (PREV_INSN (insn)) = next;
-+ else
-+ insns = next;
-+
-+ if (next)
-+ PREV_INSN (next) = PREV_INSN (insn);
-+
-+ add_insn (insn);
-+ }
-+ }
-+
-+ prev = get_last_insn ();
-+
-+ /* Write the remaining insns followed by the final copy. */
-+
-+ for (insn = insns; insn; insn = next)
-+ {
-+ next = NEXT_INSN (insn);
-+
-+ add_insn (insn);
-+ }
-+
-+ last = emit_move_insn (target, result);
-+ if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
-+ != CODE_FOR_nothing)
-+ set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
-+ else
-+ {
-+ /* Remove any existing REG_EQUAL note from "last", or else it will
-+ be mistaken for a note referring to the full contents of the
-+ libcall value when found together with the REG_RETVAL note added
-+ below. An existing note can come from an insn expansion at
-+ "last". */
-+ remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
-+ }
-+
-+ if (final_dest != target)
-+ emit_move_insn (final_dest, target);
-+
-+ if (prev == 0)
-+ first = get_insns ();
-+ else
-+ first = NEXT_INSN (prev);
-+
-+ /* Encapsulate the block so it gets manipulated as a unit. */
-+ if (!flag_non_call_exceptions || !may_trap_p (equiv))
-+ {
-+ /* We can't attach the REG_LIBCALL and REG_RETVAL notes
-+ when the encapsulated region would not be in one basic block,
-+ i.e. when there is a control_flow_insn_p insn between FIRST and LAST.
-+ */
-+ bool attach_libcall_retval_notes = true;
-+ next = NEXT_INSN (last);
-+ for (insn = first; insn != next; insn = NEXT_INSN (insn))
-+ if (control_flow_insn_p (insn))
-+ {
-+ attach_libcall_retval_notes = false;
-+ break;
-+ }
-+
-+ if (attach_libcall_retval_notes)
-+ {
-+ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
-+ REG_NOTES (first));
-+ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
-+ REG_NOTES (last));
-+ }
-+ }
-+}
-+\f
-+/* Generate code to store zero in X. */
-+
-+void
-+emit_clr_insn (x)
-+ rtx x;
-+{
-+ emit_move_insn (x, const0_rtx);
-+}
-+
-+/* Generate code to store 1 in X
-+ assuming it contains zero beforehand. */
-+
-+void
-+emit_0_to_1_insn (x)
-+ rtx x;
-+{
-+ emit_move_insn (x, const1_rtx);
-+}
-+
-+/* Nonzero if we can perform a comparison of mode MODE straightforwardly.
-+ PURPOSE describes how this comparison will be used. CODE is the rtx
-+ comparison code we will be using.
-+
-+ ??? Actually, CODE is slightly weaker than that. A target is still
-+ required to implement all of the normal bcc operations, but not
-+ required to implement all (or any) of the unordered bcc operations. */
-+
-+int
-+can_compare_p (code, mode, purpose)
-+ enum rtx_code code;
-+ enum machine_mode mode;
-+ enum can_compare_purpose purpose;
-+{
-+ do
-+ {
-+ if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ {
-+ if (purpose == ccp_jump)
-+ return bcc_gen_fctn[(int) code] != NULL;
-+ else if (purpose == ccp_store_flag)
-+ return setcc_gen_code[(int) code] != CODE_FOR_nothing;
-+ else
-+ /* There's only one cmov entry point, and it's allowed to fail. */
-+ return 1;
-+ }
-+ if (purpose == ccp_jump
-+ && cbranch_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ return 1;
-+ if (purpose == ccp_cmov
-+ && cmov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ return 1;
-+ if (purpose == ccp_store_flag
-+ && cstore_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
-+ return 1;
-+
-+ mode = GET_MODE_WIDER_MODE (mode);
-+ }
-+ while (mode != VOIDmode);
-+
-+ return 0;
-+}
-+
-+/* This function is called when we are going to emit a compare instruction that
-+ compares the values found in *PX and *PY, using the rtl operator COMPARISON.
-+
-+ *PMODE is the mode of the inputs (in case they are const_int).
-+ *PUNSIGNEDP nonzero says that the operands are unsigned;
-+ this matters if they need to be widened.
-+
-+ If they have mode BLKmode, then SIZE specifies the size of both operands.
-+
-+ This function performs all the setup necessary so that the caller only has
-+ to emit a single comparison insn. This setup can involve doing a BLKmode
-+ comparison or emitting a library call to perform the comparison if no insn
-+ is available to handle it.
-+ The values which are passed in through pointers can be modified; the caller
-+ should perform the comparison on the modified values. */
-+
-+static void
-+prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, purpose)
-+ rtx *px, *py;
-+ enum rtx_code *pcomparison;
-+ rtx size;
-+ enum machine_mode *pmode;
-+ int *punsignedp;
-+ enum can_compare_purpose purpose;
-+{
-+ enum machine_mode mode = *pmode;
-+ rtx x = *px, y = *py;
-+ int unsignedp = *punsignedp;
-+ enum mode_class class;
-+
-+ class = GET_MODE_CLASS (mode);
-+
-+ /* They could both be VOIDmode if both args are immediate constants,
-+ but we should fold that at an earlier stage.
-+ With no special code here, this will call abort,
-+ reminding the programmer to implement such folding. */
-+
-+ if (mode != BLKmode && flag_force_mem)
-+ {
-+ x = force_not_mem (x);
-+ y = force_not_mem (y);
-+ }
-+
-+ /* If we are inside an appropriately-short loop and one operand is an
-+ expensive constant, force it into a register. */
-+ if (CONSTANT_P (x) && preserve_subexpressions_p ()
-+ && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
-+ x = force_reg (mode, x);
-+
-+ if (CONSTANT_P (y) && preserve_subexpressions_p ()
-+ && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
-+ y = force_reg (mode, y);
-+
-+#ifdef HAVE_cc0
-+ /* Abort if we have a non-canonical comparison. The RTL documentation
-+ states that canonical comparisons are required only for targets which
-+ have cc0. */
-+ if (CONSTANT_P (x) && ! CONSTANT_P (y))
-+ abort ();
-+#endif
-+
-+ /* Don't let both operands fail to indicate the mode. */
-+ if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
-+ x = force_reg (mode, x);
-+
-+ /* Handle all BLKmode compares. */
-+
-+ if (mode == BLKmode)
-+ {
-+ rtx result;
-+ enum machine_mode result_mode;
-+ rtx opalign ATTRIBUTE_UNUSED
-+ = GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
-+
-+ emit_queue ();
-+ x = protect_from_queue (x, 0);
-+ y = protect_from_queue (y, 0);
-+
-+ if (size == 0)
-+ abort ();
-+#ifdef HAVE_cmpstrqi
-+ if (HAVE_cmpstrqi
-+ && GET_CODE (size) == CONST_INT
-+ && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
-+ {
-+ result_mode = insn_data[(int) CODE_FOR_cmpstrqi].operand[0].mode;
-+ result = gen_reg_rtx (result_mode);
-+ emit_insn (gen_cmpstrqi (result, x, y, size, opalign));
-+ }
-+ else
-+#endif
-+#ifdef HAVE_cmpstrhi
-+ if (HAVE_cmpstrhi
-+ && GET_CODE (size) == CONST_INT
-+ && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
-+ {
-+ result_mode = insn_data[(int) CODE_FOR_cmpstrhi].operand[0].mode;
-+ result = gen_reg_rtx (result_mode);
-+ emit_insn (gen_cmpstrhi (result, x, y, size, opalign));
-+ }
-+ else
-+#endif
-+#ifdef HAVE_cmpstrsi
-+ if (HAVE_cmpstrsi)
-+ {
-+ result_mode = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
-+ result = gen_reg_rtx (result_mode);
-+ size = protect_from_queue (size, 0);
-+ emit_insn (gen_cmpstrsi (result, x, y,
-+ convert_to_mode (SImode, size, 1),
-+ opalign));
-+ }
-+ else
-+#endif
-+ {
-+#ifdef TARGET_MEM_FUNCTIONS
-+ result = emit_library_call_value (memcmp_libfunc, NULL_RTX, LCT_PURE_MAKE_BLOCK,
-+ TYPE_MODE (integer_type_node), 3,
-+ XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
-+ convert_to_mode (TYPE_MODE (sizetype), size,
-+ TREE_UNSIGNED (sizetype)),
-+ TYPE_MODE (sizetype));
-+#else
-+ result = emit_library_call_value (bcmp_libfunc, NULL_RTX, LCT_PURE_MAKE_BLOCK,
-+ TYPE_MODE (integer_type_node), 3,
-+ XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
-+ convert_to_mode (TYPE_MODE (integer_type_node),
-+ size,
-+ TREE_UNSIGNED (integer_type_node)),
-+ TYPE_MODE (integer_type_node));
-+#endif
-+
-+ result_mode = TYPE_MODE (integer_type_node);
-+ }
-+ *px = result;
-+ *py = const0_rtx;
-+ *pmode = result_mode;
-+ return;
-+ }
-+
-+ *px = x;
-+ *py = y;
-+ if (can_compare_p (*pcomparison, mode, purpose))
-+ return;
-+
-+ /* Handle a lib call just for the mode we are using. */
-+
-+ if (cmp_optab->handlers[(int) mode].libfunc && class != MODE_FLOAT)
-+ {
-+ rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
-+ rtx result;
-+
-+ /* If we want unsigned, and this mode has a distinct unsigned
-+ comparison routine, use that. */
-+ if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
-+ libfunc = ucmp_optab->handlers[(int) mode].libfunc;
-+
-+ result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
-+ word_mode, 2, x, mode, y, mode);
-+
-+ /* Integer comparison returns a result that must be compared against 1,
-+ so that even if we do an unsigned compare afterward,
-+ there is still a value that can represent the result "less than". */
-+ *px = result;
-+ *py = const1_rtx;
-+ *pmode = word_mode;
-+ return;
-+ }
-+
-+ if (class == MODE_FLOAT)
-+ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
-+
-+ else
-+ abort ();
-+}
-+
-+/* Before emitting an insn with code ICODE, make sure that X, which is going
-+ to be used for operand OPNUM of the insn, is converted from mode MODE to
-+ WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
-+ that it is accepted by the operand predicate. Return the new value. */
-+
-+rtx
-+prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp)
-+ int icode;
-+ rtx x;
-+ int opnum;
-+ enum machine_mode mode, wider_mode;
-+ int unsignedp;
-+{
-+ x = protect_from_queue (x, 0);
-+
-+ if (mode != wider_mode)
-+ x = convert_modes (wider_mode, mode, x, unsignedp);
-+
-+ if (! (*insn_data[icode].operand[opnum].predicate)
-+ (x, insn_data[icode].operand[opnum].mode))
-+ {
-+ if (no_new_pseudos)
-+ return NULL_RTX;
-+ x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
-+ }
-+
-+ return x;
-+}
-+
-+/* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
-+ we can do the comparison.
-+ The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
-+ be NULL_RTX which indicates that only a comparison is to be generated. */
-+
-+static void
-+emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
-+ rtx x, y;
-+ enum machine_mode mode;
-+ enum rtx_code comparison;
-+ int unsignedp;
-+ rtx label;
-+{
-+ rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
-+ enum mode_class class = GET_MODE_CLASS (mode);
-+ enum machine_mode wider_mode = mode;
-+
-+ /* Try combined insns first. */
-+ do
-+ {
-+ enum insn_code icode;
-+ PUT_MODE (test, wider_mode);
-+
-+ if (label)
-+ {
-+ icode = cbranch_optab->handlers[(int) wider_mode].insn_code;
-+
-+ if (icode != CODE_FOR_nothing
-+ && (*insn_data[icode].operand[0].predicate) (test, wider_mode))
-+ {
-+ x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
-+ y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
-+ emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
-+ return;
-+ }
-+ }
-+
-+ /* Handle some compares against zero. */
-+ icode = (int) tst_optab->handlers[(int) wider_mode].insn_code;
-+ if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
-+ {
-+ x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
-+ emit_insn (GEN_FCN (icode) (x));
-+ if (label)
-+ emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
-+ return;
-+ }
-+
-+ /* Handle compares for which there is a directly suitable insn. */
-+
-+ icode = (int) cmp_optab->handlers[(int) wider_mode].insn_code;
-+ if (icode != CODE_FOR_nothing)
-+ {
-+ x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
-+ y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp);
-+ emit_insn (GEN_FCN (icode) (x, y));
-+ if (label)
-+ emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
-+ return;
-+ }
-+
-+ if (class != MODE_INT && class != MODE_FLOAT
-+ && class != MODE_COMPLEX_FLOAT)
-+ break;
-+
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode);
-+ }
-+ while (wider_mode != VOIDmode);
-+
-+ abort ();
-+}
-+
-+/* Generate code to compare X with Y so that the condition codes are
-+ set and to jump to LABEL if the condition is true. If X is a
-+ constant and Y is not a constant, then the comparison is swapped to
-+ ensure that the comparison RTL has the canonical form.
-+
-+ UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
-+ need to be widened by emit_cmp_insn. UNSIGNEDP is also used to select
-+ the proper branch condition code.
-+
-+ If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
-+
-+ MODE is the mode of the inputs (in case they are const_int).
-+
-+ COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). It will
-+ be passed unchanged to emit_cmp_insn, then potentially converted into an
-+ unsigned variant based on UNSIGNEDP to select a proper jump instruction. */
-+
-+void
-+emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, label)
-+ rtx x, y;
-+ enum rtx_code comparison;
-+ rtx size;
-+ enum machine_mode mode;
-+ int unsignedp;
-+ rtx label;
-+{
-+ rtx op0 = x, op1 = y;
-+
-+ /* Swap operands and condition to ensure canonical RTL. */
-+ if (swap_commutative_operands_p (x, y))
-+ {
-+ /* If we're not emitting a branch, this means some caller
-+ is out of sync. */
-+ if (! label)
-+ abort ();
-+
-+ op0 = y, op1 = x;
-+ comparison = swap_condition (comparison);
-+ }
-+
-+#ifdef HAVE_cc0
-+ /* If OP0 is still a constant, then both X and Y must be constants. Force
-+ X into a register to avoid aborting in emit_cmp_insn due to non-canonical
-+ RTL. */
-+ if (CONSTANT_P (op0))
-+ op0 = force_reg (mode, op0);
-+#endif
-+
-+ emit_queue ();
-+ if (unsignedp)
-+ comparison = unsigned_condition (comparison);
-+
-+ prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp,
-+ ccp_jump);
-+ emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
-+}
-+
-+/* Like emit_cmp_and_jump_insns, but generate only the comparison. */
-+
-+void
-+emit_cmp_insn (x, y, comparison, size, mode, unsignedp)
-+ rtx x, y;
-+ enum rtx_code comparison;
-+ rtx size;
-+ enum machine_mode mode;
-+ int unsignedp;
-+{
-+ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, 0);
-+}
-+\f
-+/* Emit a library call comparison between floating point X and Y.
-+ COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.). */
-+
-+static void
-+prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp)
-+ rtx *px, *py;
-+ enum rtx_code *pcomparison;
-+ enum machine_mode *pmode;
-+ int *punsignedp;
-+{
-+ enum rtx_code comparison = *pcomparison;
-+ rtx tmp;
-+ rtx x = *px = protect_from_queue (*px, 0);
-+ rtx y = *py = protect_from_queue (*py, 0);
-+ enum machine_mode mode = GET_MODE (x);
-+ rtx libfunc = 0;
-+ rtx result;
-+
-+ if (mode == HFmode)
-+ switch (comparison)
-+ {
-+ case EQ:
-+ libfunc = eqhf2_libfunc;
-+ break;
-+
-+ case NE:
-+ libfunc = nehf2_libfunc;
-+ break;
-+
-+ case GT:
-+ libfunc = gthf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LT;
-+ libfunc = lthf2_libfunc;
-+ }
-+ break;
-+
-+ case GE:
-+ libfunc = gehf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LE;
-+ libfunc = lehf2_libfunc;
-+ }
-+ break;
-+
-+ case LT:
-+ libfunc = lthf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GT;
-+ libfunc = gthf2_libfunc;
-+ }
-+ break;
-+
-+ case LE:
-+ libfunc = lehf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GE;
-+ libfunc = gehf2_libfunc;
-+ }
-+ break;
-+
-+ case UNORDERED:
-+ libfunc = unordhf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ else if (mode == SFmode)
-+ switch (comparison)
-+ {
-+ case EQ:
-+ libfunc = eqsf2_libfunc;
-+ break;
-+
-+ case NE:
-+ libfunc = nesf2_libfunc;
-+ break;
-+
-+ case GT:
-+ libfunc = gtsf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LT;
-+ libfunc = ltsf2_libfunc;
-+ }
-+ break;
-+
-+ case GE:
-+ libfunc = gesf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LE;
-+ libfunc = lesf2_libfunc;
-+ }
-+ break;
-+
-+ case LT:
-+ libfunc = ltsf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GT;
-+ libfunc = gtsf2_libfunc;
-+ }
-+ break;
-+
-+ case LE:
-+ libfunc = lesf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GE;
-+ libfunc = gesf2_libfunc;
-+ }
-+ break;
-+
-+ case UNORDERED:
-+ libfunc = unordsf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ else if (mode == DFmode)
-+ switch (comparison)
-+ {
-+ case EQ:
-+ libfunc = eqdf2_libfunc;
-+ break;
-+
-+ case NE:
-+ libfunc = nedf2_libfunc;
-+ break;
-+
-+ case GT:
-+ libfunc = gtdf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LT;
-+ libfunc = ltdf2_libfunc;
-+ }
-+ break;
-+
-+ case GE:
-+ libfunc = gedf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LE;
-+ libfunc = ledf2_libfunc;
-+ }
-+ break;
-+
-+ case LT:
-+ libfunc = ltdf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GT;
-+ libfunc = gtdf2_libfunc;
-+ }
-+ break;
-+
-+ case LE:
-+ libfunc = ledf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GE;
-+ libfunc = gedf2_libfunc;
-+ }
-+ break;
-+
-+ case UNORDERED:
-+ libfunc = unorddf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ else if (mode == XFmode)
-+ switch (comparison)
-+ {
-+ case EQ:
-+ libfunc = eqxf2_libfunc;
-+ break;
-+
-+ case NE:
-+ libfunc = nexf2_libfunc;
-+ break;
-+
-+ case GT:
-+ libfunc = gtxf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LT;
-+ libfunc = ltxf2_libfunc;
-+ }
-+ break;
-+
-+ case GE:
-+ libfunc = gexf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LE;
-+ libfunc = lexf2_libfunc;
-+ }
-+ break;
-+
-+ case LT:
-+ libfunc = ltxf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GT;
-+ libfunc = gtxf2_libfunc;
-+ }
-+ break;
-+
-+ case LE:
-+ libfunc = lexf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GE;
-+ libfunc = gexf2_libfunc;
-+ }
-+ break;
-+
-+ case UNORDERED:
-+ libfunc = unordxf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ else if (mode == TFmode)
-+ switch (comparison)
-+ {
-+ case EQ:
-+ libfunc = eqtf2_libfunc;
-+ break;
-+
-+ case NE:
-+ libfunc = netf2_libfunc;
-+ break;
-+
-+ case GT:
-+ libfunc = gttf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LT;
-+ libfunc = lttf2_libfunc;
-+ }
-+ break;
-+
-+ case GE:
-+ libfunc = getf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = LE;
-+ libfunc = letf2_libfunc;
-+ }
-+ break;
-+
-+ case LT:
-+ libfunc = lttf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GT;
-+ libfunc = gttf2_libfunc;
-+ }
-+ break;
-+
-+ case LE:
-+ libfunc = letf2_libfunc;
-+ if (libfunc == NULL_RTX)
-+ {
-+ tmp = x; x = y; y = tmp;
-+ *pcomparison = GE;
-+ libfunc = getf2_libfunc;
-+ }
-+ break;
-+
-+ case UNORDERED:
-+ libfunc = unordtf2_libfunc;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ else
-+ {
-+ enum machine_mode wider_mode;
-+
-+ for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
-+ wider_mode = GET_MODE_WIDER_MODE (wider_mode))
-+ {
-+ if ((cmp_optab->handlers[(int) wider_mode].insn_code
-+ != CODE_FOR_nothing)
-+ || (cmp_optab->handlers[(int) wider_mode].libfunc != 0))
-+ {
-+ x = protect_from_queue (x, 0);
-+ y = protect_from_queue (y, 0);
-+ *px = convert_to_mode (wider_mode, x, 0);
-+ *py = convert_to_mode (wider_mode, y, 0);
-+ prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
-+ return;
-+ }
-+ }
-+ abort ();
-+ }
-+
-+ if (libfunc == 0)
-+ abort ();
-+
-+ result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
-+ word_mode, 2, x, mode, y, mode);
-+ *px = result;
-+ *py = const0_rtx;
-+ *pmode = word_mode;
-+ if (comparison == UNORDERED)
-+ *pcomparison = NE;
-+#ifdef FLOAT_LIB_COMPARE_RETURNS_BOOL
-+ else if (FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
-+ *pcomparison = NE;
-+#endif
-+ *punsignedp = 0;
-+}
-+\f
-+/* Generate code to indirectly jump to a location given in the rtx LOC. */
-+
-+void
-+emit_indirect_jump (loc)
-+ rtx loc;
-+{
-+ if (! ((*insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate)
-+ (loc, Pmode)))
-+ loc = copy_to_mode_reg (Pmode, loc);
-+
-+ emit_jump_insn (gen_indirect_jump (loc));
-+ emit_barrier ();
-+}
-+\f
-+#ifdef HAVE_conditional_move
-+
-+/* Emit a conditional move instruction if the machine supports one for that
-+ condition and machine mode.
-+
-+ OP0 and OP1 are the operands that should be compared using CODE. CMODE is
-+ the mode to use should they be constants. If it is VOIDmode, they cannot
-+ both be constants.
-+
-+ OP2 should be stored in TARGET if the comparison is true, otherwise OP3
-+ should be stored there. MODE is the mode to use should they be constants.
-+ If it is VOIDmode, they cannot both be constants.
-+
-+ The result is either TARGET (perhaps modified) or NULL_RTX if the operation
-+ is not supported. */
-+
-+rtx
-+emit_conditional_move (target, code, op0, op1, cmode, op2, op3, mode,
-+ unsignedp)
-+ rtx target;
-+ enum rtx_code code;
-+ rtx op0, op1;
-+ enum machine_mode cmode;
-+ rtx op2, op3;
-+ enum machine_mode mode;
-+ int unsignedp;
-+{
-+ rtx tem, subtarget, comparison, insn;
-+ enum insn_code icode;
-+ enum rtx_code reversed;
-+
-+ /* If one operand is constant, make it the second one. Only do this
-+ if the other operand is not constant as well. */
-+
-+ if (swap_commutative_operands_p (op0, op1))
-+ {
-+ tem = op0;
-+ op0 = op1;
-+ op1 = tem;
-+ code = swap_condition (code);
-+ }
-+
-+ /* get_condition will prefer to generate LT and GT even if the old
-+ comparison was against zero, so undo that canonicalization here since
-+ comparisons against zero are cheaper. */
-+ if (code == LT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == 1)
-+ code = LE, op1 = const0_rtx;
-+ else if (code == GT && GET_CODE (op1) == CONST_INT && INTVAL (op1) == -1)
-+ code = GE, op1 = const0_rtx;
-+
-+ if (cmode == VOIDmode)
-+ cmode = GET_MODE (op0);
-+
-+ if (swap_commutative_operands_p (op2, op3)
-+ && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
-+ != UNKNOWN))
-+ {
-+ tem = op2;
-+ op2 = op3;
-+ op3 = tem;
-+ code = reversed;
-+ }
-+
-+ if (mode == VOIDmode)
-+ mode = GET_MODE (op2);
-+
-+ icode = movcc_gen_code[mode];
-+
-+ if (icode == CODE_FOR_nothing)
-+ return 0;
-+
-+ if (flag_force_mem)
-+ {
-+ op2 = force_not_mem (op2);
-+ op3 = force_not_mem (op3);
-+ }
-+
-+ if (target)
-+ target = protect_from_queue (target, 1);
-+ else
-+ target = gen_reg_rtx (mode);
-+
-+ subtarget = target;
-+
-+ emit_queue ();
-+
-+ op2 = protect_from_queue (op2, 0);
-+ op3 = protect_from_queue (op3, 0);
-+
-+ /* If the insn doesn't accept these operands, put them in pseudos. */
-+
-+ if (! (*insn_data[icode].operand[0].predicate)
-+ (subtarget, insn_data[icode].operand[0].mode))
-+ subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
-+
-+ if (! (*insn_data[icode].operand[2].predicate)
-+ (op2, insn_data[icode].operand[2].mode))
-+ op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
-+
-+ if (! (*insn_data[icode].operand[3].predicate)
-+ (op3, insn_data[icode].operand[3].mode))
-+ op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
-+
-+ /* Everything should now be in the suitable form, so emit the compare insn
-+ and then the conditional move. */
-+
-+ comparison
-+ = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);
-+
-+ /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)? */
-+ /* We can get const0_rtx or const_true_rtx in some circumstances. Just
-+ return NULL and let the caller figure out how best to deal with this
-+ situation. */
-+ if (GET_CODE (comparison) != code)
-+ return NULL_RTX;
-+
-+ insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);
-+
-+ /* If that failed, then give up. */
-+ if (insn == 0)
-+ return 0;
-+
-+ emit_insn (insn);
-+
-+ if (subtarget != target)
-+ convert_move (target, subtarget, 0);
-+
-+ return target;
-+}
-+
-+/* Return nonzero if a conditional move of mode MODE is supported.
-+
-+ This function is for combine so it can tell whether an insn that looks
-+ like a conditional move is actually supported by the hardware. If we
-+ guess wrong we lose a bit on optimization, but that's it. */
-+/* ??? sparc64 supports conditionally moving integers values based on fp
-+ comparisons, and vice versa. How do we handle them? */
-+
-+int
-+can_conditionally_move_p (mode)
-+ enum machine_mode mode;
-+{
-+ if (movcc_gen_code[mode] != CODE_FOR_nothing)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+#endif /* HAVE_conditional_move */
-+\f
-+/* These functions generate an insn body and return it
-+ rather than emitting the insn.
-+
-+ They do not protect from queued increments,
-+ because they may be used 1) in protect_from_queue itself
-+ and 2) in other passes where there is no queue. */
-+
-+/* Generate and return an insn body to add Y to X. */
-+
-+rtx
-+gen_add2_insn (x, y)
-+ rtx x, y;
-+{
-+ int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
-+
-+ if (! ((*insn_data[icode].operand[0].predicate)
-+ (x, insn_data[icode].operand[0].mode))
-+ || ! ((*insn_data[icode].operand[1].predicate)
-+ (x, insn_data[icode].operand[1].mode))
-+ || ! ((*insn_data[icode].operand[2].predicate)
-+ (y, insn_data[icode].operand[2].mode)))
-+ abort ();
-+
-+ return (GEN_FCN (icode) (x, x, y));
-+}
-+
-+/* Generate and return an insn body to add r1 and c,
-+ storing the result in r0. */
-+rtx
-+gen_add3_insn (r0, r1, c)
-+ rtx r0, r1, c;
-+{
-+ int icode = (int) add_optab->handlers[(int) GET_MODE (r0)].insn_code;
-+
-+ if (icode == CODE_FOR_nothing
-+ || ! ((*insn_data[icode].operand[0].predicate)
-+ (r0, insn_data[icode].operand[0].mode))
-+ || ! ((*insn_data[icode].operand[1].predicate)
-+ (r1, insn_data[icode].operand[1].mode))
-+ || ! ((*insn_data[icode].operand[2].predicate)
-+ (c, insn_data[icode].operand[2].mode)))
-+ return NULL_RTX;
-+
-+ return (GEN_FCN (icode) (r0, r1, c));
-+}
-+
-+int
-+have_add2_insn (x, y)
-+ rtx x, y;
-+{
-+ int icode;
-+
-+ if (GET_MODE (x) == VOIDmode)
-+ abort ();
-+
-+ icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
-+
-+ if (icode == CODE_FOR_nothing)
-+ return 0;
-+
-+ if (! ((*insn_data[icode].operand[0].predicate)
-+ (x, insn_data[icode].operand[0].mode))
-+ || ! ((*insn_data[icode].operand[1].predicate)
-+ (x, insn_data[icode].operand[1].mode))
-+ || ! ((*insn_data[icode].operand[2].predicate)
-+ (y, insn_data[icode].operand[2].mode)))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/* Generate and return an insn body to subtract Y from X. */
-+
-+rtx
-+gen_sub2_insn (x, y)
-+ rtx x, y;
-+{
-+ int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
-+
-+ if (! ((*insn_data[icode].operand[0].predicate)
-+ (x, insn_data[icode].operand[0].mode))
-+ || ! ((*insn_data[icode].operand[1].predicate)
-+ (x, insn_data[icode].operand[1].mode))
-+ || ! ((*insn_data[icode].operand[2].predicate)
-+ (y, insn_data[icode].operand[2].mode)))
-+ abort ();
-+
-+ return (GEN_FCN (icode) (x, x, y));
-+}
-+
-+/* Generate and return an insn body to subtract r1 and c,
-+ storing the result in r0. */
-+rtx
-+gen_sub3_insn (r0, r1, c)
-+ rtx r0, r1, c;
-+{
-+ int icode = (int) sub_optab->handlers[(int) GET_MODE (r0)].insn_code;
-+
-+ if (icode == CODE_FOR_nothing
-+ || ! ((*insn_data[icode].operand[0].predicate)
-+ (r0, insn_data[icode].operand[0].mode))
-+ || ! ((*insn_data[icode].operand[1].predicate)
-+ (r1, insn_data[icode].operand[1].mode))
-+ || ! ((*insn_data[icode].operand[2].predicate)
-+ (c, insn_data[icode].operand[2].mode)))
-+ return NULL_RTX;
-+
-+ return (GEN_FCN (icode) (r0, r1, c));
-+}
-+
-+int
-+have_sub2_insn (x, y)
-+ rtx x, y;
-+{
-+ int icode;
-+
-+ if (GET_MODE (x) == VOIDmode)
-+ abort ();
-+
-+ icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
-+
-+ if (icode == CODE_FOR_nothing)
-+ return 0;
-+
-+ if (! ((*insn_data[icode].operand[0].predicate)
-+ (x, insn_data[icode].operand[0].mode))
-+ || ! ((*insn_data[icode].operand[1].predicate)
-+ (x, insn_data[icode].operand[1].mode))
-+ || ! ((*insn_data[icode].operand[2].predicate)
-+ (y, insn_data[icode].operand[2].mode)))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+/* Generate the body of an instruction to copy Y into X.
-+ It may be a list of insns, if one insn isn't enough. */
-+
-+rtx
-+gen_move_insn (x, y)
-+ rtx x, y;
-+{
-+ enum machine_mode mode = GET_MODE (x);
-+ enum insn_code insn_code;
-+ rtx seq;
-+
-+ if (mode == VOIDmode)
-+ mode = GET_MODE (y);
-+
-+ insn_code = mov_optab->handlers[(int) mode].insn_code;
-+
-+ /* Handle MODE_CC modes: If we don't have a special move insn for this mode,
-+ find a mode to do it in. If we have a movcc, use it. Otherwise,
-+ find the MODE_INT mode of the same width. */
-+
-+ if (GET_MODE_CLASS (mode) == MODE_CC && insn_code == CODE_FOR_nothing)
-+ {
-+ enum machine_mode tmode = VOIDmode;
-+ rtx x1 = x, y1 = y;
-+
-+ if (mode != CCmode
-+ && mov_optab->handlers[(int) CCmode].insn_code != CODE_FOR_nothing)
-+ tmode = CCmode;
-+ else
-+ for (tmode = QImode; tmode != VOIDmode;
-+ tmode = GET_MODE_WIDER_MODE (tmode))
-+ if (GET_MODE_SIZE (tmode) == GET_MODE_SIZE (mode))
-+ break;
-+
-+ if (tmode == VOIDmode)
-+ abort ();
-+
-+ /* Get X and Y in TMODE. We can't use gen_lowpart here because it
-+ may call change_address which is not appropriate if we were
-+ called when a reload was in progress. We don't have to worry
-+ about changing the address since the size in bytes is supposed to
-+ be the same. Copy the MEM to change the mode and move any
-+ substitutions from the old MEM to the new one. */
-+
-+ if (reload_in_progress)
-+ {
-+ x = gen_lowpart_common (tmode, x1);
-+ if (x == 0 && GET_CODE (x1) == MEM)
-+ {
-+ x = adjust_address_nv (x1, tmode, 0);
-+ copy_replacements (x1, x);
-+ }
-+
-+ y = gen_lowpart_common (tmode, y1);
-+ if (y == 0 && GET_CODE (y1) == MEM)
-+ {
-+ y = adjust_address_nv (y1, tmode, 0);
-+ copy_replacements (y1, y);
-+ }
-+ }
-+ else
-+ {
-+ x = gen_lowpart (tmode, x);
-+ y = gen_lowpart (tmode, y);
-+ }
-+
-+ insn_code = mov_optab->handlers[(int) tmode].insn_code;
-+ return (GEN_FCN (insn_code) (x, y));
-+ }
-+
-+ start_sequence ();
-+ emit_move_insn_1 (x, y);
-+ seq = get_insns ();
-+ end_sequence ();
-+ return seq;
-+}
-+\f
-+/* Return the insn code used to extend FROM_MODE to TO_MODE.
-+ UNSIGNEDP specifies zero-extension instead of sign-extension. If
-+ no such operation exists, CODE_FOR_nothing will be returned. */
-+
-+enum insn_code
-+can_extend_p (to_mode, from_mode, unsignedp)
-+ enum machine_mode to_mode, from_mode;
-+ int unsignedp;
-+{
-+#ifdef HAVE_ptr_extend
-+ if (unsignedp < 0)
-+ return CODE_FOR_ptr_extend;
-+ else
-+#endif
-+ return extendtab[(int) to_mode][(int) from_mode][unsignedp != 0];
-+}
-+
-+/* Generate the body of an insn to extend Y (with mode MFROM)
-+ into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
-+
-+rtx
-+gen_extend_insn (x, y, mto, mfrom, unsignedp)
-+ rtx x, y;
-+ enum machine_mode mto, mfrom;
-+ int unsignedp;
-+{
-+ return (GEN_FCN (extendtab[(int) mto][(int) mfrom][unsignedp != 0]) (x, y));
-+}
-+\f
-+/* can_fix_p and can_float_p say whether the target machine
-+ can directly convert a given fixed point type to
-+ a given floating point type, or vice versa.
-+ The returned value is the CODE_FOR_... value to use,
-+ or CODE_FOR_nothing if these modes cannot be directly converted.
-+
-+ *TRUNCP_PTR is set to 1 if it is necessary to output
-+ an explicit FTRUNC insn before the fix insn; otherwise 0. */
-+
-+static enum insn_code
-+can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
-+ enum machine_mode fltmode, fixmode;
-+ int unsignedp;
-+ int *truncp_ptr;
-+{
-+ *truncp_ptr = 0;
-+ if (fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0]
-+ != CODE_FOR_nothing)
-+ return fixtrunctab[(int) fltmode][(int) fixmode][unsignedp != 0];
-+
-+ if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
-+ {
-+ *truncp_ptr = 1;
-+ return fixtab[(int) fltmode][(int) fixmode][unsignedp != 0];
-+ }
-+ return CODE_FOR_nothing;
-+}
-+
-+static enum insn_code
-+can_float_p (fltmode, fixmode, unsignedp)
-+ enum machine_mode fixmode, fltmode;
-+ int unsignedp;
-+{
-+ return floattab[(int) fltmode][(int) fixmode][unsignedp != 0];
-+}
-+\f
-+/* Generate code to convert FROM to floating point
-+ and store in TO. FROM must be fixed point and not VOIDmode.
-+ UNSIGNEDP nonzero means regard FROM as unsigned.
-+ Normally this is done by correcting the final value
-+ if it is negative. */
-+
-+void
-+expand_float (to, from, unsignedp)
-+ rtx to, from;
-+ int unsignedp;
-+{
-+ enum insn_code icode;
-+ rtx target = to;
-+ enum machine_mode fmode, imode;
-+
-+ /* Crash now, because we won't be able to decide which mode to use. */
-+ if (GET_MODE (from) == VOIDmode)
-+ abort ();
-+
-+ /* Look for an insn to do the conversion. Do it in the specified
-+ modes if possible; otherwise convert either input, output or both to
-+ wider mode. If the integer mode is wider than the mode of FROM,
-+ we can do the conversion signed even if the input is unsigned. */
-+
-+ for (fmode = GET_MODE (to); fmode != VOIDmode;
-+ fmode = GET_MODE_WIDER_MODE (fmode))
-+ for (imode = GET_MODE (from); imode != VOIDmode;
-+ imode = GET_MODE_WIDER_MODE (imode))
-+ {
-+ int doing_unsigned = unsignedp;
-+
-+ if (fmode != GET_MODE (to)
-+ && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
-+ continue;
-+
-+ icode = can_float_p (fmode, imode, unsignedp);
-+ if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
-+ icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;
-+
-+ if (icode != CODE_FOR_nothing)
-+ {
-+ to = protect_from_queue (to, 1);
-+ from = protect_from_queue (from, 0);
-+
-+ if (imode != GET_MODE (from))
-+ from = convert_to_mode (imode, from, unsignedp);
-+
-+ if (fmode != GET_MODE (to))
-+ target = gen_reg_rtx (fmode);
-+
-+ emit_unop_insn (icode, target, from,
-+ doing_unsigned ? UNSIGNED_FLOAT : FLOAT);
-+
-+ if (target != to)
-+ convert_move (to, target, 0);
-+ return;
-+ }
-+ }
-+
-+ /* Unsigned integer, and no way to convert directly.
-+ Convert as signed, then conditionally adjust the result. */
-+ if (unsignedp)
-+ {
-+ rtx label = gen_label_rtx ();
-+ rtx temp;
-+ REAL_VALUE_TYPE offset;
-+
-+ emit_queue ();
-+
-+ to = protect_from_queue (to, 1);
-+ from = protect_from_queue (from, 0);
-+
-+ if (flag_force_mem)
-+ from = force_not_mem (from);
-+
-+ /* Look for a usable floating mode FMODE wider than the source and at
-+ least as wide as the target. Using FMODE will avoid rounding woes
-+ with unsigned values greater than the signed maximum value. */
-+
-+ for (fmode = GET_MODE (to); fmode != VOIDmode;
-+ fmode = GET_MODE_WIDER_MODE (fmode))
-+ if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
-+ && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
-+ break;
-+
-+ if (fmode == VOIDmode)
-+ {
-+ /* There is no such mode. Pretend the target is wide enough. */
-+ fmode = GET_MODE (to);
-+
-+ /* Avoid double-rounding when TO is narrower than FROM. */
-+ if ((significand_size (fmode) + 1)
-+ < GET_MODE_BITSIZE (GET_MODE (from)))
-+ {
-+ rtx temp1;
-+ rtx neglabel = gen_label_rtx ();
-+
-+ /* Don't use TARGET if it isn't a register, is a hard register,
-+ or is the wrong mode. */
-+ if (GET_CODE (target) != REG
-+ || REGNO (target) < FIRST_PSEUDO_REGISTER
-+ || GET_MODE (target) != fmode)
-+ target = gen_reg_rtx (fmode);
-+
-+ imode = GET_MODE (from);
-+ do_pending_stack_adjust ();
-+
-+ /* Test whether the sign bit is set. */
-+ emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
-+ 0, neglabel);
-+
-+ /* The sign bit is not set. Convert as signed. */
-+ expand_float (target, from, 0);
-+ emit_jump_insn (gen_jump (label));
-+ emit_barrier ();
-+
-+ /* The sign bit is set.
-+ Convert to a usable (positive signed) value by shifting right
-+ one bit, while remembering if a nonzero bit was shifted
-+ out; i.e., compute (from & 1) | (from >> 1). */
-+
-+ emit_label (neglabel);
-+ temp = expand_binop (imode, and_optab, from, const1_rtx,
-+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
-+ temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
-+ NULL_RTX, 1);
-+ temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
-+ OPTAB_LIB_WIDEN);
-+ expand_float (target, temp, 0);
-+
-+ /* Multiply by 2 to undo the shift above. */
-+ temp = expand_binop (fmode, add_optab, target, target,
-+ target, 0, OPTAB_LIB_WIDEN);
-+ if (temp != target)
-+ emit_move_insn (target, temp);
-+
-+ do_pending_stack_adjust ();
-+ emit_label (label);
-+ goto done;
-+ }
-+ }
-+
-+ /* If we are about to do some arithmetic to correct for an
-+ unsigned operand, do it in a pseudo-register. */
-+
-+ if (GET_MODE (to) != fmode
-+ || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER)
-+ target = gen_reg_rtx (fmode);
-+
-+ /* Convert as signed integer to floating. */
-+ expand_float (target, from, 0);
-+
-+ /* If FROM is negative (and therefore TO is negative),
-+ correct its value by 2**bitwidth. */
-+
-+ do_pending_stack_adjust ();
-+ emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
-+ 0, label);
-+
-+
-+ real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)));
-+ temp = expand_binop (fmode, add_optab, target,
-+ CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
-+ target, 0, OPTAB_LIB_WIDEN);
-+ if (temp != target)
-+ emit_move_insn (target, temp);
-+
-+ do_pending_stack_adjust ();
-+ emit_label (label);
-+ goto done;
-+ }
-+
-+ /* No hardware instruction available; call a library routine to convert from
-+ SImode, DImode, or TImode into SFmode, DFmode, XFmode, or TFmode. */
-+ {
-+ rtx libfcn;
-+ rtx insns;
-+ rtx value;
-+
-+ to = protect_from_queue (to, 1);
-+ from = protect_from_queue (from, 0);
-+
-+ if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
-+ from = convert_to_mode (SImode, from, unsignedp);
-+
-+ if (flag_force_mem)
-+ from = force_not_mem (from);
-+
-+ if (GET_MODE (to) == SFmode)
-+ {
-+ if (GET_MODE (from) == SImode)
-+ libfcn = floatsisf_libfunc;
-+ else if (GET_MODE (from) == DImode)
-+ libfcn = floatdisf_libfunc;
-+ else if (GET_MODE (from) == TImode)
-+ libfcn = floattisf_libfunc;
-+ else
-+ abort ();
-+ }
-+ else if (GET_MODE (to) == DFmode)
-+ {
-+ if (GET_MODE (from) == SImode)
-+ libfcn = floatsidf_libfunc;
-+ else if (GET_MODE (from) == DImode)
-+ libfcn = floatdidf_libfunc;
-+ else if (GET_MODE (from) == TImode)
-+ libfcn = floattidf_libfunc;
-+ else
-+ abort ();
-+ }
-+ else if (GET_MODE (to) == XFmode)
-+ {
-+ if (GET_MODE (from) == SImode)
-+ libfcn = floatsixf_libfunc;
-+ else if (GET_MODE (from) == DImode)
-+ libfcn = floatdixf_libfunc;
-+ else if (GET_MODE (from) == TImode)
-+ libfcn = floattixf_libfunc;
-+ else
-+ abort ();
-+ }
-+ else if (GET_MODE (to) == TFmode)
-+ {
-+ if (GET_MODE (from) == SImode)
-+ libfcn = floatsitf_libfunc;
-+ else if (GET_MODE (from) == DImode)
-+ libfcn = floatditf_libfunc;
-+ else if (GET_MODE (from) == TImode)
-+ libfcn = floattitf_libfunc;
-+ else
-+ abort ();
-+ }
-+ else
-+ abort ();
-+
-+ start_sequence ();
-+
-+ value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
-+ GET_MODE (to), 1, from,
-+ GET_MODE (from));
-+ insns = get_insns ();
-+ end_sequence ();
-+
-+ emit_libcall_block (insns, target, value,
-+ gen_rtx_FLOAT (GET_MODE (to), from));
-+ }
-+
-+ done:
-+
-+ /* Copy result to requested destination
-+ if we have been computing in a temp location. */
-+
-+ if (target != to)
-+ {
-+ if (GET_MODE (target) == GET_MODE (to))
-+ emit_move_insn (to, target);
-+ else
-+ convert_move (to, target, 0);
-+ }
-+}
-+\f
-+/* expand_fix: generate code to convert FROM to fixed point
-+ and store in TO. FROM must be floating point. */
-+
-+static rtx
-+ftruncify (x)
-+ rtx x;
-+{
-+ rtx temp = gen_reg_rtx (GET_MODE (x));
-+ return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
-+}
-+
-+void
-+expand_fix (to, from, unsignedp)
-+ rtx to, from;
-+ int unsignedp;
-+{
-+ enum insn_code icode;
-+ rtx target = to;
-+ enum machine_mode fmode, imode;
-+ int must_trunc = 0;
-+ rtx libfcn = 0;
-+
-+ /* We first try to find a pair of modes, one real and one integer, at
-+ least as wide as FROM and TO, respectively, in which we can open-code
-+ this conversion. If the integer mode is wider than the mode of TO,
-+ we can do the conversion either signed or unsigned. */
-+
-+ for (fmode = GET_MODE (from); fmode != VOIDmode;
-+ fmode = GET_MODE_WIDER_MODE (fmode))
-+ for (imode = GET_MODE (to); imode != VOIDmode;
-+ imode = GET_MODE_WIDER_MODE (imode))
-+ {
-+ int doing_unsigned = unsignedp;
-+
-+ icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
-+ if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
-+ icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;
-+
-+ if (icode != CODE_FOR_nothing)
-+ {
-+ to = protect_from_queue (to, 1);
-+ from = protect_from_queue (from, 0);
-+
-+ if (fmode != GET_MODE (from))
-+ from = convert_to_mode (fmode, from, 0);
-+
-+ if (must_trunc)
-+ from = ftruncify (from);
-+
-+ if (imode != GET_MODE (to))
-+ target = gen_reg_rtx (imode);
-+
-+ emit_unop_insn (icode, target, from,
-+ doing_unsigned ? UNSIGNED_FIX : FIX);
-+ if (target != to)
-+ convert_move (to, target, unsignedp);
-+ return;
-+ }
-+ }
-+
-+ /* For an unsigned conversion, there is one more way to do it.
-+ If we have a signed conversion, we generate code that compares
-+ the real value to the largest representable positive number. If if
-+ is smaller, the conversion is done normally. Otherwise, subtract
-+ one plus the highest signed number, convert, and add it back.
-+
-+ We only need to check all real modes, since we know we didn't find
-+ anything with a wider integer mode. */
-+
-+ if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
-+ for (fmode = GET_MODE (from); fmode != VOIDmode;
-+ fmode = GET_MODE_WIDER_MODE (fmode))
-+ /* Make sure we won't lose significant bits doing this. */
-+ if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
-+ && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
-+ &must_trunc))
+
+ /* Don't count call-insns, (set (reg 0) (call ...)), as a set.
+ The hard function value register is used only once, to copy to
+diff -urN gcc-3.3.1/gcc/explow.c gcc-3.3.1-pp/gcc/explow.c
+--- gcc-3.3.1/gcc/explow.c 2003-04-07 22:58:12.000000000 +0000
++++ gcc-3.3.1-pp/gcc/explow.c 2003-09-12 13:40:28.000000000 +0000
+@@ -86,7 +86,8 @@
+ rtx tem;
+ int all_constant = 0;
+
+- if (c == 0)
++ if (c == 0
++ && !(flag_propolice_protection && x == virtual_stack_vars_rtx))
+ return x;
+
+ restart:
+@@ -187,7 +188,8 @@
+ break;
+ }
+
+- if (c != 0)
++ if (c != 0
++ || (flag_propolice_protection && x == virtual_stack_vars_rtx))
+ x = gen_rtx_PLUS (mode, x, GEN_INT (c));
+
+ if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
+@@ -531,6 +533,21 @@
+ in certain cases. This is not necessary since the code
+ below can handle all possible cases, but machine-dependent
+ transformations can make better code. */
++ if (flag_propolice_protection)
+ {
-+ int bitsize;
-+ REAL_VALUE_TYPE offset;
-+ rtx limit, lab1, lab2, insn;
-+
-+ bitsize = GET_MODE_BITSIZE (GET_MODE (to));
-+ real_2expN (&offset, bitsize - 1);
-+ limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
-+ lab1 = gen_label_rtx ();
-+ lab2 = gen_label_rtx ();
-+
-+ emit_queue ();
-+ to = protect_from_queue (to, 1);
-+ from = protect_from_queue (from, 0);
-+
-+ if (flag_force_mem)
-+ from = force_not_mem (from);
-+
-+ if (fmode != GET_MODE (from))
-+ from = convert_to_mode (fmode, from, 0);
-+
-+ /* See if we need to do the subtraction. */
-+ do_pending_stack_adjust ();
-+ emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
-+ 0, lab1);
-+
-+ /* If not, do the signed "fix" and branch around fixup code. */
-+ expand_fix (to, from, 0);
-+ emit_jump_insn (gen_jump (lab2));
-+ emit_barrier ();
-+
-+ /* Otherwise, subtract 2**(N-1), convert to signed number,
-+ then add 2**(N-1). Do the addition using XOR since this
-+ will often generate better code. */
-+ emit_label (lab1);
-+ target = expand_binop (GET_MODE (from), sub_optab, from, limit,
-+ NULL_RTX, 0, OPTAB_LIB_WIDEN);
-+ expand_fix (to, target, 0);
-+ target = expand_binop (GET_MODE (to), xor_optab, to,
-+ gen_int_mode
-+ ((HOST_WIDE_INT) 1 << (bitsize - 1),
-+ GET_MODE (to)),
-+ to, 1, OPTAB_LIB_WIDEN);
-+
-+ if (target != to)
-+ emit_move_insn (to, target);
-+
-+ emit_label (lab2);
-+
-+ if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
-+ != CODE_FOR_nothing)
++#define FRAMEADDR_P(X) (GET_CODE (X) == PLUS \
++ && XEXP (X, 0) == virtual_stack_vars_rtx \
++ && GET_CODE (XEXP (X, 1)) == CONST_INT)
++ rtx y;
++ if (FRAMEADDR_P (x)) goto win;
++ for (y=x; y!=0 && GET_CODE (y)==PLUS; y = XEXP (y, 0))
+ {
-+ /* Make a place for a REG_NOTE and add it. */
-+ insn = emit_move_insn (to, to);
-+ set_unique_reg_note (insn,
-+ REG_EQUAL,
-+ gen_rtx_fmt_e (UNSIGNED_FIX,
-+ GET_MODE (to),
-+ copy_rtx (from)));
++ if (FRAMEADDR_P (XEXP (y, 0)))
++ XEXP (y, 0) = force_reg (GET_MODE (XEXP (y, 0)), XEXP (y, 0));
++ if (FRAMEADDR_P (XEXP (y, 1)))
++ XEXP (y, 1) = force_reg (GET_MODE (XEXP (y, 1)), XEXP (y, 1));
+ }
-+
-+ return;
+ }
+ LEGITIMIZE_ADDRESS (x, oldx, mode, win);
+
+ /* PLUS and MULT can appear in special ways
+diff -urN gcc-3.3.1/gcc/expr.c gcc-3.3.1-pp/gcc/expr.c
+--- gcc-3.3.1/gcc/expr.c 2003-07-24 19:11:20.000000000 +0000
++++ gcc-3.3.1-pp/gcc/expr.c 2003-09-12 13:40:28.000000000 +0000
+@@ -45,6 +45,7 @@
+ #include "langhooks.h"
+ #include "intl.h"
+ #include "tm_p.h"
++#include "protector.h"
+
+ /* Decide whether a function's arguments should be processed
+ from first to last or from last to first.
+@@ -1518,7 +1519,7 @@
+
+ if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
+ {
+- data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
++ data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len-GET_MODE_SIZE (mode)));
+ data.autinc_from = 1;
+ data.explicit_inc_from = -1;
+ }
+@@ -1532,7 +1533,7 @@
+ data.from_addr = copy_addr_to_reg (from_addr);
+ if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
+ {
+- data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
++ data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len-GET_MODE_SIZE (mode)));
+ data.autinc_to = 1;
+ data.explicit_inc_to = -1;
+ }
+@@ -1649,11 +1650,13 @@
+ from1 = adjust_address (data->from, mode, data->offset);
+
+ if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
+- emit_insn (gen_add2_insn (data->to_addr,
+- GEN_INT (-(HOST_WIDE_INT)size)));
++ if (data->explicit_inc_to < -1)
++ emit_insn (gen_add2_insn (data->to_addr,
++ GEN_INT (-(HOST_WIDE_INT)size)));
+ if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
+- emit_insn (gen_add2_insn (data->from_addr,
+- GEN_INT (-(HOST_WIDE_INT)size)));
++ if (data->explicit_inc_from < -1)
++ emit_insn (gen_add2_insn (data->from_addr,
++ GEN_INT (-(HOST_WIDE_INT)size)));
+
+ if (data->to)
+ emit_insn ((*genfun) (to1, from1));
+@@ -2826,7 +2829,7 @@
+
+ if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
+ {
+- data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
++ data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len-GET_MODE_SIZE (mode)));
+ data->autinc_to = 1;
+ data->explicit_inc_to = -1;
+ }
+@@ -2897,8 +2900,9 @@
+ to1 = adjust_address (data->to, mode, data->offset);
+
+ if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
+- emit_insn (gen_add2_insn (data->to_addr,
+- GEN_INT (-(HOST_WIDE_INT) size)));
++ if (data->explicit_inc_to < -1)
++ emit_insn (gen_add2_insn (data->to_addr,
++ GEN_INT (-(HOST_WIDE_INT) size)));
+
+ cst = (*data->constfun) (data->constfundata, data->offset, mode);
+ emit_insn ((*genfun) (to1, cst));
+@@ -5894,7 +5898,9 @@
+ && GET_CODE (XEXP (value, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
+ && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
+- && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
++ && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER
++ && (!flag_propolice_protection
++ || XEXP (XEXP (value, 0), 0) != virtual_stack_vars_rtx))
+ {
+ rtx temp = expand_simple_binop (GET_MODE (value), code,
+ XEXP (XEXP (value, 0), 0), op2,
+@@ -8070,7 +8076,8 @@
+ /* If adding to a sum including a constant,
+ associate it to put the constant outside. */
+ if (GET_CODE (op1) == PLUS
+- && CONSTANT_P (XEXP (op1, 1)))
++ && CONSTANT_P (XEXP (op1, 1))
++ && !(flag_propolice_protection && (contains_fp (op0) || contains_fp (op1))))
+ {
+ rtx constant_term = const0_rtx;
+
+diff -urN gcc-3.3.1/gcc/flags.h gcc-3.3.1-pp/gcc/flags.h
+--- gcc-3.3.1/gcc/flags.h 2003-06-20 21:18:41.000000000 +0000
++++ gcc-3.3.1-pp/gcc/flags.h 2003-09-12 13:40:28.000000000 +0000
+@@ -690,4 +690,12 @@
+ #define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
+ (MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations)
+
++/* Nonzero means use propolice as a stack protection method */
+
-+ /* We can't do it with an insn, so use a library call. But first ensure
-+ that the mode of TO is at least as wide as SImode, since those are the
-+ only library calls we know about. */
-+
-+ if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
-+ {
-+ target = gen_reg_rtx (SImode);
++extern int flag_propolice_protection;
+
-+ expand_fix (target, from, unsignedp);
-+ }
-+ else if (GET_MODE (from) == SFmode)
-+ {
-+ if (GET_MODE (to) == SImode)
-+ libfcn = unsignedp ? fixunssfsi_libfunc : fixsfsi_libfunc;
-+ else if (GET_MODE (to) == DImode)
-+ libfcn = unsignedp ? fixunssfdi_libfunc : fixsfdi_libfunc;
-+ else if (GET_MODE (to) == TImode)
-+ libfcn = unsignedp ? fixunssfti_libfunc : fixsfti_libfunc;
-+ else
-+ abort ();
-+ }
-+ else if (GET_MODE (from) == DFmode)
-+ {
-+ if (GET_MODE (to) == SImode)
-+ libfcn = unsignedp ? fixunsdfsi_libfunc : fixdfsi_libfunc;
-+ else if (GET_MODE (to) == DImode)
-+ libfcn = unsignedp ? fixunsdfdi_libfunc : fixdfdi_libfunc;
-+ else if (GET_MODE (to) == TImode)
-+ libfcn = unsignedp ? fixunsdfti_libfunc : fixdfti_libfunc;
-+ else
-+ abort ();
-+ }
-+ else if (GET_MODE (from) == XFmode)
-+ {
-+ if (GET_MODE (to) == SImode)
-+ libfcn = unsignedp ? fixunsxfsi_libfunc : fixxfsi_libfunc;
-+ else if (GET_MODE (to) == DImode)
-+ libfcn = unsignedp ? fixunsxfdi_libfunc : fixxfdi_libfunc;
-+ else if (GET_MODE (to) == TImode)
-+ libfcn = unsignedp ? fixunsxfti_libfunc : fixxfti_libfunc;
-+ else
-+ abort ();
-+ }
-+ else if (GET_MODE (from) == TFmode)
-+ {
-+ if (GET_MODE (to) == SImode)
-+ libfcn = unsignedp ? fixunstfsi_libfunc : fixtfsi_libfunc;
-+ else if (GET_MODE (to) == DImode)
-+ libfcn = unsignedp ? fixunstfdi_libfunc : fixtfdi_libfunc;
-+ else if (GET_MODE (to) == TImode)
-+ libfcn = unsignedp ? fixunstfti_libfunc : fixtfti_libfunc;
-+ else
-+ abort ();
-+ }
-+ else
-+ abort ();
++/* Warn when not issuing stack smashing protection for some reason */
+
-+ if (libfcn)
-+ {
-+ rtx insns;
-+ rtx value;
++extern int warn_stack_protector;
+
-+ to = protect_from_queue (to, 1);
-+ from = protect_from_queue (from, 0);
+ #endif /* ! GCC_FLAGS_H */
+diff -urN gcc-3.3.1/gcc/function.c gcc-3.3.1-pp/gcc/function.c
+--- gcc-3.3.1/gcc/function.c 2003-04-10 22:26:04.000000000 +0000
++++ gcc-3.3.1-pp/gcc/function.c 2003-09-12 13:40:28.000000000 +0000
+@@ -59,6 +59,7 @@
+ #include "tm_p.h"
+ #include "integrate.h"
+ #include "langhooks.h"
++#include "protector.h"
+
+ #ifndef TRAMPOLINE_ALIGNMENT
+ #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
+@@ -142,6 +143,10 @@
+ /* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue
+ in this function. */
+ static GTY(()) varray_type sibcall_epilogue;
+
-+ if (flag_force_mem)
-+ from = force_not_mem (from);
++/* Current boundary mark for character arrays. */
++int temp_boundary_mark = 0;
+
-+ start_sequence ();
+ \f
+ /* In order to evaluate some expressions, such as function calls returning
+ structures in memory, we need to temporarily allocate stack locations.
+@@ -195,6 +200,8 @@
+ /* The size of the slot, including extra space for alignment. This
+ info is for combine_temp_slots. */
+ HOST_WIDE_INT full_size;
++ /* Boundary mark of a character array and the others. This info is for propolice */
++ int boundary_mark;
+ };
+ \f
+ /* This structure is used to record MEMs or pseudos used to replace VAR, any
+@@ -629,6 +636,7 @@
+ whose lifetime is controlled by CLEANUP_POINT_EXPRs. KEEP is 3
+ if we are to allocate something at an inner level to be treated as
+ a variable in the block (e.g., a SAVE_EXPR).
++ KEEP is 5 if we allocate a place to return structure.
+
+ TYPE is the type that will be used for the stack slot. */
+
+@@ -642,6 +650,8 @@
+ unsigned int align;
+ struct temp_slot *p, *best_p = 0;
+ rtx slot;
++ int char_array = (flag_propolice_protection
++ && keep == 1 && search_string_def (type));
+
+ /* If SIZE is -1 it means that somebody tried to allocate a temporary
+ of a variable size. */
+@@ -667,7 +677,8 @@
+ && ! p->in_use
+ && objects_must_conflict_p (p->type, type)
+ && (best_p == 0 || best_p->size > p->size
+- || (best_p->size == p->size && best_p->align > p->align)))
++ || (best_p->size == p->size && best_p->align > p->align))
++ && (! char_array || p->boundary_mark != 0))
+ {
+ if (p->align == align && p->size == size)
+ {
+@@ -702,6 +713,7 @@
+ p->address = 0;
+ p->rtl_expr = 0;
+ p->type = best_p->type;
++ p->boundary_mark = best_p->boundary_mark;
+ p->next = temp_slots;
+ temp_slots = p;
+
+@@ -762,6 +774,7 @@
+ p->full_size = frame_offset - frame_offset_old;
+ #endif
+ p->address = 0;
++ p->boundary_mark = char_array?++temp_boundary_mark:0;
+ p->next = temp_slots;
+ temp_slots = p;
+ }
+@@ -932,14 +945,16 @@
+ int delete_q = 0;
+ if (! q->in_use && GET_MODE (q->slot) == BLKmode)
+ {
+- if (p->base_offset + p->full_size == q->base_offset)
++ if (p->base_offset + p->full_size == q->base_offset &&
++ p->boundary_mark == q->boundary_mark)
+ {
+ /* Q comes after P; combine Q into P. */
+ p->size += q->size;
+ p->full_size += q->full_size;
+ delete_q = 1;
+ }
+- else if (q->base_offset + q->full_size == p->base_offset)
++ else if (q->base_offset + q->full_size == p->base_offset &&
++ p->boundary_mark == q->boundary_mark)
+ {
+ /* P comes after Q; combine P into Q. */
+ q->size += p->size;
+@@ -1497,7 +1512,9 @@
+ new = func->x_parm_reg_stack_loc[regno];
+
+ if (new == 0)
+- new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func);
++ new = function ?
++ assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func):
++ assign_stack_local_for_pseudo_reg (decl_mode, GET_MODE_SIZE (decl_mode), 0);
+
+ PUT_CODE (reg, MEM);
+ PUT_MODE (reg, decl_mode);
+@@ -3961,7 +3978,8 @@
+ constant with that register. */
+ temp = gen_reg_rtx (Pmode);
+ XEXP (x, 0) = new;
+- if (validate_change (object, &XEXP (x, 1), temp, 0))
++ if (validate_change (object, &XEXP (x, 1), temp, 0)
++ && ! flag_propolice_protection)
+ emit_insn_before (gen_move_insn (temp, new_offset), object);
+ else
+ {
+diff -urN gcc-3.3.1/gcc/gcse.c gcc-3.3.1-pp/gcc/gcse.c
+--- gcc-3.3.1/gcc/gcse.c 2003-07-14 09:21:22.000000000 +0000
++++ gcc-3.3.1-pp/gcc/gcse.c 2003-09-12 13:40:28.000000000 +0000
+@@ -4211,7 +4211,7 @@
+ /* Find an assignment that sets reg_used and is available
+ at the start of the block. */
+ set = find_avail_set (regno, insn);
+- if (! set)
++ if (! set || set->expr->volatil)
+ continue;
+
+ pat = set->expr;
+diff -urN gcc-3.3.1/gcc/integrate.c gcc-3.3.1-pp/gcc/integrate.c
+--- gcc-3.3.1/gcc/integrate.c 2003-07-15 01:05:43.000000000 +0000
++++ gcc-3.3.1-pp/gcc/integrate.c 2003-09-12 13:40:28.000000000 +0000
+@@ -401,6 +401,10 @@
+ /* These args would always appear unused, if not for this. */
+ TREE_USED (copy) = 1;
+
++ /* The inlined variable is marked as INLINE not to sweep by propolice */
++ if (flag_propolice_protection && TREE_CODE (copy) == VAR_DECL)
++ DECL_INLINE (copy) = 1;
+
-+ value = emit_library_call_value (libfcn, NULL_RTX, LCT_CONST,
-+ GET_MODE (to), 1, from,
-+ GET_MODE (from));
-+ insns = get_insns ();
-+ end_sequence ();
+ /* Set the context for the new declaration. */
+ if (!DECL_CONTEXT (decl))
+ /* Globals stay global. */
+@@ -1965,6 +1969,10 @@
+
+ seq = get_insns ();
+ end_sequence ();
++#ifdef FRAME_GROWS_DOWNWARD
++ if (flag_propolice_protection && GET_CODE (seq) == SET)
++ RTX_INTEGRATED_P (SET_SRC (seq)) = 1;
++#endif
+ emit_insn_after (seq, map->insns_at_start);
+ return temp;
+ }
+diff -urN gcc-3.3.1/gcc/libgcc-std.ver gcc-3.3.1-pp/gcc/libgcc-std.ver
+--- gcc-3.3.1/gcc/libgcc-std.ver 2003-07-13 21:25:09.000000000 +0000
++++ gcc-3.3.1-pp/gcc/libgcc-std.ver 2003-09-12 13:40:28.000000000 +0000
+@@ -174,6 +174,10 @@
+ _Unwind_SjLj_RaiseException
+ _Unwind_SjLj_ForcedUnwind
+ _Unwind_SjLj_Resume
+
-+ emit_libcall_block (insns, target, value,
-+ gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
-+ GET_MODE (to), from));
-+ }
-+
-+ if (target != to)
-+ {
-+ if (GET_MODE (to) == GET_MODE (target))
-+ emit_move_insn (to, target);
-+ else
-+ convert_move (to, target, 0);
-+ }
-+}
++ # stack smash handler symbols
++ __guard
++ __stack_smash_handler
+ }
+
+ %inherit GCC_3.3 GCC_3.0
+diff -urN gcc-3.3.1/gcc/libgcc2.c gcc-3.3.1-pp/gcc/libgcc2.c
+--- gcc-3.3.1/gcc/libgcc2.c 2002-10-23 10:47:24.000000000 +0000
++++ gcc-3.3.1-pp/gcc/libgcc2.c 2003-09-12 13:40:28.000000000 +0000
+@@ -1993,3 +1993,102 @@
+ #endif /* NEED_ATEXIT */
+
+ #endif /* L_exit */
+\f
-+/* Report whether we have an instruction to perform the operation
-+ specified by CODE on operands of mode MODE. */
-+int
-+have_insn_for (code, mode)
-+ enum rtx_code code;
-+ enum machine_mode mode;
-+{
-+ return (code_to_optab[(int) code] != 0
-+ && (code_to_optab[(int) code]->handlers[(int) mode].insn_code
-+ != CODE_FOR_nothing));
-+}
-+
-+/* Create a blank optab. */
-+static optab
-+new_optab ()
-+{
-+ int i;
-+ optab op = (optab) ggc_alloc (sizeof (struct optab));
-+ for (i = 0; i < NUM_MACHINE_MODES; i++)
-+ {
-+ op->handlers[i].insn_code = CODE_FOR_nothing;
-+ op->handlers[i].libfunc = 0;
-+ }
-+
-+ return op;
-+}
-+
-+/* Same, but fill in its code as CODE, and write it into the
-+ code_to_optab table. */
-+static inline optab
-+init_optab (code)
-+ enum rtx_code code;
-+{
-+ optab op = new_optab ();
-+ op->code = code;
-+ code_to_optab[(int) code] = op;
-+ return op;
-+}
-+
-+/* Same, but fill in its code as CODE, and do _not_ write it into
-+ the code_to_optab table. */
-+static inline optab
-+init_optabv (code)
-+ enum rtx_code code;
-+{
-+ optab op = new_optab ();
-+ op->code = code;
-+ return op;
-+}
-+
-+/* Initialize the libfunc fields of an entire group of entries in some
-+ optab. Each entry is set equal to a string consisting of a leading
-+ pair of underscores followed by a generic operation name followed by
-+ a mode name (downshifted to lower case) followed by a single character
-+ representing the number of operands for the given operation (which is
-+ usually one of the characters '2', '3', or '4').
-+
-+ OPTABLE is the table in which libfunc fields are to be initialized.
-+ FIRST_MODE is the first machine mode index in the given optab to
-+ initialize.
-+ LAST_MODE is the last machine mode index in the given optab to
-+ initialize.
-+ OPNAME is the generic (string) name of the operation.
-+ SUFFIX is the character which specifies the number of operands for
-+ the given generic operation.
-+*/
-+
-+static void
-+init_libfuncs (optable, first_mode, last_mode, opname, suffix)
-+ optab optable;
-+ int first_mode;
-+ int last_mode;
-+ const char *opname;
-+ int suffix;
-+{
-+ int mode;
-+ unsigned opname_len = strlen (opname);
-+
-+ for (mode = first_mode; (int) mode <= (int) last_mode;
-+ mode = (enum machine_mode) ((int) mode + 1))
-+ {
-+ const char *mname = GET_MODE_NAME (mode);
-+ unsigned mname_len = strlen (mname);
-+ char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
-+ char *p;
-+ const char *q;
-+
-+ p = libfunc_name;
-+ *p++ = '_';
-+ *p++ = '_';
-+ for (q = opname; *q; )
-+ *p++ = *q++;
-+ for (q = mname; *q; q++)
-+ *p++ = TOLOWER (*q);
-+ *p++ = suffix;
-+ *p = '\0';
-+
-+ optable->handlers[(int) mode].libfunc
-+ = gen_rtx_SYMBOL_REF (Pmode, ggc_alloc_string (libfunc_name,
-+ p - libfunc_name));
-+ }
-+}
-+
-+/* Initialize the libfunc fields of an entire group of entries in some
-+ optab which correspond to all integer mode operations. The parameters
-+ have the same meaning as similarly named ones for the `init_libfuncs'
-+ routine. (See above). */
-+
-+static void
-+init_integral_libfuncs (optable, opname, suffix)
-+ optab optable;
-+ const char *opname;
-+ int suffix;
-+{
-+ init_libfuncs (optable, SImode, TImode, opname, suffix);
-+}
-+
-+/* Initialize the libfunc fields of an entire group of entries in some
-+ optab which correspond to all real mode operations. The parameters
-+ have the same meaning as similarly named ones for the `init_libfuncs'
-+ routine. (See above). */
-+
-+static void
-+init_floating_libfuncs (optable, opname, suffix)
-+ optab optable;
-+ const char *opname;
-+ int suffix;
-+{
-+ init_libfuncs (optable, SFmode, TFmode, opname, suffix);
-+}
-+
-+rtx
-+init_one_libfunc (name)
-+ const char *name;
-+{
-+ /* Create a FUNCTION_DECL that can be passed to
-+ targetm.encode_section_info. */
-+ /* ??? We don't have any type information except for this is
-+ a function. Pretend this is "int foo()". */
-+ tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
-+ build_function_type (integer_type_node, NULL_TREE));
-+ DECL_ARTIFICIAL (decl) = 1;
-+ DECL_EXTERNAL (decl) = 1;
-+ TREE_PUBLIC (decl) = 1;
-+
-+ /* Return the symbol_ref from the mem rtx. */
-+ return XEXP (DECL_RTL (decl), 0);
-+}
-+
-+/* Call this once to initialize the contents of the optabs
-+ appropriately for the current target machine. */
-+
-+void
-+init_optabs ()
-+{
-+ unsigned int i, j, k;
-+
-+ /* Start by initializing all tables to contain CODE_FOR_nothing. */
-+
-+ for (i = 0; i < ARRAY_SIZE (fixtab); i++)
-+ for (j = 0; j < ARRAY_SIZE (fixtab[0]); j++)
-+ for (k = 0; k < ARRAY_SIZE (fixtab[0][0]); k++)
-+ fixtab[i][j][k] = CODE_FOR_nothing;
-+
-+ for (i = 0; i < ARRAY_SIZE (fixtrunctab); i++)
-+ for (j = 0; j < ARRAY_SIZE (fixtrunctab[0]); j++)
-+ for (k = 0; k < ARRAY_SIZE (fixtrunctab[0][0]); k++)
-+ fixtrunctab[i][j][k] = CODE_FOR_nothing;
-+
-+ for (i = 0; i < ARRAY_SIZE (floattab); i++)
-+ for (j = 0; j < ARRAY_SIZE (floattab[0]); j++)
-+ for (k = 0; k < ARRAY_SIZE (floattab[0][0]); k++)
-+ floattab[i][j][k] = CODE_FOR_nothing;
-+
-+ for (i = 0; i < ARRAY_SIZE (extendtab); i++)
-+ for (j = 0; j < ARRAY_SIZE (extendtab[0]); j++)
-+ for (k = 0; k < ARRAY_SIZE (extendtab[0][0]); k++)
-+ extendtab[i][j][k] = CODE_FOR_nothing;
-+
-+ for (i = 0; i < NUM_RTX_CODE; i++)
-+ setcc_gen_code[i] = CODE_FOR_nothing;
++#ifdef L_stack_smash_handler
++#include <stdio.h>
++#include <string.h>
++#include <fcntl.h>
++#include <unistd.h>
+
-+#ifdef HAVE_conditional_move
-+ for (i = 0; i < NUM_MACHINE_MODES; i++)
-+ movcc_gen_code[i] = CODE_FOR_nothing;
++#ifdef _POSIX_SOURCE
++#include <signal.h>
+#endif
+
-+ add_optab = init_optab (PLUS);
-+ addv_optab = init_optabv (PLUS);
-+ sub_optab = init_optab (MINUS);
-+ subv_optab = init_optabv (MINUS);
-+ smul_optab = init_optab (MULT);
-+ smulv_optab = init_optabv (MULT);
-+ smul_highpart_optab = init_optab (UNKNOWN);
-+ umul_highpart_optab = init_optab (UNKNOWN);
-+ smul_widen_optab = init_optab (UNKNOWN);
-+ umul_widen_optab = init_optab (UNKNOWN);
-+ sdiv_optab = init_optab (DIV);
-+ sdivv_optab = init_optabv (DIV);
-+ sdivmod_optab = init_optab (UNKNOWN);
-+ udiv_optab = init_optab (UDIV);
-+ udivmod_optab = init_optab (UNKNOWN);
-+ smod_optab = init_optab (MOD);
-+ umod_optab = init_optab (UMOD);
-+ ftrunc_optab = init_optab (UNKNOWN);
-+ and_optab = init_optab (AND);
-+ ior_optab = init_optab (IOR);
-+ xor_optab = init_optab (XOR);
-+ ashl_optab = init_optab (ASHIFT);
-+ ashr_optab = init_optab (ASHIFTRT);
-+ lshr_optab = init_optab (LSHIFTRT);
-+ rotl_optab = init_optab (ROTATE);
-+ rotr_optab = init_optab (ROTATERT);
-+ smin_optab = init_optab (SMIN);
-+ smax_optab = init_optab (SMAX);
-+ umin_optab = init_optab (UMIN);
-+ umax_optab = init_optab (UMAX);
-+
-+ /* These three have codes assigned exclusively for the sake of
-+ have_insn_for. */
-+ mov_optab = init_optab (SET);
-+ movstrict_optab = init_optab (STRICT_LOW_PART);
-+ cmp_optab = init_optab (COMPARE);
-+
-+ ucmp_optab = init_optab (UNKNOWN);
-+ tst_optab = init_optab (UNKNOWN);
-+ neg_optab = init_optab (NEG);
-+ negv_optab = init_optabv (NEG);
-+ abs_optab = init_optab (ABS);
-+ absv_optab = init_optabv (ABS);
-+ one_cmpl_optab = init_optab (NOT);
-+ ffs_optab = init_optab (FFS);
-+ sqrt_optab = init_optab (SQRT);
-+ sin_optab = init_optab (UNKNOWN);
-+ cos_optab = init_optab (UNKNOWN);
-+ exp_optab = init_optab (UNKNOWN);
-+ log_optab = init_optab (UNKNOWN);
-+ strlen_optab = init_optab (UNKNOWN);
-+ cbranch_optab = init_optab (UNKNOWN);
-+ cmov_optab = init_optab (UNKNOWN);
-+ cstore_optab = init_optab (UNKNOWN);
-+ push_optab = init_optab (UNKNOWN);
-+
-+ for (i = 0; i < NUM_MACHINE_MODES; i++)
-+ {
-+ movstr_optab[i] = CODE_FOR_nothing;
-+ clrstr_optab[i] = CODE_FOR_nothing;
++#if defined(HAVE_SYSLOG)
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/un.h>
+
-+#ifdef HAVE_SECONDARY_RELOADS
-+ reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
++#include <sys/syslog.h>
++#ifndef _PATH_LOG
++#define _PATH_LOG "/dev/log"
+#endif
-+ }
-+
-+ /* Fill in the optabs with the insns we support. */
-+ init_all_optabs ();
-+
-+#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
-+ /* This flag says the same insns that convert to a signed fixnum
-+ also convert validly to an unsigned one. */
-+ for (i = 0; i < NUM_MACHINE_MODES; i++)
-+ for (j = 0; j < NUM_MACHINE_MODES; j++)
-+ fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
+#endif
+
-+ /* Initialize the optabs with the names of the library functions. */
-+ init_integral_libfuncs (add_optab, "add", '3');
-+ init_floating_libfuncs (add_optab, "add", '3');
-+ init_integral_libfuncs (addv_optab, "addv", '3');
-+ init_floating_libfuncs (addv_optab, "add", '3');
-+ init_integral_libfuncs (sub_optab, "sub", '3');
-+ init_floating_libfuncs (sub_optab, "sub", '3');
-+ init_integral_libfuncs (subv_optab, "subv", '3');
-+ init_floating_libfuncs (subv_optab, "sub", '3');
-+ init_integral_libfuncs (smul_optab, "mul", '3');
-+ init_floating_libfuncs (smul_optab, "mul", '3');
-+ init_integral_libfuncs (smulv_optab, "mulv", '3');
-+ init_floating_libfuncs (smulv_optab, "mul", '3');
-+ init_integral_libfuncs (sdiv_optab, "div", '3');
-+ init_floating_libfuncs (sdiv_optab, "div", '3');
-+ init_integral_libfuncs (sdivv_optab, "divv", '3');
-+ init_integral_libfuncs (udiv_optab, "udiv", '3');
-+ init_integral_libfuncs (sdivmod_optab, "divmod", '4');
-+ init_integral_libfuncs (udivmod_optab, "udivmod", '4');
-+ init_integral_libfuncs (smod_optab, "mod", '3');
-+ init_integral_libfuncs (umod_optab, "umod", '3');
-+ init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
-+ init_integral_libfuncs (and_optab, "and", '3');
-+ init_integral_libfuncs (ior_optab, "ior", '3');
-+ init_integral_libfuncs (xor_optab, "xor", '3');
-+ init_integral_libfuncs (ashl_optab, "ashl", '3');
-+ init_integral_libfuncs (ashr_optab, "ashr", '3');
-+ init_integral_libfuncs (lshr_optab, "lshr", '3');
-+ init_integral_libfuncs (smin_optab, "min", '3');
-+ init_floating_libfuncs (smin_optab, "min", '3');
-+ init_integral_libfuncs (smax_optab, "max", '3');
-+ init_floating_libfuncs (smax_optab, "max", '3');
-+ init_integral_libfuncs (umin_optab, "umin", '3');
-+ init_integral_libfuncs (umax_optab, "umax", '3');
-+ init_integral_libfuncs (neg_optab, "neg", '2');
-+ init_floating_libfuncs (neg_optab, "neg", '2');
-+ init_integral_libfuncs (negv_optab, "negv", '2');
-+ init_floating_libfuncs (negv_optab, "neg", '2');
-+ init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
-+ init_integral_libfuncs (ffs_optab, "ffs", '2');
-+
-+ /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
-+ init_integral_libfuncs (cmp_optab, "cmp", '2');
-+ init_integral_libfuncs (ucmp_optab, "ucmp", '2');
-+ init_floating_libfuncs (cmp_optab, "cmp", '2');
-+
-+#ifdef MULSI3_LIBCALL
-+ smul_optab->handlers[(int) SImode].libfunc
-+ = init_one_libfunc (MULSI3_LIBCALL);
-+#endif
-+#ifdef MULDI3_LIBCALL
-+ smul_optab->handlers[(int) DImode].libfunc
-+ = init_one_libfunc (MULDI3_LIBCALL);
++long __guard[8] = {0,0,0,0,0,0,0,0};
++static void __guard_setup (void) __attribute__ ((constructor)) ;
++static void __guard_setup (void)
++{
++ int fd;
++ if (__guard[0]!=0) return;
++ fd = open ("/dev/urandom", 0);
++ if (fd != -1) {
++ ssize_t size = read (fd, (char*)&__guard, sizeof(__guard));
++ close (fd) ;
++ if (size == sizeof(__guard)) return;
++ }
++ /* If a random generator can't be used, the protector switches the guard
++ to the "terminator canary" */
++ ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
++ ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
++}
++void __stack_smash_handler (char func[], int damaged ATTRIBUTE_UNUSED)
++{
++#if defined (__GNU_LIBRARY__)
++ extern char * __progname;
+#endif
-+
-+#ifdef DIVSI3_LIBCALL
-+ sdiv_optab->handlers[(int) SImode].libfunc
-+ = init_one_libfunc (DIVSI3_LIBCALL);
++ const char message[] = ": stack smashing attack in function ";
++ int bufsz = 256, len;
++ char buf[bufsz];
++#if defined(HAVE_SYSLOG)
++ int LogFile;
++ struct sockaddr_un SyslogAddr; /* AF_UNIX address of local logger */
+#endif
-+#ifdef DIVDI3_LIBCALL
-+ sdiv_optab->handlers[(int) DImode].libfunc
-+ = init_one_libfunc (DIVDI3_LIBCALL);
++#ifdef _POSIX_SOURCE
++ {
++ sigset_t mask;
++ sigfillset(&mask);
++ sigdelset(&mask, SIGABRT); /* Block all signal handlers */
++ sigprocmask(SIG_BLOCK, &mask, NULL); /* except SIGABRT */
++ }
+#endif
+
-+#ifdef UDIVSI3_LIBCALL
-+ udiv_optab->handlers[(int) SImode].libfunc
-+ = init_one_libfunc (UDIVSI3_LIBCALL);
-+#endif
-+#ifdef UDIVDI3_LIBCALL
-+ udiv_optab->handlers[(int) DImode].libfunc
-+ = init_one_libfunc (UDIVDI3_LIBCALL);
++ strcpy(buf, "<2>"); len=3; /* send LOG_CRIT */
++#if defined (__GNU_LIBRARY__)
++ strncat(buf, __progname, bufsz-len-1); len = strlen(buf);
+#endif
++ if (bufsz>len) {strncat(buf, message, bufsz-len-1); len = strlen(buf);}
++ if (bufsz>len) {strncat(buf, func, bufsz-len-1); len = strlen(buf);}
+
-+#ifdef MODSI3_LIBCALL
-+ smod_optab->handlers[(int) SImode].libfunc
-+ = init_one_libfunc (MODSI3_LIBCALL);
-+#endif
-+#ifdef MODDI3_LIBCALL
-+ smod_optab->handlers[(int) DImode].libfunc
-+ = init_one_libfunc (MODDI3_LIBCALL);
-+#endif
++ /* print error message */
++ write (STDERR_FILENO, buf+3, len-3);
++#if defined(HAVE_SYSLOG)
++ if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) != -1) {
+
-+#ifdef UMODSI3_LIBCALL
-+ umod_optab->handlers[(int) SImode].libfunc
-+ = init_one_libfunc (UMODSI3_LIBCALL);
-+#endif
-+#ifdef UMODDI3_LIBCALL
-+ umod_optab->handlers[(int) DImode].libfunc
-+ = init_one_libfunc (UMODDI3_LIBCALL);
++ /*
++ * Send "found" message to the "/dev/log" path
++ */
++ SyslogAddr.sun_family = AF_UNIX;
++ (void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
++ sizeof(SyslogAddr.sun_path) - 1);
++ SyslogAddr.sun_path[sizeof(SyslogAddr.sun_path) - 1] = '\0';
++ sendto(LogFile, buf, len, 0, (struct sockaddr *)&SyslogAddr,
++ sizeof(SyslogAddr));
++ }
+#endif
+
-+ /* Use cabs for DC complex abs, since systems generally have cabs.
-+ Don't define any libcall for SCmode, so that cabs will be used. */
-+ abs_optab->handlers[(int) DCmode].libfunc
-+ = init_one_libfunc ("cabs");
-+
-+ /* The ffs function operates on `int'. */
-+ ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
-+ = init_one_libfunc ("ffs");
-+
-+ extendsfdf2_libfunc = init_one_libfunc ("__extendsfdf2");
-+ extendsfxf2_libfunc = init_one_libfunc ("__extendsfxf2");
-+ extendsftf2_libfunc = init_one_libfunc ("__extendsftf2");
-+ extenddfxf2_libfunc = init_one_libfunc ("__extenddfxf2");
-+ extenddftf2_libfunc = init_one_libfunc ("__extenddftf2");
-+
-+ truncdfsf2_libfunc = init_one_libfunc ("__truncdfsf2");
-+ truncxfsf2_libfunc = init_one_libfunc ("__truncxfsf2");
-+ trunctfsf2_libfunc = init_one_libfunc ("__trunctfsf2");
-+ truncxfdf2_libfunc = init_one_libfunc ("__truncxfdf2");
-+ trunctfdf2_libfunc = init_one_libfunc ("__trunctfdf2");
-+
-+ abort_libfunc = init_one_libfunc ("abort");
-+ memcpy_libfunc = init_one_libfunc ("memcpy");
-+ memmove_libfunc = init_one_libfunc ("memmove");
-+ bcopy_libfunc = init_one_libfunc ("bcopy");
-+ memcmp_libfunc = init_one_libfunc ("memcmp");
-+ bcmp_libfunc = init_one_libfunc ("__gcc_bcmp");
-+ memset_libfunc = init_one_libfunc ("memset");
-+ bzero_libfunc = init_one_libfunc ("bzero");
-+
-+ unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
-+ ? "_Unwind_SjLj_Resume"
-+ : "_Unwind_Resume");
-+#ifndef DONT_USE_BUILTIN_SETJMP
-+ setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
-+ longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
-+#else
-+ setjmp_libfunc = init_one_libfunc ("setjmp");
-+ longjmp_libfunc = init_one_libfunc ("longjmp");
-+#endif
-+ unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
-+ unwind_sjlj_unregister_libfunc
-+ = init_one_libfunc ("_Unwind_SjLj_Unregister");
-+
-+ eqhf2_libfunc = init_one_libfunc ("__eqhf2");
-+ nehf2_libfunc = init_one_libfunc ("__nehf2");
-+ gthf2_libfunc = init_one_libfunc ("__gthf2");
-+ gehf2_libfunc = init_one_libfunc ("__gehf2");
-+ lthf2_libfunc = init_one_libfunc ("__lthf2");
-+ lehf2_libfunc = init_one_libfunc ("__lehf2");
-+ unordhf2_libfunc = init_one_libfunc ("__unordhf2");
-+
-+ eqsf2_libfunc = init_one_libfunc ("__eqsf2");
-+ nesf2_libfunc = init_one_libfunc ("__nesf2");
-+ gtsf2_libfunc = init_one_libfunc ("__gtsf2");
-+ gesf2_libfunc = init_one_libfunc ("__gesf2");
-+ ltsf2_libfunc = init_one_libfunc ("__ltsf2");
-+ lesf2_libfunc = init_one_libfunc ("__lesf2");
-+ unordsf2_libfunc = init_one_libfunc ("__unordsf2");
-+
-+ eqdf2_libfunc = init_one_libfunc ("__eqdf2");
-+ nedf2_libfunc = init_one_libfunc ("__nedf2");
-+ gtdf2_libfunc = init_one_libfunc ("__gtdf2");
-+ gedf2_libfunc = init_one_libfunc ("__gedf2");
-+ ltdf2_libfunc = init_one_libfunc ("__ltdf2");
-+ ledf2_libfunc = init_one_libfunc ("__ledf2");
-+ unorddf2_libfunc = init_one_libfunc ("__unorddf2");
-+
-+ eqxf2_libfunc = init_one_libfunc ("__eqxf2");
-+ nexf2_libfunc = init_one_libfunc ("__nexf2");
-+ gtxf2_libfunc = init_one_libfunc ("__gtxf2");
-+ gexf2_libfunc = init_one_libfunc ("__gexf2");
-+ ltxf2_libfunc = init_one_libfunc ("__ltxf2");
-+ lexf2_libfunc = init_one_libfunc ("__lexf2");
-+ unordxf2_libfunc = init_one_libfunc ("__unordxf2");
-+
-+ eqtf2_libfunc = init_one_libfunc ("__eqtf2");
-+ netf2_libfunc = init_one_libfunc ("__netf2");
-+ gttf2_libfunc = init_one_libfunc ("__gttf2");
-+ getf2_libfunc = init_one_libfunc ("__getf2");
-+ lttf2_libfunc = init_one_libfunc ("__lttf2");
-+ letf2_libfunc = init_one_libfunc ("__letf2");
-+ unordtf2_libfunc = init_one_libfunc ("__unordtf2");
-+
-+ floatsisf_libfunc = init_one_libfunc ("__floatsisf");
-+ floatdisf_libfunc = init_one_libfunc ("__floatdisf");
-+ floattisf_libfunc = init_one_libfunc ("__floattisf");
-+
-+ floatsidf_libfunc = init_one_libfunc ("__floatsidf");
-+ floatdidf_libfunc = init_one_libfunc ("__floatdidf");
-+ floattidf_libfunc = init_one_libfunc ("__floattidf");
-+
-+ floatsixf_libfunc = init_one_libfunc ("__floatsixf");
-+ floatdixf_libfunc = init_one_libfunc ("__floatdixf");
-+ floattixf_libfunc = init_one_libfunc ("__floattixf");
-+
-+ floatsitf_libfunc = init_one_libfunc ("__floatsitf");
-+ floatditf_libfunc = init_one_libfunc ("__floatditf");
-+ floattitf_libfunc = init_one_libfunc ("__floattitf");
-+
-+ fixsfsi_libfunc = init_one_libfunc ("__fixsfsi");
-+ fixsfdi_libfunc = init_one_libfunc ("__fixsfdi");
-+ fixsfti_libfunc = init_one_libfunc ("__fixsfti");
-+
-+ fixdfsi_libfunc = init_one_libfunc ("__fixdfsi");
-+ fixdfdi_libfunc = init_one_libfunc ("__fixdfdi");
-+ fixdfti_libfunc = init_one_libfunc ("__fixdfti");
-+
-+ fixxfsi_libfunc = init_one_libfunc ("__fixxfsi");
-+ fixxfdi_libfunc = init_one_libfunc ("__fixxfdi");
-+ fixxfti_libfunc = init_one_libfunc ("__fixxfti");
-+
-+ fixtfsi_libfunc = init_one_libfunc ("__fixtfsi");
-+ fixtfdi_libfunc = init_one_libfunc ("__fixtfdi");
-+ fixtfti_libfunc = init_one_libfunc ("__fixtfti");
-+
-+ fixunssfsi_libfunc = init_one_libfunc ("__fixunssfsi");
-+ fixunssfdi_libfunc = init_one_libfunc ("__fixunssfdi");
-+ fixunssfti_libfunc = init_one_libfunc ("__fixunssfti");
-+
-+ fixunsdfsi_libfunc = init_one_libfunc ("__fixunsdfsi");
-+ fixunsdfdi_libfunc = init_one_libfunc ("__fixunsdfdi");
-+ fixunsdfti_libfunc = init_one_libfunc ("__fixunsdfti");
-+
-+ fixunsxfsi_libfunc = init_one_libfunc ("__fixunsxfsi");
-+ fixunsxfdi_libfunc = init_one_libfunc ("__fixunsxfdi");
-+ fixunsxfti_libfunc = init_one_libfunc ("__fixunsxfti");
-+
-+ fixunstfsi_libfunc = init_one_libfunc ("__fixunstfsi");
-+ fixunstfdi_libfunc = init_one_libfunc ("__fixunstfdi");
-+ fixunstfti_libfunc = init_one_libfunc ("__fixunstfti");
-+
-+ /* For function entry/exit instrumentation. */
-+ profile_function_entry_libfunc
-+ = init_one_libfunc ("__cyg_profile_func_enter");
-+ profile_function_exit_libfunc
-+ = init_one_libfunc ("__cyg_profile_func_exit");
-+
-+ if (HAVE_conditional_trap)
-+ trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
-+
-+#ifdef INIT_TARGET_OPTABS
-+ /* Allow the target to add more libcalls or rename some, etc. */
-+ INIT_TARGET_OPTABS;
++#ifdef _POSIX_SOURCE
++ { /* Make sure the default handler is associated with SIGABRT */
++ struct sigaction sa;
++
++ memset(&sa, 0, sizeof(struct sigaction));
++ sigfillset(&sa.sa_mask); /* Block all signals */
++ sa.sa_flags = 0;
++ sa.sa_handler = SIG_DFL;
++ sigaction(SIGABRT, &sa, NULL);
++ (void)kill(getpid(), SIGABRT);
++ }
+#endif
++ _exit(127);
+}
-+\f
-+/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
-+ CODE. Return 0 on failure. */
-+
-+rtx
-+gen_cond_trap (code, op1, op2, tcode)
-+ enum rtx_code code ATTRIBUTE_UNUSED;
-+ rtx op1, op2 ATTRIBUTE_UNUSED, tcode ATTRIBUTE_UNUSED;
-+{
-+ enum machine_mode mode = GET_MODE (op1);
-+ enum insn_code icode;
-+ rtx insn;
-+
-+ if (!HAVE_conditional_trap)
-+ return 0;
-+
-+ if (mode == VOIDmode)
-+ return 0;
-+
-+ icode = cmp_optab->handlers[(int) mode].insn_code;
-+ if (icode == CODE_FOR_nothing)
++#endif
+diff -urN gcc-3.3.1/gcc/loop.c gcc-3.3.1-pp/gcc/loop.c
+--- gcc-3.3.1/gcc/loop.c 2003-07-11 06:47:05.000000000 +0000
++++ gcc-3.3.1-pp/gcc/loop.c 2003-09-12 13:40:28.000000000 +0000
+@@ -6516,6 +6516,14 @@
+ if (GET_CODE (*mult_val) == USE)
+ *mult_val = XEXP (*mult_val, 0);
+
++#ifndef FRAME_GROWS_DOWNWARD
++ if (flag_propolice_protection
++ && GET_CODE (*add_val) == PLUS
++ && (XEXP (*add_val, 0) == frame_pointer_rtx
++ || XEXP (*add_val, 1) == frame_pointer_rtx))
+ return 0;
++#endif
+
-+ start_sequence ();
-+ op1 = prepare_operand (icode, op1, 0, mode, mode, 0);
-+ op2 = prepare_operand (icode, op2, 1, mode, mode, 0);
-+ if (!op1 || !op2)
+ if (is_addr)
+ *pbenefit += address_cost (orig_x, addr_mode) - reg_address_cost;
+ else
+diff -urN gcc-3.3.1/gcc/optabs.c gcc-3.3.1-pp/gcc/optabs.c
+--- gcc-3.3.1/gcc/optabs.c 2003-07-19 00:25:25.000000000 +0000
++++ gcc-3.3.1-pp/gcc/optabs.c 2003-09-12 13:40:28.000000000 +0000
+@@ -703,6 +703,26 @@
+ if (target)
+ target = protect_from_queue (target, 1);
+
++ if (flag_propolice_protection
++ && binoptab->code == PLUS
++ && op0 == virtual_stack_vars_rtx
++ && GET_CODE(op1) == CONST_INT)
+ {
-+ end_sequence ();
-+ return 0;
-+ }
-+ emit_insn (GEN_FCN (icode) (op1, op2));
++ int icode = (int) binoptab->handlers[(int) mode].insn_code;
++ if (target)
++ temp = target;
++ else
++ temp = gen_reg_rtx (mode);
+
-+ PUT_CODE (trap_rtx, code);
-+ insn = gen_conditional_trap (trap_rtx, tcode);
-+ if (insn)
-+ {
-+ emit_insn (insn);
-+ insn = get_insns ();
-+ }
-+ end_sequence ();
++ if (! (*insn_data[icode].operand[0].predicate) (temp, mode)
++ || GET_CODE (temp) != REG)
++ temp = gen_reg_rtx (mode);
+
-+ return insn;
-+}
++ emit_insn (gen_rtx_SET (VOIDmode, temp,
++ gen_rtx_PLUS (GET_MODE (op0), op0, op1)));
++ return temp;
++ }
+
-+#include "gt-optabs.h"
-diff -ruN gcc-3.3.1/gcc/protector.c gcc-3.3.1.pp/gcc/protector.c
+ if (flag_force_mem)
+ {
+ op0 = force_not_mem (op0);
+diff -urN gcc-3.3.1/gcc/protector.c gcc-3.3.1-pp/gcc/protector.c
--- gcc-3.3.1/gcc/protector.c 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/protector.c 2003-09-05 11:59:47.000000000 +0000
++++ gcc-3.3.1-pp/gcc/protector.c 2003-09-12 13:40:28.000000000 +0000
@@ -0,0 +1,2489 @@
+/* RTL buffer overflow protection function for GNU C compiler
+ Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+ return FALSE;
+}
+#endif
-diff -ruN gcc-3.3.1/gcc/protector.h gcc-3.3.1.pp/gcc/protector.h
+diff -urN gcc-3.3.1/gcc/protector.h gcc-3.3.1-pp/gcc/protector.h
--- gcc-3.3.1/gcc/protector.h 1970-01-01 00:00:00.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/protector.h 2003-09-05 11:59:47.000000000 +0000
++++ gcc-3.3.1-pp/gcc/protector.h 2003-09-12 13:40:28.000000000 +0000
@@ -0,0 +1,48 @@
+/* RTL buffer overflow protection function for GNU C compiler
+ Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+extern rtx assign_stack_local_for_pseudo_reg PARAMS ((enum machine_mode, HOST_WIDE_INT, int));
+
+#endif
-diff -ruN gcc-3.3.1/gcc/reload1.c gcc-3.3.1.pp/gcc/reload1.c
+diff -urN gcc-3.3.1/gcc/reload1.c gcc-3.3.1-pp/gcc/reload1.c
--- gcc-3.3.1/gcc/reload1.c 2003-06-07 05:30:09.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/reload1.c 2003-09-05 11:58:59.000000000 +0000
++++ gcc-3.3.1-pp/gcc/reload1.c 2003-09-12 13:40:28.000000000 +0000
@@ -42,6 +42,7 @@
#include "toplev.h"
#include "except.h"
inherent_size == total_size ? 0 : -1);
if (BYTES_BIG_ENDIAN)
/* Cancel the big-endian correction done in assign_stack_local.
-diff -ruN gcc-3.3.1/gcc/simplify-rtx.c gcc-3.3.1.pp/gcc/simplify-rtx.c
+diff -urN gcc-3.3.1/gcc/simplify-rtx.c gcc-3.3.1-pp/gcc/simplify-rtx.c
--- gcc-3.3.1/gcc/simplify-rtx.c 2003-07-03 07:38:22.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/simplify-rtx.c 2003-09-05 11:58:59.000000000 +0000
++++ gcc-3.3.1-pp/gcc/simplify-rtx.c 2003-09-12 13:40:28.000000000 +0000
@@ -1670,7 +1670,8 @@
int n_ops = 2, input_ops = 2, input_consts = 0, n_consts;
int first, negate, changed;
/* Put a non-negated operand first. If there aren't any, make all
operands positive and negate the whole thing later. */
-diff -ruN gcc-3.3.1/gcc/toplev.c gcc-3.3.1.pp/gcc/toplev.c
+diff -urN gcc-3.3.1/gcc/toplev.c gcc-3.3.1-pp/gcc/toplev.c
--- gcc-3.3.1/gcc/toplev.c 2003-07-18 06:59:16.000000000 +0000
-+++ gcc-3.3.1.pp/gcc/toplev.c 2003-09-05 11:58:59.000000000 +0000
++++ gcc-3.3.1-pp/gcc/toplev.c 2003-09-12 13:40:28.000000000 +0000
@@ -904,6 +904,13 @@
minimum function alignment. Zero means no alignment is forced. */
int force_align_functions_log;