aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Larmour <jlarmour@redhat.co.uk>2000-02-15 23:54:53 -0800
committerRichard Henderson <rth@gcc.gnu.org>2000-02-15 23:54:53 -0800
commit3ea8083fc9062ef5c6f2e97b563ce2e8b3f7a8c6 (patch)
treef50c2625d7ae54acdbe802acaad3b0628f04ef06
parentba96c72d6baddf4dec4515c6f7fa57716440913b (diff)
downloadgcc-3ea8083fc9062ef5c6f2e97b563ce2e8b3f7a8c6.zip
gcc-3ea8083fc9062ef5c6f2e97b563ce2e8b3f7a8c6.tar.gz
gcc-3ea8083fc9062ef5c6f2e97b563ce2e8b3f7a8c6.tar.bz2
Jonathan Larmour <jlarmour@redhat.co.uk>:
Add new __GNUC_PATCHLEVEL__ define. From-SVN: r32004
-rw-r--r--gcc/ChangeLog33
-rw-r--r--gcc/ch/ChangeLog4
-rw-r--r--gcc/ch/lang-specs.h2
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/lang-specs.h11
-rw-r--r--gcc/cpp.16
-rw-r--r--gcc/cpp.texi19
-rw-r--r--gcc/f/ChangeLog4
-rw-r--r--gcc/f/lang-specs.h4
-rw-r--r--gcc/flow.c422
-rw-r--r--gcc/gcc.c40
-rw-r--r--gcc/toplev.c1
12 files changed, 282 insertions, 268 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a96ad73..62d5ec7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2000-02-15 Jonathan Larmour <jlarmour@redhat.co.uk>
+
+ * gcc.c (default_compilers): Add new __GNUC_PATCHLEVEL__ define
+ to default cpp spec.
+ (do_spec_1): Add support for %v3 spec used by __GNUC_PATCHLEVEL__.
+ * cpp.texi: Document __GNUC_PATCHLEVEL__.
+ * cpp.1: Likewise.
+
+ * objc/lang-specs.h: Add new __GNUC_PATCHLEVEL__ define to
+ default spec.
+
2000-02-15 Denis Chertykov <denisc@overta.ru>
* configure.in: Add support for avr target.
@@ -32,7 +43,7 @@ Tue Feb 15 23:22:26 2000 Andrew Haley <aph@cygnus.com>
* config/sh/sh.h: Correct comment about macros.
Tue Feb 15 22:30:36 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
- Andrew MacLeod <amacleod@cygnus.com>
+ Andrew MacLeod <amacleod@cygnus.com>
* Makefile.in (lcm.o): Depend on insn-attr.h.
* basic-block.h (optimize_mode_switching): Declare.
@@ -127,7 +138,7 @@ Tue Feb 15 22:30:36 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
to import the frames themselves.
Mon Feb 14 13:31:01 2000 Stan Cox <scox@cygnus.com>
- Jason Eckhardt <jle@cygnus.com>
+ Jason Eckhardt <jle@cygnus.com>
* basic_block.h: Added prototype for reorder_basic_blocks.
* toplev.c: Changes to add -freorder-blocks and graph dump after
@@ -226,28 +237,28 @@ Sat Feb 12 01:44:26 MET 2000 Jan Hubicka <jh@suse.cz>
two types have compatable, arm specific, attributes.
* config/arm/arm.h (CUMULATIVE_ARGS): Redefine to be a
- structure.
+ structure.
(FUNCTION_ARG): Redefine to call arm_function_arg.
(FUNCTION_ARG_PARTIAL_NREGS): Redefine to use correct
- structure field.
+ structure field.
(INIT_CUMULATIVE_ARGS): Redefine to call
- arm_init_cumulative_args.
+ arm_init_cumulative_args.
(FUNCTION_ARG_ADVANCE): Redefine to use correct structure
- field.
+ field.
(SETUP_INCOMING_VARARGS): Redefine to use correct structure
- field.
+ field.
(ARM_MARK_NEARBY_FUNCTION): New macro: Mark already compiled
- functions.
+ functions.
(ENCODE_SECTION): Add call to ARM_MARK_NEARBY_FUNCTION.
(VALID_MACHINE_TYPE_ATTRIBUTE): Define.
(COMP_TYPE_ATTRIBUTES): Define.
* config/arm/arm.md (call): Call arm_is_long_call_p to decide
- if a long call is needed.
+ if a long call is needed.
(call_value): Call arm_is_long_call_p to decide if a long call
- is needed.
+ is needed.
(call_symbol): Call arm_is_long_call_p to decide if a long call
- is needed.
+ is needed.
* config/arm/arm-protos.h: Add prototype for arm_is_long_call_p.
diff --git a/gcc/ch/ChangeLog b/gcc/ch/ChangeLog
index 269b600..896b7c6 100644
--- a/gcc/ch/ChangeLog
+++ b/gcc/ch/ChangeLog
@@ -1,3 +1,7 @@
+2000-02-15 Jonathan Larmour <jlarmour@redhat.co.uk>
+
+ * lang-specs.h: Add new __GNUC_PATCHLEVEL__ define to default spec.
+
2000-02-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* grant.c: Don't declare `version_string'.
diff --git a/gcc/ch/lang-specs.h b/gcc/ch/lang-specs.h
index ba946d3..1b377f5 100644
--- a/gcc/ch/lang-specs.h
+++ b/gcc/ch/lang-specs.h
@@ -26,7 +26,7 @@ Boston, MA 02111-1307, USA. */
{"@chill",
{"cpp -lang-chill %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU CHILL does not support -C without using -E}}\
- %{!no-gcc:-D__GNUCHILL__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{!no-gcc:-D__GNUCHILL__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:-D__OPTIMIZE__} %{traditional} %{ftraditional:-traditional}\
%{traditional-cpp:-traditional} %{!undef:%{!ansi:%p} %P} %{trigraphs}\
%{g*} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*} %{U*} %{i*} %Z\
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 927ea7d..3c0254d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,7 @@
+2000-02-15 Jonathan Larmour <jlarmour@redhat.co.uk>
+
+ * lang-specs.h: Add new __GNUC_PATCHLEVEL__ define to default spec.
+
2000-01-16 Gabriel Dos Reis <gdr@codesourcery.com>
* decl2.c (lang_decode_option): Enable automatic line wrapping.
diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index 558480e..630641c 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -33,8 +33,8 @@ Boston, MA 02111-1307, USA. */
"%{E|M|MM:cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C++ does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\
- -D__cplusplus\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2\
+ -D__GNUC_PATCHLEVEL__=%v3} -D__cplusplus\
%{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
%{!fno-exceptions:-D__EXCEPTIONS}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} %{trigraphs}\
@@ -46,7 +46,8 @@ Boston, MA 02111-1307, USA. */
-lang-c++ %{nostdinc*} %{C} %{A*} %{I*} %{P} %{$} %I\
%{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
%{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1\
- -D__GNUC_MINOR__=%v2} -D__cplusplus\
+ -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
+ -D__cplusplus\
%{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
%{!fno-exceptions:-D__EXCEPTIONS}\
%{fnew-abi:-D__GXX_ABI_VERSION=100}\
@@ -68,8 +69,8 @@ Boston, MA 02111-1307, USA. */
{"cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C++ does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\
- -D__cplusplus\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2\
+ -D__GNUC_PATCHLEVEL__=%v3} -D__cplusplus\
%{ansi:-trigraphs -D__STRICT_ANSI__} %{!undef:%{!ansi:%p} %P}\
%{!fno-exceptions:-D__EXCEPTIONS}\
%{fnew-abi:-D__GXX_ABI_VERSION=100}\
diff --git a/gcc/cpp.1 b/gcc/cpp.1
index d51ae74..2f65cf3 100644
--- a/gcc/cpp.1
+++ b/gcc/cpp.1
@@ -401,9 +401,9 @@ wins.
.Ip "\fB\-undef\fR" 4
Do not predefine any nonstandard macros.
.Ip "\fB\-gcc\fR" 4
-Define the macros \fI_\|_GNUC_\|_\fR and \fI_\|_GNUC_MINOR_\|_\fR. These are
-defined automatically when you use \fBgcc \-E\fR; you can turn them off
-in that case with \fB\-no-gcc\fR.
+Define the macros \fI_\|_GNUC_\|_\fR, \fI_\|_GNUC_MINOR_\|_\fR and
+\fI_\|_GNUC_PATCHLEVEL_\|_\fR. These are defined automatically when you
+use \fBgcc \-E\fR; you can turn them off in that case with \fB\-no-gcc\fR.
.Ip "\fB\-A \fIpredicate\fR(\fIanswer\fR)\fR" 4
Make an assertion with the predicate \fIpredicate\fR and answer
\fIanswer\fR.
diff --git a/gcc/cpp.texi b/gcc/cpp.texi
index 5751722..f7a0dc9 100644
--- a/gcc/cpp.texi
+++ b/gcc/cpp.texi
@@ -978,9 +978,16 @@ The macro contains the minor version number of the compiler. This can
be used to work around differences between different releases of the
compiler (for example, if gcc 2.6.3 is known to support a feature, you
can test for @code{__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6)}).
-The last number, @samp{3} in the
-example above, denotes the bugfix level of the compiler; no macro
-contains this value.
+
+@item __GNUC_PATCHLEVEL__
+@findex __GNUC_PATCHLEVEL__
+This macro contains the patch level of the compiler. This can be
+used to work around differences between different patch level releases
+of the compiler (for example, if gcc 2.6.2 is known to contain a bug,
+whereas gcc 2.6.3 contains a fix, and you have code which can workaround
+ths problem depending on whether the bug is fixed or not, you can test for
+@code{__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6) ||
+(__GNUC__ == 2 && __GNUC_MINOR__ == 6 && __GNUC_PATCHLEVEL__ > 3)}).
@item __GNUG__
@findex __GNUG__
@@ -2870,9 +2877,9 @@ Do not predefine any nonstandard macros.
@item -gcc
@findex -gcc
-Define the macros @var{__GNUC__} and @var{__GNUC_MINOR__}. These are
-defined automatically when you use @samp{gcc -E}; you can turn them off
-in that case with @samp{-no-gcc}.
+Define the macros @var{__GNUC__}, @var{__GNUC_MINOR__} and
+@var{__GNUC_PATCHLEVEL__}. These are defined automatically when you use
+@samp{gcc -E}; you can turn them off in that case with @samp{-no-gcc}.
@item -A @var{predicate}(@var{answer})
@findex -A
diff --git a/gcc/f/ChangeLog b/gcc/f/ChangeLog
index 68e748e..a3fdb9b 100644
--- a/gcc/f/ChangeLog
+++ b/gcc/f/ChangeLog
@@ -1,3 +1,7 @@
+2000-02-15 Jonathan Larmour <jlarmour@redhat.co.uk>
+
+ * lang-specs.h: Add new __GNUC_PATCHLEVEL__ define to default spec.
+
Tue Feb 15 11:14:17 2000 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* g77spec.c: Don't declare `version_string'.
diff --git a/gcc/f/lang-specs.h b/gcc/f/lang-specs.h
index 924802e..4ee0320 100644
--- a/gcc/f/lang-specs.h
+++ b/gcc/f/lang-specs.h
@@ -38,7 +38,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
{"cpp -lang-fortran %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
%{ansi:-trigraphs -$ -D__STRICT_ANSI__}\
%{!undef:%P} -D_LANGUAGE_FORTRAN %{trigraphs} \
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} -traditional\
@@ -88,7 +88,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
{"cpp -lang-fortran %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I \
%{C:%{!E:%eGNU C does not support -C without using -E}} \
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} \
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2} \
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3} \
%{ansi:-trigraphs -$ -D__STRICT_ANSI__} \
%{!undef:%P} -D_LANGUAGE_FORTRAN %{trigraphs} \
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}} -traditional \
diff --git a/gcc/flow.c b/gcc/flow.c
index 781a657..6c4c953 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -274,12 +274,6 @@ varray_type basic_block_for_insn;
static rtx label_value_list;
-/* INSN_VOLATILE (insn) is 1 if the insn refers to anything volatile. */
-
-#define INSN_VOLATILE(INSN) bitmap_bit_p (uid_volatile, INSN_UID (INSN))
-#define SET_INSN_VOLATILE(INSN) bitmap_set_bit (uid_volatile, INSN_UID (INSN))
-static bitmap uid_volatile;
-
/* Forward declarations */
static int count_basic_blocks PARAMS ((rtx));
static rtx find_basic_blocks_1 PARAMS ((rtx));
@@ -316,11 +310,11 @@ static void verify_wide_reg PARAMS ((int, rtx, rtx));
static void verify_local_live_at_start PARAMS ((regset, basic_block));
static int set_noop_p PARAMS ((rtx));
static int noop_move_p PARAMS ((rtx));
-static void notice_stack_pointer_modification PARAMS ((rtx, rtx, void *));
-static void record_volatile_insns PARAMS ((rtx));
+static void delete_noop_moves PARAMS ((rtx));
+static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
+static void notice_stack_pointer_modification PARAMS ((rtx));
static void mark_reg PARAMS ((rtx, void *));
static void mark_regs_live_at_end PARAMS ((regset));
-static void life_analysis_1 PARAMS ((rtx, int, int));
static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int));
static void propagate_block PARAMS ((basic_block, regset,
regset, int));
@@ -2460,27 +2454,25 @@ life_analysis (f, nregs, file, remove_dead_code)
FILE *file;
int remove_dead_code;
{
+ register int i;
#ifdef ELIMINABLE_REGS
- register size_t i;
static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
#endif
int flags;
-
+ sbitmap all_blocks;
+
/* Record which registers will be eliminated. We use this in
mark_used_regs. */
CLEAR_HARD_REG_SET (elim_reg_set);
#ifdef ELIMINABLE_REGS
- for (i = 0; i < sizeof eliminables / sizeof eliminables[0]; i++)
+ for (i = 0; i < (int) (sizeof eliminables / sizeof eliminables[0]); i++)
SET_HARD_REG_BIT (elim_reg_set, eliminables[i].from);
#else
SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
#endif
- /* Allocate a bitmap to be filled in by record_volatile_insns. */
- uid_volatile = BITMAP_XMALLOC ();
-
/* We want alias analysis information for local dead store elimination. */
init_alias_analysis ();
@@ -2492,17 +2484,53 @@ life_analysis (f, nregs, file, remove_dead_code)
if (! remove_dead_code)
flags &= ~(PROP_SCAN_DEAD_CODE | PROP_KILL_DEAD_CODE);
}
- life_analysis_1 (f, nregs, flags);
+ /* The post-reload life analysis have (on a global basis) the same
+ registers live as was computed by reload itself. elimination
+ Otherwise offsets and such may be incorrect.
+
+ Reload will make some registers as live even though they do not
+ appear in the rtl. */
+ if (reload_completed)
+ flags &= ~PROP_REG_INFO;
+
+ max_regno = nregs;
+
+ /* Always remove no-op moves. Do this before other processing so
+ that we don't have to keep re-scanning them. */
+ delete_noop_moves (f);
+
+ /* Some targets can emit simpler epilogues if they know that sp was
+ not ever modified during the function. After reload, of course,
+ we've already emitted the epilogue so there's no sense searching. */
if (! reload_completed)
- mark_constant_function ();
+ notice_stack_pointer_modification (f);
+
+ /* Allocate and zero out data structures that will record the
+ data from lifetime analysis. */
+ allocate_reg_life_data ();
+ allocate_bb_life_data ();
+ reg_next_use = (rtx *) xcalloc (nregs, sizeof (rtx));
+ all_blocks = sbitmap_alloc (n_basic_blocks);
+ sbitmap_ones (all_blocks);
+
+ /* Find the set of registers live on function exit. */
+ mark_regs_live_at_end (EXIT_BLOCK_PTR->global_live_at_start);
+
+ /* "Update" life info from zero. It'd be nice to begin the
+ relaxation with just the exit and noreturn blocks, but that set
+ is not immediately handy. */
+ update_life_info (all_blocks, UPDATE_LIFE_GLOBAL, flags);
+ /* Clean up. */
+ sbitmap_free (all_blocks);
+ free (reg_next_use);
+ reg_next_use = NULL;
end_alias_analysis ();
if (file)
dump_flow_info (file);
- BITMAP_XFREE (uid_volatile);
free_basic_block_vars (1);
}
@@ -2581,7 +2609,7 @@ verify_local_live_at_start (new_live_at_start, bb)
}
}
-/* Updates death notes starting with the basic blocks set in BLOCKS.
+/* Updates life information starting with the basic blocks set in BLOCKS.
If LOCAL_ONLY, such as after splitting or peepholeing, we are only
expecting local modifications to basic blocks. If we find extra
@@ -2596,8 +2624,8 @@ verify_local_live_at_start (new_live_at_start, bb)
BLOCK_FOR_INSN is assumed to be correct.
- ??? PROP_FLAGS should not contain PROP_LOG_LINKS. Need to set up
- reg_next_use for that. Including PROP_REG_INFO does not refresh
+ PROP_FLAGS should not contain PROP_LOG_LINKS unless the caller sets
+ up reg_next_use. Including PROP_REG_INFO does not properly refresh
regs_ever_live unless the caller resets it to zero. */
void
@@ -2634,6 +2662,35 @@ update_life_info (blocks, extent, prop_flags)
});
FREE_REG_SET (tmp);
+
+ if (prop_flags & PROP_REG_INFO)
+ {
+ /* The only pseudos that are live at the beginning of the function
+ are those that were not set anywhere in the function. local-alloc
+ doesn't know how to handle these correctly, so mark them as not
+ local to any one basic block. */
+ EXECUTE_IF_SET_IN_REG_SET (ENTRY_BLOCK_PTR->global_live_at_end,
+ FIRST_PSEUDO_REGISTER, i,
+ { REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL; });
+
+ /* We have a problem with any pseudoreg that lives across the setjmp.
+ ANSI says that if a user variable does not change in value between
+ the setjmp and the longjmp, then the longjmp preserves it. This
+ includes longjmp from a place where the pseudo appears dead.
+ (In principle, the value still exists if it is in scope.)
+ If the pseudo goes in a hard reg, some other value may occupy
+ that hard reg where this pseudo is dead, thus clobbering the pseudo.
+ Conclusion: such a pseudo must not go in a hard reg. */
+ EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
+ FIRST_PSEUDO_REGISTER, i,
+ {
+ if (regno_reg_rtx[i] != 0)
+ {
+ REG_LIVE_LENGTH (i) = -1;
+ REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
+ }
+ });
+ }
}
/* Free the variables allocated by find_basic_blocks.
@@ -2670,18 +2727,17 @@ set_noop_p (set)
{
rtx src = SET_SRC (set);
rtx dst = SET_DEST (set);
- if (GET_CODE (src) == REG && GET_CODE (dst) == REG
- && REGNO (src) == REGNO (dst))
- return 1;
- if (GET_CODE (src) != SUBREG || GET_CODE (dst) != SUBREG
- || SUBREG_WORD (src) != SUBREG_WORD (dst))
- return 0;
- src = SUBREG_REG (src);
- dst = SUBREG_REG (dst);
- if (GET_CODE (src) == REG && GET_CODE (dst) == REG
- && REGNO (src) == REGNO (dst))
- return 1;
- return 0;
+
+ if (GET_CODE (src) == SUBREG && GET_CODE (dst) == SUBREG)
+ {
+ if (SUBREG_WORD (src) != SUBREG_WORD (dst))
+ return 0;
+ src = SUBREG_REG (src);
+ dst = SUBREG_REG (dst);
+ }
+
+ return (GET_CODE (src) == REG && GET_CODE (dst) == REG
+ && REGNO (src) == REGNO (dst));
}
/* Return nonzero if an insn consists only of SETs, each of which only sets a
@@ -2721,8 +2777,29 @@ noop_move_p (insn)
return 0;
}
+/* Delete any insns that copy a register to itself. */
+
+static void
+delete_noop_moves (f)
+ rtx f;
+{
+ rtx insn;
+ for (insn = f; insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) == INSN && noop_move_p (insn))
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
+ }
+}
+
+/* Determine if the stack pointer is constant over the life of the function.
+ Only useful before prologues have been emitted. */
+
static void
-notice_stack_pointer_modification (x, pat, data)
+notice_stack_pointer_modification_1 (x, pat, data)
rtx x;
rtx pat ATTRIBUTE_UNUSED;
void *data ATTRIBUTE_UNUSED;
@@ -2740,57 +2817,28 @@ notice_stack_pointer_modification (x, pat, data)
current_function_sp_is_unchanging = 0;
}
-/* Record which insns refer to any volatile memory
- or for any reason can't be deleted just because they are dead stores.
- Also, delete any insns that copy a register to itself.
- And see if the stack pointer is modified. */
static void
-record_volatile_insns (f)
+notice_stack_pointer_modification (f)
rtx f;
{
rtx insn;
+
+ /* Assume that the stack pointer is unchanging if alloca hasn't
+ been used. */
+ current_function_sp_is_unchanging = !current_function_calls_alloca;
+ if (! current_function_sp_is_unchanging)
+ return;
+
for (insn = f; insn; insn = NEXT_INSN (insn))
{
- enum rtx_code code1 = GET_CODE (insn);
- if (code1 == CALL_INSN)
- SET_INSN_VOLATILE (insn);
- else if (code1 == INSN || code1 == JUMP_INSN)
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
- if (GET_CODE (PATTERN (insn)) != USE
- && volatile_refs_p (PATTERN (insn)))
- SET_INSN_VOLATILE (insn);
-
- /* A SET that makes space on the stack cannot be dead.
- (Such SETs occur only for allocating variable-size data,
- so they will always have a PLUS or MINUS according to the
- direction of stack growth.)
- Even if this function never uses this stack pointer value,
- signal handlers do! */
- else if (code1 == INSN && GET_CODE (PATTERN (insn)) == SET
- && SET_DEST (PATTERN (insn)) == stack_pointer_rtx
-#ifdef STACK_GROWS_DOWNWARD
- && GET_CODE (SET_SRC (PATTERN (insn))) == MINUS
-#else
- && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
-#endif
- && XEXP (SET_SRC (PATTERN (insn)), 0) == stack_pointer_rtx)
- SET_INSN_VOLATILE (insn);
-
- /* Delete (in effect) any obvious no-op moves. */
- else if (noop_move_p (insn))
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
+ /* Check if insn modifies the stack pointer. */
+ note_stores (PATTERN (insn), notice_stack_pointer_modification_1,
+ NULL);
+ if (! current_function_sp_is_unchanging)
+ return;
}
-
- /* Check if insn modifies the stack pointer. */
- if ( current_function_sp_is_unchanging
- && GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- note_stores (PATTERN (insn),
- notice_stack_pointer_modification,
- NULL);
}
}
@@ -2882,117 +2930,6 @@ mark_regs_live_at_end (set)
diddle_return_value (mark_reg, set);
}
-/* Determine which registers are live at the start of each
- basic block of the function whose first insn is F.
- NREGS is the number of registers used in F.
- We allocate the vector basic_block_live_at_start
- and the regsets that it points to, and fill them with the data.
- regset_size and regset_bytes are also set here. */
-
-static void
-life_analysis_1 (f, nregs, flags)
- rtx f;
- int nregs;
- int flags;
-{
- char save_regs_ever_live[FIRST_PSEUDO_REGISTER];
- register int i;
-
- max_regno = nregs;
-
- /* Allocate and zero out many data structures
- that will record the data from lifetime analysis. */
-
- allocate_reg_life_data ();
- allocate_bb_life_data ();
-
- reg_next_use = (rtx *) xcalloc (nregs, sizeof (rtx));
-
- /* Assume that the stack pointer is unchanging if alloca hasn't been used.
- This will be cleared by record_volatile_insns if it encounters an insn
- which modifies the stack pointer. */
- current_function_sp_is_unchanging = !current_function_calls_alloca;
- record_volatile_insns (f);
-
- /* Find the set of registers live on function exit. Do this before
- zeroing regs_ever_live, as we use that data post-reload. */
- mark_regs_live_at_end (EXIT_BLOCK_PTR->global_live_at_start);
-
- /* The post-reload life analysis have (on a global basis) the same
- registers live as was computed by reload itself. elimination
- Otherwise offsets and such may be incorrect.
-
- Reload will make some registers as live even though they do not
- appear in the rtl. */
- if (reload_completed)
- memcpy (save_regs_ever_live, regs_ever_live, sizeof (regs_ever_live));
- memset (regs_ever_live, 0, sizeof regs_ever_live);
-
- /* Compute register life at block boundaries. It'd be nice to
- begin with just the exit and noreturn blocks, but that set
- is not immediately handy. */
- {
- sbitmap blocks;
- blocks = sbitmap_alloc (n_basic_blocks);
- sbitmap_ones (blocks);
- calculate_global_regs_live (blocks, blocks, flags & PROP_SCAN_DEAD_CODE);
- sbitmap_free (blocks);
- }
-
- /* The only pseudos that are live at the beginning of the function are
- those that were not set anywhere in the function. local-alloc doesn't
- know how to handle these correctly, so mark them as not local to any
- one basic block. */
-
- EXECUTE_IF_SET_IN_REG_SET (ENTRY_BLOCK_PTR->global_live_at_end,
- FIRST_PSEUDO_REGISTER, i,
- { REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL; });
-
- /* Now the life information is accurate. Make one more pass over each
- basic block to delete dead stores, create autoincrement addressing
- and record how many times each register is used, is set, or dies. */
- {
- regset tmp;
- tmp = ALLOCA_REG_SET ();
-
- for (i = n_basic_blocks - 1; i >= 0; --i)
- {
- basic_block bb = BASIC_BLOCK (i);
-
- COPY_REG_SET (tmp, bb->global_live_at_end);
- propagate_block (bb, tmp, (regset) NULL, flags);
- }
-
- FREE_REG_SET (tmp);
- }
-
- /* We have a problem with any pseudoreg that lives across the setjmp.
- ANSI says that if a user variable does not change in value between
- the setjmp and the longjmp, then the longjmp preserves it. This
- includes longjmp from a place where the pseudo appears dead.
- (In principle, the value still exists if it is in scope.)
- If the pseudo goes in a hard reg, some other value may occupy
- that hard reg where this pseudo is dead, thus clobbering the pseudo.
- Conclusion: such a pseudo must not go in a hard reg. */
- EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
- FIRST_PSEUDO_REGISTER, i,
- {
- if (regno_reg_rtx[i] != 0)
- {
- REG_LIVE_LENGTH (i) = -1;
- REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
- }
- });
-
- /* Restore regs_ever_live that was provided by reload. */
- if (reload_completed)
- memcpy (regs_ever_live, save_regs_ever_live, sizeof (regs_ever_live));
-
- /* Clean up. */
- free (reg_next_use);
- reg_next_use = NULL;
-}
-
/* Propagate global life info around the graph of basic blocks. Begin
considering blocks with their corresponding bit set in BLOCKS_IN.
BLOCKS_OUT is set for every block that was changed. */
@@ -3289,11 +3226,8 @@ propagate_block (bb, old, significant, flags)
if (flags & PROP_SCAN_DEAD_CODE)
{
- insn_is_dead = (insn_dead_p (PATTERN (insn), old, 0,
- REG_NOTES (insn))
- /* Don't delete something that refers to
- volatile storage! */
- && ! INSN_VOLATILE (insn));
+ insn_is_dead = insn_dead_p (PATTERN (insn), old, 0,
+ REG_NOTES (insn));
libcall_is_dead = (insn_is_dead && note != 0
&& libcall_dead_p (PATTERN (insn), old,
note, insn));
@@ -3576,18 +3510,29 @@ insn_dead_p (x, needed, call_ok, notes)
{
rtx r = SET_DEST (x);
- /* A SET that is a subroutine call cannot be dead. */
- if (! call_ok && GET_CODE (SET_SRC (x)) == CALL)
- return 0;
-
#ifdef HAVE_cc0
if (GET_CODE (r) == CC0)
return ! cc0_live;
#endif
- if (GET_CODE (r) == MEM && ! MEM_VOLATILE_P (r))
+ /* A SET that is a subroutine call cannot be dead. */
+ if (GET_CODE (SET_SRC (x)) == CALL)
+ {
+ if (! call_ok)
+ return 0;
+ }
+
+ /* Don't eliminate loads from volatile memory or volatile asms. */
+ else if (volatile_refs_p (SET_SRC (x)))
+ return 0;
+
+ if (GET_CODE (r) == MEM)
{
rtx temp;
+
+ if (MEM_VOLATILE_P (r))
+ return 0;
+
/* Walk the set of memory locations we are currently tracking
and see if one is an identical match to this memory location.
If so, this memory write is dead (remember, we're walking
@@ -3600,52 +3545,68 @@ insn_dead_p (x, needed, call_ok, notes)
temp = XEXP (temp, 1);
}
}
+ else
+ {
+ while (GET_CODE (r) == SUBREG
+ || GET_CODE (r) == STRICT_LOW_PART
+ || GET_CODE (r) == ZERO_EXTRACT)
+ r = XEXP (r, 0);
- while (GET_CODE (r) == SUBREG || GET_CODE (r) == STRICT_LOW_PART
- || GET_CODE (r) == ZERO_EXTRACT)
- r = XEXP (r, 0);
+ if (GET_CODE (r) == REG)
+ {
+ int regno = REGNO (r);
- if (GET_CODE (r) == REG)
- {
- int regno = REGNO (r);
+ /* Obvious. */
+ if (REGNO_REG_SET_P (needed, regno))
+ return 0;
+
+ /* If this is a hard register, verify that subsequent
+ words are not needed. */
+ if (regno < FIRST_PSEUDO_REGISTER)
+ {
+ int n = HARD_REGNO_NREGS (regno, GET_MODE (r));
+
+ while (--n > 0)
+ if (REGNO_REG_SET_P (needed, regno+n))
+ return 0;
+ }
+
+ /* Don't delete insns to set global regs. */
+ if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
+ return 0;
+
+ /* Make sure insns to set the stack pointer aren't deleted. */
+ if (regno == STACK_POINTER_REGNUM)
+ return 0;
- /* Don't delete insns to set global regs. */
- if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
- /* Make sure insns to set frame pointer aren't deleted. */
- || (regno == FRAME_POINTER_REGNUM
+ /* Make sure insns to set the frame pointer aren't deleted. */
+ if (regno == FRAME_POINTER_REGNUM
&& (! reload_completed || frame_pointer_needed))
+ return 0;
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || (regno == HARD_FRAME_POINTER_REGNUM
+ if (regno == HARD_FRAME_POINTER_REGNUM
&& (! reload_completed || frame_pointer_needed))
+ return 0;
#endif
+
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* Make sure insns to set arg pointer are never deleted
- (if the arg pointer isn't fixed, there will be a USE for
- it, so we can treat it normally). */
- || (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
+ (if the arg pointer isn't fixed, there will be a USE
+ for it, so we can treat it normally). */
+ if (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
+ return 0;
#endif
- || REGNO_REG_SET_P (needed, regno))
- return 0;
- /* If this is a hard register, verify that subsequent words are
- not needed. */
- if (regno < FIRST_PSEUDO_REGISTER)
- {
- int n = HARD_REGNO_NREGS (regno, GET_MODE (r));
-
- while (--n > 0)
- if (REGNO_REG_SET_P (needed, regno+n))
- return 0;
+ /* Otherwise, the set is dead. */
+ return 1;
}
-
- return 1;
}
}
- /* If performing several activities,
- insn is dead if each activity is individually dead.
- Also, CLOBBERs and USEs can be ignored; a CLOBBER or USE
- that's inside a PARALLEL doesn't make the insn worth keeping. */
+ /* If performing several activities, insn is dead if each activity
+ is individually dead. Also, CLOBBERs and USEs can be ignored; a
+ CLOBBER or USE that's inside a PARALLEL doesn't make the insn
+ worth keeping. */
else if (code == PARALLEL)
{
int i = XVECLEN (x, 0);
@@ -4451,7 +4412,8 @@ mark_used_regs (needed, live, x, flags, insn)
it was allocated to the pseudos. If the register will not
be eliminated, reload will set it live at that point. */
- if (! TEST_HARD_REG_BIT (elim_reg_set, regno))
+ if ((flags & PROP_REG_INFO)
+ && ! TEST_HARD_REG_BIT (elim_reg_set, regno))
regs_ever_live[regno] = 1;
return;
}
diff --git a/gcc/gcc.c b/gcc/gcc.c
index b8f3ddb..24a7d2c 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -327,9 +327,11 @@ or with constant text in a single argument.
%Y Output the accumulated assembler options specified by compilations.
%Z Output the accumulated preprocessor options specified by compilations.
%v1 Substitute the major version number of GCC.
- (For version 2.5.n, this is 2.)
+ (For version 2.5.3, this is 2.)
%v2 Substitute the minor version number of GCC.
- (For version 2.5.n, this is 5.)
+ (For version 2.5.3, this is 5.)
+ %v3 Substitute the patch level number of GCC.
+ (For version 2.5.3, this is 3.)
%a process ASM_SPEC as a spec.
This allows config.h to specify part of the spec for running as.
%A process ASM_FINAL_SPEC as a spec. A capital A is actually
@@ -614,7 +616,7 @@ static struct compiler default_compilers[] =
%{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
%{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
%{ffast-math:-D__FAST_MATH__}\
@@ -628,7 +630,7 @@ static struct compiler default_compilers[] =
%{std*} %{nostdinc*} %{A*} %{I*} %I\
%{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
%{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
%{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
%{ffast-math:-D__FAST_MATH__}\
@@ -651,7 +653,7 @@ static struct compiler default_compilers[] =
%{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
%{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
%{ffast-math:-D__FAST_MATH__}\
@@ -679,7 +681,7 @@ static struct compiler default_compilers[] =
%{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
%{!undef:%{!ansi:%{!std=*:%p}%{std=gnu*:%p}} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
%{ffast-math:-D__FAST_MATH__}\
@@ -696,7 +698,7 @@ static struct compiler default_compilers[] =
cpp %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\
%{C:%{!E:%eGNU C does not support -C without using -E}}\
%{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\
- %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\
+ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2 -D__GNUC_PATCHLEVEL__=%v3}\
%{!undef:%{!std=*:%p}%{std=gnu*:%p} %P} %{trigraphs}\
%c %{Os:-D__OPTIMIZE_SIZE__} %{O*:%{!O0:-D__OPTIMIZE__}}\
%{ffast-math:-D__FAST_MATH__}\
@@ -4497,6 +4499,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
int c1 = *p++; /* Select first or second version number. */
char *v = compiler_version;
char *q;
+ static const char zeroc = '0';
/* The format of the version string is
([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */
@@ -4508,7 +4511,7 @@ do_spec_1 (spec, inswitch, soft_matched_part)
abort ();
/* If desired, advance to second version number. */
- if (c1 == '2')
+ if (c1 >= '2')
{
/* Set V after the first period. */
while (ISDIGIT (*v))
@@ -4518,6 +4521,19 @@ do_spec_1 (spec, inswitch, soft_matched_part)
v++;
}
+ /* If desired, advance to third version number.
+ But don't complain if it's not present */
+ if (c1 == '3')
+ {
+ /* Set V after the second period. */
+ while (ISDIGIT (*v))
+ v++;
+ if ((*v != 0) && (*v != ' ') && (*v != '.') && (*v != '-'))
+ abort ();
+ if (*v != 0)
+ v++;
+ }
+
/* Set Q at the next period or at the end. */
q = v;
while (ISDIGIT (*q))
@@ -4525,8 +4541,12 @@ do_spec_1 (spec, inswitch, soft_matched_part)
if (*q != 0 && *q != ' ' && *q != '.' && *q != '-')
abort ();
- /* Put that part into the command. */
- obstack_grow (&obstack, v, q - v);
+ if (q > v)
+ /* Put that part into the command. */
+ obstack_grow (&obstack, v, q - v);
+ else
+ /* Default to "0" */
+ obstack_grow (&obstack, &zeroc, 1);
arg_going = 1;
}
break;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 42e47a4..ebdd212 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3237,6 +3237,7 @@ rest_of_compilation (decl)
if (optimize)
calculate_loop_depth (rtl_dump_file);
life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
+ mark_constant_function ();
});
if (warn_uninitialized || extra_warnings)