blob: e99ba671741d807893ddb806e32fad652f2d4e30 [file] [log] [blame]
IMPORTANT: After applying this patch, you must rebuild the
Info documentation derived from the Texinfo files in the
gcc distribution, as this patch does not include patches
to any derived files (due to differences in the way gcc
version 2.7.2.2 is obtained by users). Use the following
command sequence after applying this patch:
cd gcc-2.7.2.2; make -f Makefile.in gcc.info
If that fails due to `makeinfo' not being installed, obtain
texinfo-3.11.tar.gz from a GNU distribution site, unpack,
build, and install it, and try the above command sequence
again.
diff -rcp2N gcc-2.7.2.2/ChangeLog g77-new/ChangeLog
*** gcc-2.7.2.2/ChangeLog Thu Feb 20 19:24:10 1997
--- g77-new/ChangeLog Mon Aug 11 06:48:02 1997
***************
*** 1,2 ****
--- 1,244 ----
+ Sun Aug 10 18:14:24 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ Integrate C front end part of patch for better alias
+ handling from John Carr <jfc@mit.edu>:
+ * c-decl.c (grokdeclarator): Check for RID_RESTRICT
+ flag; diagnose certain misuses; set DECL_RESTRICT as
+ appropriate.
+ * c-lex.c (init_lex): Set up RID_RESTRICT pointer.
+ Unset `restrict' as reserved word.
+ * c-lex.h: Replace RID_NOALIAS with RID_RESTRICT.
+ * c-parse.gperf: Add `restrict' and `__restrict'
+ keywords.
+ * tree.h: Add DECL_RESTRICT flag.
+
+ Sun Aug 10 14:50:30 1997 Jim Wilson <wilson@cygnus.com>
+
+ * sdbout.c (plain_type_1, case ARRAY_TYPE): Verify that TYPE_DOMAIN
+ has integer TYPE_{MAX,MIN}_VALUE before using them.
+
+ Mon Jul 28 15:35:38 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * combine.c (num_sign_bit_copies): Speed up the 961126-1.c
+ case of repeated (neg (neg (neg ...))) so c-torture runs
+ in less time.
+
+ * reload.c (find_reloads_toplev, find_reloads_address):
+ These now return whether replacement by a constant, so
+ caller can know to do other replacements. Currently if
+ caller doesn't want that info and such replacement would
+ happen, we crash so as to investigate the problem and
+ learn more about it. All callers updated.
+ (find_reloads): If pseudo replaced by constant, always
+ update duplicates of it.
+
+ Mon Jul 21 00:00:24 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * fold-const.c (size_binop): Make sure overflows
+ are flagged properly, so as to avoid silently generating
+ bad code for, e.g., a too-large array.
+
+ Sun Jul 13 22:23:14 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * stmt.c (expand_expr_stmt): Must generate code for
+ statements within an expression (gcc's `({ ... )}')
+ even if -fsyntax-only.
+
+ Mon Jun 30 17:23:07 1997 Michael Meissner <meissner@cygnus.com>
+
+ * gcc.c (process_command): If -save-temps and -pipe were specified
+ together, don't do -pipe.
+
+ Thu Jun 26 05:40:46 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * stor-layout.c (get_best_mode): Handle negative bitpos
+ correctly, so caller doesn't get into infinite recursion
+ trying to cope with a spurious VOIDmode.
+
+ Tue Jun 24 19:46:31 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * varasm.c (assemble_variable): If low part of size
+ doesn't fit in an int, variable is too large.
+
+ Sat Jun 21 12:09:00 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * toplev.c (rest_of_compilation): Also temporarily set
+ flag_unroll_all_loops to 0 during first of two calls
+ to loop_optimize, and clean up code a bit to make it
+ easier to read.
+
+ * expr.c (safe_from_p_1, safe_from_p): Fix these to use
+ TREE_SET_CODE instead of TREE_CODE.
+
+ Thu Jun 19 19:30:47 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * config/alpha/alpha.c: Don't include <stamp.h> on
+ GNU Linux machines.
+
+ * config/alpha/elf.c: New file for ELF systems.
+
+ * config/alpha/xm-alpha.h: Don't declare alloca()
+ if it's already a macro (probably defined in stdlib.h).
+
+ * config/alpha/xm-linux.h (HAVE_STRERROR): #define
+ this, according to what various people suggest.
+
+ * config.guess, configure: Make some (hopefully safe)
+ changes, based mostly on gcc-2.8.0-in-development,
+ in the hopes that these make some systems configure
+ "out of the box" more easily, especially Alpha systems.
+
+ Mon Jun 9 04:26:53 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * expr.c (safe_from_p): Don't examine a given SAVE_EXPR
+ node more than once, to avoid combinatorial explosion
+ in complex expressions. Fortran case that triggered
+ this had a complicated *and* complex expression with
+ 293 unique nodes, resulting in 28 minutes of compile
+ time mostly spent in a single top-level safe_from_p()
+ call due to all the redundant SAVE_EXPR traversals.
+ This change reduced the time to around 2 seconds.
+ (safe_from_p_1): New helper function that does almost
+ exactly what the old safe_from_p() did.
+
+ Sun May 18 21:18:48 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * fold-const.c (fold): Clarify why TRUNC_DIV_EXPR
+ and FLOOR_DIV_EXPR aren't rewritten to EXACT_DIV_EXPR,
+ clean up related code.
+
+ Sat May 3 13:53:00 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * config.sub: Change all `i[345]' to `i[3456]' to
+ support Pentium Pro (this change was already made
+ in configure for gcc-2.7.2.2).
+
+ From Toon Moene <toon@moene.indiv.nluug.nl>:
+ * toplev.c (rest_of_compilation): Unroll loops
+ only the final time through loop optimization.
+
+ Sun Apr 20 10:45:35 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * final.c (profile_function): Only call ASM_OUTPUT_REG_{PUSH,POP}
+ if defined.
+
+ Wed Apr 16 22:26:16 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * alias.c, cse.c, loop.c, rtl.c, rtl.h, sched.c:
+ Make changes submitted by <jfc@mit.edu>.
+
+ Sun Apr 13 19:32:53 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * fold-const.c (fold): If extra warnings enabled,
+ warn about integer division by zero.
+
+ Sun Apr 13 08:15:31 1997 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
+
+ * final.c (profile_function): Save the static chain register
+ around the call to the profiler function.
+
+ Sat Apr 12 14:56:42 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * unroll.c (find_splittable_givs): Permit more cases
+ of mult_val/add_val to agree by using rtx_equal_p
+ to compare them instead of requiring them to be
+ integers with the same value. Also don't bother
+ checking if ADDRESS_COST not defined (they will be
+ equal in that case).
+
+ Fri Apr 11 03:30:04 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * unroll.c (find_splittable_givs): Must create a new
+ register if the mult_val and add_val fields don't
+ agree.
+
+ Fri Apr 4 23:00:55 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * fold-const.c (fold): Don't call multiple_of_p if
+ arg1 is constant zero, to avoid crashing; simplify
+ code accordingly.
+
+ Wed Feb 26 13:09:33 1997 Michael Meissner <meissner@cygnus.com>
+
+ * reload.c (debug_reload): Fix format string to print
+ reload_nocombine[r].
+
+ Sun Feb 23 15:26:53 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * fold-const.c (multiple_of_p): Clean up and improve.
+ (fold): Clean up invocation of multiple_of_p.
+
+ Sat Feb 8 04:53:27 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ From <jfc@jfc.tiac.net> Fri, 07 Feb 1997 22:02:21 -0500:
+ * alias.c (init_alias_analysis): Reduce amount of time
+ needed to simplify the reg_base_value array in the
+ typical case (especially involving function inlining).
+
+ Fri Jan 10 17:22:17 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ Minor improvements/fixes to better alias handling:
+ * Makefile.in (alias.o): Fix typo in rule (was RLT_H).
+ * cse.c, sched.c: Fix up some indenting.
+ * toplev.c: Add -fargument-alias flag, so Fortran users
+ can turn C-style aliasing on once g77 defaults to
+ -fargument-noalias-global.
+
+ Integrate patch for better alias handling from
+ John Carr <jfc@mit.edu>:
+ * Makefile.in (OBJS, alias.o): New module and rule.
+ * alias.c: New source module.
+ * calls.c (expand_call): Recognize alias status of calls
+ to malloc().
+ * combine.c (distribute_notes): New REG_NOALIAS note.
+ * rtl.h (REG_NOALIAS): Ditto.
+ Many other changes for new alias.c module.
+ * cse.c: Many changes, and much code moved into alias.c.
+ * flags.h (flag_alias_check, flag_argument_noalias):
+ New flags.
+ * toplev.c: New flags and related options.
+ * local-alloc.c (validate_equiv_mem_from_store):
+ Caller of true_dependence changed.
+ * loop.c (NUM_STORES): Increase to 50 from 20.
+ (prescan_loop): "const" functions don't alter unknown addresses.
+ (invariant_p): Caller of true_dependence changed.
+ (record_giv): Zero new unrolled and shared flags.
+ (emit_iv_add_mult): Record base value for register.
+ * sched.c: Many changes, mostly moving code to alias.c.
+ (sched_note_set): SCHED_SORT macro def form, but not function,
+ inexplicably changed.
+ * unroll.c: Record base values for registers, etc.
+
+ Fri Jan 3 04:01:00 1997 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * loop.c (check_final_value): Handle insns with no luid's
+ appropriately, instead of crashing on INSN_LUID macro
+ invocations.
+
+ Mon Dec 23 00:49:19 1996 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * config/alpha/alpha.md: Fix pattern that matches if_then_else
+ involving DF target, DF comparison, SF source.
+
+ Fri Dec 20 15:42:52 1996 Craig Burley <burley@gnu.ai.mit.edu>
+
+ * fold-const.c (multiple_of_p): New function.
+ (fold): Use new function to turn *_DIV_EXPR into EXACT_DIV_EXPR.
+
+ Tue Oct 22 18:32:20 1996 Jim Wilson <wilson@cygnus.com>
+
+ * unroll.c (unroll_loop): Always reject loops with unbalanced blocks.
+
+ Tue Sep 24 19:37:00 1996 Jim Wilson <wilson@cygnus.com>
+
+ * reload.c (push_secondary_reload): Do strip paradoxical SUBREG
+ even if reload_class is CLASS_CANNOT_CHANGE_SIZE. Change reload_mode
+ to mode in SECONDARY_MEMORY_NEEDED and get_secondary_mem calls.
+
+ Mon Aug 5 16:53:36 1996 Doug Evans <dje@fallis.cygnus.com>
+
+ * stor-layout.c (layout_record): Correct overflow test for 0 sized
+ fields.
+
Sat Jun 29 12:33:39 1996 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
*************** Tue Jun 11 20:18:03 1996 Per Bothner <b
*** 8,11 ****
--- 250,259 ----
* alpha.h (FIXPROTO_INIT): Define new macro.
+ Sat May 18 20:17:27 1996 Jim Wilson <wilson@cygnus.com>
+
+ * unroll.c (copy_loop_body): When update split DEST_ADDR giv,
+ check to make sure it was split.
+ (find_splittable_givs): Fix reversed test of verify_addresses result.
+
Fri May 10 18:35:00 1996 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
*************** Mon Feb 19 07:35:07 1996 Torbjorn Granl
*** 66,69 ****
--- 314,322 ----
* rs6000.md (not:SI with assign and compare): Fix typo.
+ Tue Feb 13 17:43:46 1996 Jim Wilson <wilson@cygnus.com>
+
+ * integrate.c (save_constants_in_decl_trees): New function.
+ (save_for_inline_copying, save_for_inline_nocopy): Call it.
+
Wed Jan 24 18:00:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
*************** Tue Jan 16 06:01:28 1996 Thomas Graiche
*** 81,88 ****
--- 334,357 ----
* i386/freebsd.h (ASM_WEAKEN_LABEL): Deleted; not supported.
+ Mon Jan 15 07:22:59 1996 Michel Delval (mfd@ccv.fr)
+
+ * reload.c (find_equiv_reg): Apply single_set, not PATTERN, to WHERE.
+
Sun Jan 7 17:11:11 1996 David Edelsohn <edelsohn@mhpcc.edu>
* collect2.c (scan_libraries): Correct Import File ID interpretation.
+ Mon Jan 1 09:05:07 1996 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+ * local-alloc.c (reg_equiv_replacement): New variable.
+ (memref_referenced_p, case REG): Check for reg_equiv_replacement.
+ (update_equiv_regs): reg_equiv_replacement now file-scope.
+
+ Fri Dec 22 17:29:42 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+ * reload.c (find_valid_class): New function.
+ (push_reload): Use it in cases where a SUBREG and its contents
+ both need to be reloaded.
+
Thu Dec 28 22:24:53 1995 Michael Meissner <meissner@tiktok.cygnus.com>
*************** Mon Dec 18 18:40:34 1995 Jim Wilson <w
*** 99,102 ****
--- 368,376 ----
above.
+ Sun Dec 17 06:37:00 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+ * reload.c (push_secondary_reload): Don't strip paradoxical SUBREG
+ if reload_class is CLASS_CANNOT_CHANGE_SIZE.
+
Sat Dec 16 07:03:33 1995 Philippe De Muyter (phdm@info.ucl.ac.be)
*************** Sat Dec 9 18:05:03 1995 Jim Wilson <w
*** 113,116 ****
--- 387,395 ----
* expr.c (expand_expr, case INDIRECT_REF): Correct typo in May 8
change.
+
+ Fri Dec 8 19:17:30 1995 Mike Meissner <meissner@beauty.cygnus.com>
+
+ * rs6000/rs6000.c (input_operand): Allow any integer constant, not
+ just integers that fit in 1 instruction.
Sun Nov 26 14:47:42 1995 Richard Kenner <kenner@mole.gnu.ai.mit.edu>
diff -rcp2N gcc-2.7.2.2/Makefile.in g77-new/Makefile.in
*** gcc-2.7.2.2/Makefile.in Sun Nov 26 14:44:25 1995
--- g77-new/Makefile.in Sun Aug 10 18:46:06 1997
*************** OBJS = toplev.o version.o tree.o print-t
*** 519,523 ****
integrate.o jump.o cse.o loop.o unroll.o flow.o stupid.o combine.o \
regclass.o local-alloc.o global.o reload.o reload1.o caller-save.o \
! insn-peep.o reorg.o sched.o final.o recog.o reg-stack.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o \
insn-attrtab.o $(out_object_file) getpwd.o convert.o $(EXTRA_OBJS)
--- 519,523 ----
integrate.o jump.o cse.o loop.o unroll.o flow.o stupid.o combine.o \
regclass.o local-alloc.o global.o reload.o reload1.o caller-save.o \
! insn-peep.o reorg.o alias.o sched.o final.o recog.o reg-stack.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o \
insn-attrtab.o $(out_object_file) getpwd.o convert.o $(EXTRA_OBJS)
*************** LIB2FUNCS = _muldi3 _divdi3 _moddi3 _udi
*** 570,574 ****
_fixxfdi _fixunsxfdi _floatdixf _fixunsxfsi \
_fixtfdi _fixunstfdi _floatditf \
! __gcc_bcmp _varargs _eprintf _op_new _op_vnew _new_handler _op_delete \
_op_vdel _bb _shtab _clear_cache _trampoline __main _exit _ctors _eh \
_pure
--- 570,575 ----
_fixxfdi _fixunsxfdi _floatdixf _fixunsxfsi \
_fixtfdi _fixunstfdi _floatditf \
! __gcc_bcmp _varargs __dummy _eprintf \
! _op_new _op_vnew _new_handler _op_delete \
_op_vdel _bb _shtab _clear_cache _trampoline __main _exit _ctors _eh \
_pure
*************** expr.o : expr.c $(CONFIG_H) $(RTL_H) $(T
*** 1179,1183 ****
insn-flags.h insn-codes.h expr.h insn-config.h recog.h output.h \
typeclass.h bytecode.h bc-opcode.h bc-typecd.h bc-typecd.def bc-optab.h \
! bc-emit.h modemap.def
calls.o : calls.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h expr.h insn-codes.h \
insn-flags.h
--- 1180,1184 ----
insn-flags.h insn-codes.h expr.h insn-config.h recog.h output.h \
typeclass.h bytecode.h bc-opcode.h bc-typecd.h bc-typecd.def bc-optab.h \
! bc-emit.h modemap.def hard-reg-set.h
calls.o : calls.c $(CONFIG_H) $(RTL_H) $(TREE_H) flags.h expr.h insn-codes.h \
insn-flags.h
*************** reorg.o : reorg.c $(CONFIG_H) $(RTL_H) c
*** 1238,1241 ****
--- 1239,1243 ----
basic-block.h regs.h insn-config.h insn-attr.h insn-flags.h recog.h \
flags.h output.h
+ alias.o : $(CONFIG_H) $(RTL_H) flags.h hard-reg-set.h regs.h
sched.o : sched.c $(CONFIG_H) $(RTL_H) basic-block.h regs.h hard-reg-set.h \
flags.h insn-config.h insn-attr.h
diff -rcp2N gcc-2.7.2.2/alias.c g77-new/alias.c
*** gcc-2.7.2.2/alias.c Wed Dec 31 19:00:00 1969
--- g77-new/alias.c Thu Jul 10 20:08:43 1997
***************
*** 0 ****
--- 1,996 ----
+ /* Alias analysis for GNU C, by John Carr (jfc@mit.edu).
+ Derived in part from sched.c */
+ #include "config.h"
+ #include "rtl.h"
+ #include "expr.h"
+ #include "regs.h"
+ #include "hard-reg-set.h"
+ #include "flags.h"
+
+ static rtx canon_rtx PROTO((rtx));
+ static int rtx_equal_for_memref_p PROTO((rtx, rtx));
+ static rtx find_symbolic_term PROTO((rtx));
+ static int memrefs_conflict_p PROTO((int, rtx, int, rtx,
+ HOST_WIDE_INT));
+
+ /* Set up all info needed to perform alias analysis on memory references. */
+
+ #define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
+
+ /* reg_base_value[N] gives an address to which register N is related.
+ If all sets after the first add or subtract to the current value
+ or otherwise modify it so it does not point to a different top level
+ object, reg_base_value[N] is equal to the address part of the source
+ of the first set. The value will be a SYMBOL_REF, a LABEL_REF, or
+ (address (reg)) to indicate that the address is derived from an
+ argument or fixed register. */
+ rtx *reg_base_value;
+ unsigned int reg_base_value_size; /* size of reg_base_value array */
+ #define REG_BASE_VALUE(X) \
+ (REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
+
+ /* Vector indexed by N giving the initial (unchanging) value known
+ for pseudo-register N. */
+ rtx *reg_known_value;
+
+ /* Indicates number of valid entries in reg_known_value. */
+ static int reg_known_value_size;
+
+ /* Vector recording for each reg_known_value whether it is due to a
+ REG_EQUIV note. Future passes (viz., reload) may replace the
+ pseudo with the equivalent expression and so we account for the
+ dependences that would be introduced if that happens. */
+ /* ??? This is a problem only on the Convex. The REG_EQUIV notes created in
+ assign_parms mention the arg pointer, and there are explicit insns in the
+ RTL that modify the arg pointer. Thus we must ensure that such insns don't
+ get scheduled across each other because that would invalidate the REG_EQUIV
+ notes. One could argue that the REG_EQUIV notes are wrong, but solving
+ the problem in the scheduler will likely give better code, so we do it
+ here. */
+ char *reg_known_equiv_p;
+
+ /* Inside SRC, the source of a SET, find a base address. */
+
+ /* When copying arguments into pseudo-registers, record the (ADDRESS)
+ expression for the argument directly so that even if the argument
+ register is changed later (e.g. for a function call) the original
+ value is noted. */
+ static int copying_arguments;
+
+ static rtx
+ find_base_value (src)
+ register rtx src;
+ {
+ switch (GET_CODE (src))
+ {
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return src;
+
+ case REG:
+ if (copying_arguments && REGNO (src) < FIRST_PSEUDO_REGISTER)
+ return reg_base_value[REGNO (src)];
+ return src;
+
+ case MEM:
+ /* Check for an argument passed in memory. Only record in the
+ copying-arguments block; it is too hard to track changes
+ otherwise. */
+ if (copying_arguments
+ && (XEXP (src, 0) == arg_pointer_rtx
+ || (GET_CODE (XEXP (src, 0)) == PLUS
+ && XEXP (XEXP (src, 0), 0) == arg_pointer_rtx)))
+ return gen_rtx (ADDRESS, VOIDmode, src);
+ return 0;
+
+ case CONST:
+ src = XEXP (src, 0);
+ if (GET_CODE (src) != PLUS && GET_CODE (src) != MINUS)
+ break;
+ /* fall through */
+ case PLUS:
+ case MINUS:
+ /* Guess which operand to set the register equivalent to. */
+ /* If the first operand is a symbol or the second operand is
+ an integer, the first operand is the base address. */
+ if (GET_CODE (XEXP (src, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (src, 0)) == LABEL_REF
+ || GET_CODE (XEXP (src, 1)) == CONST_INT)
+ return XEXP (src, 0);
+ /* If an operand is a register marked as a pointer, it is the base. */
+ if (GET_CODE (XEXP (src, 0)) == REG
+ && REGNO_POINTER_FLAG (REGNO (XEXP (src, 0))))
+ src = XEXP (src, 0);
+ else if (GET_CODE (XEXP (src, 1)) == REG
+ && REGNO_POINTER_FLAG (REGNO (XEXP (src, 1))))
+ src = XEXP (src, 1);
+ else
+ return 0;
+ if (copying_arguments && REGNO (src) < FIRST_PSEUDO_REGISTER)
+ return reg_base_value[REGNO (src)];
+ return src;
+
+ case AND:
+ /* If the second operand is constant set the base
+ address to the first operand. */
+ if (GET_CODE (XEXP (src, 1)) == CONST_INT
+ && GET_CODE (XEXP (src, 0)) == REG)
+ {
+ src = XEXP (src, 0);
+ if (copying_arguments && REGNO (src) < FIRST_PSEUDO_REGISTER)
+ return reg_base_value[REGNO (src)];
+ return src;
+ }
+ return 0;
+
+ case HIGH:
+ return XEXP (src, 0);
+ }
+
+ return 0;
+ }
+
+ /* Called from init_alias_analysis indirectly through note_stores. */
+
+ /* while scanning insns to find base values, reg_seen[N] is nonzero if
+ register N has been set in this function. */
+ static char *reg_seen;
+
+ static
+ void record_set (dest, set)
+ rtx dest, set;
+ {
+ register int regno;
+ rtx src;
+
+ if (GET_CODE (dest) != REG)
+ return;
+
+ regno = REGNO (dest);
+
+ if (set)
+ {
+ /* A CLOBBER wipes out any old value but does not prevent a previously
+ unset register from acquiring a base address (i.e. reg_seen is not
+ set). */
+ if (GET_CODE (set) == CLOBBER)
+ {
+ reg_base_value[regno] = 0;
+ return;
+ }
+ src = SET_SRC (set);
+ }
+ else
+ {
+ static int unique_id;
+ if (reg_seen[regno])
+ {
+ reg_base_value[regno] = 0;
+ return;
+ }
+ reg_seen[regno] = 1;
+ reg_base_value[regno] = gen_rtx (ADDRESS, Pmode,
+ GEN_INT (unique_id++));
+ return;
+ }
+
+ /* This is not the first set. If the new value is not related to the
+ old value, forget the base value. Note that the following code is
+ not detected:
+ extern int x, y; int *p = &x; p += (&y-&x);
+ ANSI C does not allow computing the difference of addresses
+ of distinct top level objects. */
+ if (reg_base_value[regno])
+ switch (GET_CODE (src))
+ {
+ case PLUS:
+ case MINUS:
+ if (XEXP (src, 0) != dest && XEXP (src, 1) != dest)
+ reg_base_value[regno] = 0;
+ break;
+ case AND:
+ if (XEXP (src, 0) != dest || GET_CODE (XEXP (src, 1)) != CONST_INT)
+ reg_base_value[regno] = 0;
+ break;
+ case LO_SUM:
+ if (XEXP (src, 0) != dest)
+ reg_base_value[regno] = 0;
+ break;
+ default:
+ reg_base_value[regno] = 0;
+ break;
+ }
+ /* If this is the first set of a register, record the value. */
+ else if ((regno >= FIRST_PSEUDO_REGISTER || ! fixed_regs[regno])
+ && ! reg_seen[regno] && reg_base_value[regno] == 0)
+ reg_base_value[regno] = find_base_value (src);
+
+ reg_seen[regno] = 1;
+ }
+
+ /* Called from loop optimization when a new pseudo-register is created. */
+ void
+ record_base_value (regno, val)
+ int regno;
+ rtx val;
+ {
+ if (!flag_alias_check || regno >= reg_base_value_size)
+ return;
+ if (GET_CODE (val) == REG)
+ {
+ if (REGNO (val) < reg_base_value_size)
+ reg_base_value[regno] = reg_base_value[REGNO (val)];
+ return;
+ }
+ reg_base_value[regno] = find_base_value (val);
+ }
+
+ static rtx
+ canon_rtx (x)
+ rtx x;
+ {
+ /* Recursively look for equivalences. */
+ if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
+ && REGNO (x) < reg_known_value_size)
+ return reg_known_value[REGNO (x)] == x
+ ? x : canon_rtx (reg_known_value[REGNO (x)]);
+ else if (GET_CODE (x) == PLUS)
+ {
+ rtx x0 = canon_rtx (XEXP (x, 0));
+ rtx x1 = canon_rtx (XEXP (x, 1));
+
+ if (x0 != XEXP (x, 0) || x1 != XEXP (x, 1))
+ {
+ /* We can tolerate LO_SUMs being offset here; these
+ rtl are used for nothing other than comparisons. */
+ if (GET_CODE (x0) == CONST_INT)
+ return plus_constant_for_output (x1, INTVAL (x0));
+ else if (GET_CODE (x1) == CONST_INT)
+ return plus_constant_for_output (x0, INTVAL (x1));
+ return gen_rtx (PLUS, GET_MODE (x), x0, x1);
+ }
+ }
+ /* This gives us much better alias analysis when called from
+ the loop optimizer. Note we want to leave the original
+ MEM alone, but need to return the canonicalized MEM with
+ all the flags with their original values. */
+ else if (GET_CODE (x) == MEM)
+ {
+ rtx addr = canon_rtx (XEXP (x, 0));
+ if (addr != XEXP (x, 0))
+ {
+ rtx new = gen_rtx (MEM, GET_MODE (x), addr);
+ MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
+ RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
+ MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
+ x = new;
+ }
+ }
+ return x;
+ }
+
+ /* Return 1 if X and Y are identical-looking rtx's.
+
+ We use the data in reg_known_value above to see if two registers with
+ different numbers are, in fact, equivalent. */
+
+ static int
+ rtx_equal_for_memref_p (x, y)
+ rtx x, y;
+ {
+ register int i;
+ register int j;
+ register enum rtx_code code;
+ register char *fmt;
+
+ if (x == 0 && y == 0)
+ return 1;
+ if (x == 0 || y == 0)
+ return 0;
+ x = canon_rtx (x);
+ y = canon_rtx (y);
+
+ if (x == y)
+ return 1;
+
+ code = GET_CODE (x);
+ /* Rtx's of different codes cannot be equal. */
+ if (code != GET_CODE (y))
+ return 0;
+
+ /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
+ (REG:SI x) and (REG:HI x) are NOT equivalent. */
+
+ if (GET_MODE (x) != GET_MODE (y))
+ return 0;
+
+ /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively. */
+
+ if (code == REG)
+ return REGNO (x) == REGNO (y);
+ if (code == LABEL_REF)
+ return XEXP (x, 0) == XEXP (y, 0);
+ if (code == SYMBOL_REF)
+ return XSTR (x, 0) == XSTR (y, 0);
+
+ /* For commutative operations, the RTX match if the operand match in any
+ order. Also handle the simple binary and unary cases without a loop. */
+ if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
+ return ((rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))
+ && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1)))
+ || (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 1))
+ && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 0))));
+ else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2')
+ return (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))
+ && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1)));
+ else if (GET_RTX_CLASS (code) == '1')
+ return rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0));
+
+ /* Compare the elements. If any pair of corresponding elements
+ fail to match, return 0 for the whole things. */
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ switch (fmt[i])
+ {
+ case 'w':
+ if (XWINT (x, i) != XWINT (y, i))
+ return 0;
+ break;
+
+ case 'n':
+ case 'i':
+ if (XINT (x, i) != XINT (y, i))
+ return 0;
+ break;
+
+ case 'V':
+ case 'E':
+ /* Two vectors must have the same length. */
+ if (XVECLEN (x, i) != XVECLEN (y, i))
+ return 0;
+
+ /* And the corresponding elements must match. */
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (rtx_equal_for_memref_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0)
+ return 0;
+ break;
+
+ case 'e':
+ if (rtx_equal_for_memref_p (XEXP (x, i), XEXP (y, i)) == 0)
+ return 0;
+ break;
+
+ case 'S':
+ case 's':
+ if (strcmp (XSTR (x, i), XSTR (y, i)))
+ return 0;
+ break;
+
+ case 'u':
+ /* These are just backpointers, so they don't matter. */
+ break;
+
+ case '0':
+ break;
+
+ /* It is believed that rtx's at this level will never
+ contain anything but integers and other rtx's,
+ except for within LABEL_REFs and SYMBOL_REFs. */
+ default:
+ abort ();
+ }
+ }
+ return 1;
+ }
+
+ /* Given an rtx X, find a SYMBOL_REF or LABEL_REF within
+ X and return it, or return 0 if none found. */
+
+ static rtx
+ find_symbolic_term (x)
+ rtx x;
+ {
+ register int i;
+ register enum rtx_code code;
+ register char *fmt;
+
+ code = GET_CODE (x);
+ if (code == SYMBOL_REF || code == LABEL_REF)
+ return x;
+ if (GET_RTX_CLASS (code) == 'o')
+ return 0;
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ rtx t;
+
+ if (fmt[i] == 'e')
+ {
+ t = find_symbolic_term (XEXP (x, i));
+ if (t != 0)
+ return t;
+ }
+ else if (fmt[i] == 'E')
+ break;
+ }
+ return 0;
+ }
+
+ static rtx
+ find_base_term (x)
+ register rtx x;
+ {
+ switch (GET_CODE (x))
+ {
+ case REG:
+ return REG_BASE_VALUE (x);
+
+ case HIGH:
+ return find_base_term (XEXP (x, 0));
+
+ case CONST:
+ x = XEXP (x, 0);
+ if (GET_CODE (x) != PLUS && GET_CODE (x) != MINUS)
+ return 0;
+ /* fall through */
+ case LO_SUM:
+ case PLUS:
+ case MINUS:
+ {
+ rtx tmp = find_base_term (XEXP (x, 0));
+ if (tmp)
+ return tmp;
+ return find_base_term (XEXP (x, 1));
+ }
+
+ case AND:
+ if (GET_CODE (XEXP (x, 0)) == REG && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ return REG_BASE_VALUE (XEXP (x, 0));
+ return 0;
+
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return x;
+
+ default:
+ return 0;
+ }
+ }
+
+ /* Return 0 if the addresses X and Y are known to point to different
+ objects, 1 if they might be pointers to the same object. */
+
+ static int
+ base_alias_check (x, y)
+ rtx x, y;
+ {
+ rtx x_base = find_base_term (x);
+ rtx y_base = find_base_term (y);
+
+ /* If either base address is unknown or the base addresses are equal,
+ nothing is known about aliasing. */
+
+ if (x_base == 0 || y_base == 0 || rtx_equal_p (x_base, y_base))
+ return 1;
+
+ /* The base addresses of the read and write are different
+ expressions. If they are both symbols there is no
+ conflict. */
+ if (GET_CODE (x_base) != ADDRESS && GET_CODE (y_base) != ADDRESS)
+ return 0;
+
+ /* If one address is a stack reference there can be no alias:
+ stack references using different base registers do not alias,
+ a stack reference can not alias a parameter, and a stack reference
+ can not alias a global. */
+ if ((GET_CODE (x_base) == ADDRESS && GET_MODE (x_base) == Pmode)
+ || (GET_CODE (y_base) == ADDRESS && GET_MODE (y_base) == Pmode))
+ return 0;
+
+ if (! flag_argument_noalias)
+ return 1;
+
+ if (flag_argument_noalias > 1)
+ return 0;
+
+ /* Weak noalias assertion (arguments are distinct, but may match globals). */
+ return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode);
+ }
+
+ /* Return nonzero if X and Y (memory addresses) could reference the
+ same location in memory. C is an offset accumulator. When
+ C is nonzero, we are testing aliases between X and Y + C.
+ XSIZE is the size in bytes of the X reference,
+ similarly YSIZE is the size in bytes for Y.
+
+ If XSIZE or YSIZE is zero, we do not know the amount of memory being
+ referenced (the reference was BLKmode), so make the most pessimistic
+ assumptions.
+
+ We recognize the following cases of non-conflicting memory:
+
+ (1) addresses involving the frame pointer cannot conflict
+ with addresses involving static variables.
+ (2) static variables with different addresses cannot conflict.
+
+ Nice to notice that varying addresses cannot conflict with fp if no
+ local variables had their addresses taken, but that's too hard now. */
+
+
+ static int
+ memrefs_conflict_p (xsize, x, ysize, y, c)
+ register rtx x, y;
+ int xsize, ysize;
+ HOST_WIDE_INT c;
+ {
+ if (GET_CODE (x) == HIGH)
+ x = XEXP (x, 0);
+ else if (GET_CODE (x) == LO_SUM)
+ x = XEXP (x, 1);
+ else
+ x = canon_rtx (x);
+ if (GET_CODE (y) == HIGH)
+ y = XEXP (y, 0);
+ else if (GET_CODE (y) == LO_SUM)
+ y = XEXP (y, 1);
+ else
+ y = canon_rtx (y);
+
+ if (rtx_equal_for_memref_p (x, y))
+ {
+ if (xsize == 0 || ysize == 0)
+ return 1;
+ if (c >= 0 && xsize > c)
+ return 1;
+ if (c < 0 && ysize+c > 0)
+ return 1;
+ return 0;
+ }
+
+ if (y == frame_pointer_rtx || y == hard_frame_pointer_rtx
+ || y == stack_pointer_rtx)
+ {
+ rtx t = y;
+ int tsize = ysize;
+ y = x; ysize = xsize;
+ x = t; xsize = tsize;
+ }
+
+ if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
+ || x == stack_pointer_rtx)
+ {
+ rtx y1;
+
+ if (CONSTANT_P (y))
+ return 0;
+
+ if (GET_CODE (y) == PLUS
+ && canon_rtx (XEXP (y, 0)) == x
+ && (y1 = canon_rtx (XEXP (y, 1)))
+ && GET_CODE (y1) == CONST_INT)
+ {
+ c += INTVAL (y1);
+ return (xsize == 0 || ysize == 0
+ || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
+ }
+
+ if (GET_CODE (y) == PLUS
+ && (y1 = canon_rtx (XEXP (y, 0)))
+ && CONSTANT_P (y1))
+ return 0;
+
+ return 1;
+ }
+
+ if (GET_CODE (x) == PLUS)
+ {
+ /* The fact that X is canonicalized means that this
+ PLUS rtx is canonicalized. */
+ rtx x0 = XEXP (x, 0);
+ rtx x1 = XEXP (x, 1);
+
+ if (GET_CODE (y) == PLUS)
+ {
+ /* The fact that Y is canonicalized means that this
+ PLUS rtx is canonicalized. */
+ rtx y0 = XEXP (y, 0);
+ rtx y1 = XEXP (y, 1);
+
+ if (rtx_equal_for_memref_p (x1, y1))
+ return memrefs_conflict_p (xsize, x0, ysize, y0, c);
+ if (rtx_equal_for_memref_p (x0, y0))
+ return memrefs_conflict_p (xsize, x1, ysize, y1, c);
+ if (GET_CODE (x1) == CONST_INT)
+ if (GET_CODE (y1) == CONST_INT)
+ return memrefs_conflict_p (xsize, x0, ysize, y0,
+ c - INTVAL (x1) + INTVAL (y1));
+ else
+ return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
+ else if (GET_CODE (y1) == CONST_INT)
+ return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
+
+ /* Handle case where we cannot understand iteration operators,
+ but we notice that the base addresses are distinct objects. */
+ /* ??? Is this still necessary? */
+ x = find_symbolic_term (x);
+ if (x == 0)
+ return 1;
+ y = find_symbolic_term (y);
+ if (y == 0)
+ return 1;
+ return rtx_equal_for_memref_p (x, y);
+ }
+ else if (GET_CODE (x1) == CONST_INT)
+ return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
+ }
+ else if (GET_CODE (y) == PLUS)
+ {
+ /* The fact that Y is canonicalized means that this
+ PLUS rtx is canonicalized. */
+ rtx y0 = XEXP (y, 0);
+ rtx y1 = XEXP (y, 1);
+
+ if (GET_CODE (y1) == CONST_INT)
+ return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
+ else
+ return 1;
+ }
+
+ if (GET_CODE (x) == GET_CODE (y))
+ switch (GET_CODE (x))
+ {
+ case MULT:
+ {
+ /* Handle cases where we expect the second operands to be the
+ same, and check only whether the first operand would conflict
+ or not. */
+ rtx x0, y0;
+ rtx x1 = canon_rtx (XEXP (x, 1));
+ rtx y1 = canon_rtx (XEXP (y, 1));
+ if (! rtx_equal_for_memref_p (x1, y1))
+ return 1;
+ x0 = canon_rtx (XEXP (x, 0));
+ y0 = canon_rtx (XEXP (y, 0));
+ if (rtx_equal_for_memref_p (x0, y0))
+ return (xsize == 0 || ysize == 0
+ || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
+
+ /* Can't properly adjust our sizes. */
+ if (GET_CODE (x1) != CONST_INT)
+ return 1;
+ xsize /= INTVAL (x1);
+ ysize /= INTVAL (x1);
+ c /= INTVAL (x1);
+ return memrefs_conflict_p (xsize, x0, ysize, y0, c);
+ }
+ }
+
+ /* Treat an access through an AND (e.g. a subword access on an Alpha)
+ as an access with indeterminate size. */
+ if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ return memrefs_conflict_p (0, XEXP (x, 0), ysize, y, c);
+ if (GET_CODE (y) == AND && GET_CODE (XEXP (y, 1)) == CONST_INT)
+ return memrefs_conflict_p (xsize, x, 0, XEXP (y, 0), c);
+
+ if (CONSTANT_P (x))
+ {
+ if (GET_CODE (x) == CONST_INT && GET_CODE (y) == CONST_INT)
+ {
+ c += (INTVAL (y) - INTVAL (x));
+ return (xsize == 0 || ysize == 0
+ || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
+ }
+
+ if (GET_CODE (x) == CONST)
+ {
+ if (GET_CODE (y) == CONST)
+ return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),
+ ysize, canon_rtx (XEXP (y, 0)), c);
+ else
+ return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),
+ ysize, y, c);
+ }
+ if (GET_CODE (y) == CONST)
+ return memrefs_conflict_p (xsize, x, ysize,
+ canon_rtx (XEXP (y, 0)), c);
+
+ if (CONSTANT_P (y))
+ return (rtx_equal_for_memref_p (x, y)
+ && (xsize == 0 || ysize == 0
+ || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)));
+
+ return 1;
+ }
+ return 1;
+ }
+
+ /* Functions to compute memory dependencies.
+
+ Since we process the insns in execution order, we can build tables
+ to keep track of what registers are fixed (and not aliased), what registers
+ are varying in known ways, and what registers are varying in unknown
+ ways.
+
+ If both memory references are volatile, then there must always be a
+ dependence between the two references, since their order can not be
+ changed. A volatile and non-volatile reference can be interchanged
+ though.
+
+ A MEM_IN_STRUCT reference at a non-QImode varying address can never
+ conflict with a non-MEM_IN_STRUCT reference at a fixed address. We must
+ allow QImode aliasing because the ANSI C standard allows character
+ pointers to alias anything. We are assuming that characters are
+ always QImode here. */
+
+ /* Read dependence: X is read after read in MEM takes place. There can
+ only be a dependence here if both reads are volatile. */
+
+ int
+ read_dependence (mem, x)
+ rtx mem;
+ rtx x;
+ {
+ return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem);
+ }
+
+ /* True dependence: X is read after store in MEM takes place. */
+
+ int
+ true_dependence (mem, mem_mode, x, varies)
+ rtx mem;
+ enum machine_mode mem_mode;
+ rtx x;
+ int (*varies)();
+ {
+ rtx x_addr, mem_addr;
+
+ if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
+ return 1;
+
+ x_addr = XEXP (x, 0);
+ mem_addr = XEXP (mem, 0);
+
+ if (flag_alias_check && ! base_alias_check (x_addr, mem_addr))
+ return 0;
+
+ /* If X is an unchanging read, then it can't possibly conflict with any
+ non-unchanging store. It may conflict with an unchanging write though,
+ because there may be a single store to this address to initialize it.
+ Just fall through to the code below to resolve the case where we have
+ both an unchanging read and an unchanging write. This won't handle all
+ cases optimally, but the possible performance loss should be
+ negligible. */
+ if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
+ return 0;
+
+ x_addr = canon_rtx (x_addr);
+ mem_addr = canon_rtx (mem_addr);
+ if (mem_mode == VOIDmode)
+ mem_mode = GET_MODE (mem);
+
+ if (! memrefs_conflict_p (mem_mode, mem_addr, SIZE_FOR_MODE (x), x_addr, 0))
+ return 0;
+
+ /* If both references are struct references, or both are not, nothing
+ is known about aliasing.
+
+ If either reference is QImode or BLKmode, ANSI C permits aliasing.
+
+ If both addresses are constant, or both are not, nothing is known
+ about aliasing. */
+ if (MEM_IN_STRUCT_P (x) == MEM_IN_STRUCT_P (mem)
+ || mem_mode == QImode || mem_mode == BLKmode
+ || GET_MODE (x) == QImode || GET_MODE (mem) == BLKmode
+ || varies (x_addr) == varies (mem_addr))
+ return 1;
+
+ /* One memory reference is to a constant address, one is not.
+ One is to a structure, the other is not.
+
+ If either memory reference is a variable structure the other is a
+ fixed scalar and there is no aliasing. */
+ if ((MEM_IN_STRUCT_P (mem) && varies (mem_addr))
+ || (MEM_IN_STRUCT_P (x) && varies (x)))
+ return 0;
+
+ return 1;
+ }
+
+ /* Anti dependence: X is written after read in MEM takes place. */
+
+ int
+ anti_dependence (mem, x)
+ rtx mem;
+ rtx x;
+ {
+ if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
+ return 1;
+
+ if (flag_alias_check && ! base_alias_check (XEXP (x, 0), XEXP (mem, 0)))
+ return 0;
+
+ /* If MEM is an unchanging read, then it can't possibly conflict with
+ the store to X, because there is at most one store to MEM, and it must
+ have occurred somewhere before MEM. */
+ x = canon_rtx (x);
+ mem = canon_rtx (mem);
+ if (RTX_UNCHANGING_P (mem))
+ return 0;
+
+ return (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
+ SIZE_FOR_MODE (x), XEXP (x, 0), 0)
+ && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
+ && GET_MODE (mem) != QImode
+ && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
+ && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
+ && GET_MODE (x) != QImode
+ && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem)));
+ }
+
+ /* Output dependence: X is written after store in MEM takes place. */
+
+ int
+ output_dependence (mem, x)
+ register rtx mem;
+ register rtx x;
+ {
+ if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
+ return 1;
+
+ if (flag_alias_check && !base_alias_check (XEXP (x, 0), XEXP (mem, 0)))
+ return 0;
+
+ x = canon_rtx (x);
+ mem = canon_rtx (mem);
+ return (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
+ SIZE_FOR_MODE (x), XEXP (x, 0), 0)
+ && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
+ && GET_MODE (mem) != QImode
+ && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
+ && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
+ && GET_MODE (x) != QImode
+ && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem)));
+ }
+
+ void
+ init_alias_analysis ()
+ {
+ int maxreg = max_reg_num ();
+ int changed;
+ register int i;
+ register rtx insn;
+ rtx note;
+ rtx set;
+
+ reg_known_value_size = maxreg;
+
+ reg_known_value
+ = (rtx *) oballoc ((maxreg - FIRST_PSEUDO_REGISTER) * sizeof (rtx))
+ - FIRST_PSEUDO_REGISTER;
+ reg_known_equiv_p =
+ oballoc (maxreg - FIRST_PSEUDO_REGISTER) - FIRST_PSEUDO_REGISTER;
+ bzero ((char *) (reg_known_value + FIRST_PSEUDO_REGISTER),
+ (maxreg-FIRST_PSEUDO_REGISTER) * sizeof (rtx));
+ bzero (reg_known_equiv_p + FIRST_PSEUDO_REGISTER,
+ (maxreg - FIRST_PSEUDO_REGISTER) * sizeof (char));
+
+ if (flag_alias_check)
+ {
+ /* Overallocate reg_base_value to allow some growth during loop
+ optimization. Loop unrolling can create a large number of
+ registers. */
+ reg_base_value_size = maxreg * 2;
+ reg_base_value = (rtx *)oballoc (reg_base_value_size * sizeof (rtx));
+ reg_seen = (char *)alloca (reg_base_value_size);
+ bzero (reg_base_value, reg_base_value_size * sizeof (rtx));
+ bzero (reg_seen, reg_base_value_size);
+
+ /* Mark all hard registers which may contain an address.
+ The stack, frame and argument pointers may contain an address.
+ An argument register which can hold a Pmode value may contain
+ an address even if it is not in BASE_REGS.
+
+ The address expression is VOIDmode for an argument and
+ Pmode for other registers. */
+ #ifndef OUTGOING_REGNO
+ #define OUTGOING_REGNO(N) N
+ #endif
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ /* Check whether this register can hold an incoming pointer
+ argument. FUNCTION_ARG_REGNO_P tests outgoing register
+ numbers, so translate if necessary due to register windows. */
+ if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i)) && HARD_REGNO_MODE_OK (i, Pmode))
+ reg_base_value[i] = gen_rtx (ADDRESS, VOIDmode,
+ gen_rtx (REG, Pmode, i));
+
+ reg_base_value[STACK_POINTER_REGNUM]
+ = gen_rtx (ADDRESS, Pmode, stack_pointer_rtx);
+ reg_base_value[ARG_POINTER_REGNUM]
+ = gen_rtx (ADDRESS, Pmode, arg_pointer_rtx);
+ reg_base_value[FRAME_POINTER_REGNUM]
+ = gen_rtx (ADDRESS, Pmode, frame_pointer_rtx);
+ reg_base_value[HARD_FRAME_POINTER_REGNUM]
+ = gen_rtx (ADDRESS, Pmode, hard_frame_pointer_rtx);
+ }
+
+ copying_arguments = 1;
+ /* Fill in the entries with known constant values. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ if (flag_alias_check && GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ /* If this insn has a noalias note, process it, Otherwise,
+ scan for sets. A simple set will have no side effects
+ which could change the base value of any other register. */
+ rtx noalias_note;
+ if (GET_CODE (PATTERN (insn)) == SET
+ && (noalias_note = find_reg_note (insn, REG_NOALIAS, NULL_RTX)))
+ record_set (SET_DEST (PATTERN (insn)), 0);
+ else
+ note_stores (PATTERN (insn), record_set);
+ }
+ else if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+ copying_arguments = 0;
+
+ if ((set = single_set (insn)) != 0
+ && GET_CODE (SET_DEST (set)) == REG
+ && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
+ && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
+ && reg_n_sets[REGNO (SET_DEST (set))] == 1)
+ || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
+ && GET_CODE (XEXP (note, 0)) != EXPR_LIST)
+ {
+ int regno = REGNO (SET_DEST (set));
+ reg_known_value[regno] = XEXP (note, 0);
+ reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV;
+ }
+ }
+
+ /* Fill in the remaining entries. */
+ for (i = FIRST_PSEUDO_REGISTER; i < maxreg; i++)
+ if (reg_known_value[i] == 0)
+ reg_known_value[i] = regno_reg_rtx[i];
+
+ if (! flag_alias_check)
+ return;
+
+ /* Simplify the reg_base_value array so that no register refers to
+ another register, except to special registers indirectly through
+ ADDRESS expressions.
+
+ In theory this loop can take as long as O(registers^2), but unless
+ there are very long dependency chains it will run in close to linear
+ time. */
+ do
+ {
+ changed = 0;
+ for (i = FIRST_PSEUDO_REGISTER; i < reg_base_value_size; i++)
+ {
+ rtx base = reg_base_value[i];
+ if (base && GET_CODE (base) == REG)
+ {
+ int base_regno = REGNO (base);
+ if (base_regno == i) /* register set from itself */
+ reg_base_value[i] = 0;
+ else
+ reg_base_value[i] = reg_base_value[base_regno];
+ changed = 1;
+ }
+ }
+ }
+ while (changed);
+
+ reg_seen = 0;
+ }
+
+ void
+ end_alias_analysis ()
+ {
+ reg_known_value = 0;
+ reg_base_value = 0;
+ reg_base_value_size = 0;
+ }
diff -rcp2N gcc-2.7.2.2/c-decl.c g77-new/c-decl.c
*** gcc-2.7.2.2/c-decl.c Fri Oct 27 05:44:43 1995
--- g77-new/c-decl.c Sun Aug 10 18:46:24 1997
*************** init_decl_processing ()
*** 3207,3210 ****
--- 3207,3223 ----
builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
BUILT_IN_COS, "cosl");
+ builtin_function ("__builtin_setjmp",
+ build_function_type (integer_type_node,
+ tree_cons (NULL_TREE,
+ ptr_type_node, endlink)),
+ BUILT_IN_SETJMP, NULL_PTR);
+ builtin_function ("__builtin_longjmp",
+ build_function_type
+ (void_type_node,
+ tree_cons (NULL, ptr_type_node,
+ tree_cons (NULL_TREE,
+ integer_type_node,
+ endlink))),
+ BUILT_IN_LONGJMP, NULL_PTR);
/* In an ANSI C program, it is okay to supply built-in meanings
*************** grokdeclarator (declarator, declspecs, d
*** 4049,4052 ****
--- 4062,4066 ----
int volatilep;
int inlinep;
+ int restrictp;
int explicit_int = 0;
int explicit_char = 0;
*************** grokdeclarator (declarator, declspecs, d
*** 4342,4349 ****
--- 4356,4366 ----
volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
inlinep = !! (specbits & (1 << (int) RID_INLINE));
+ restrictp = !! (specbits & (1 << (int) RID_RESTRICT));
if (constp > 1)
pedwarn ("duplicate `const'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
+ if (restrictp)
+ error ("`restrict' used in non-parameter or non-pointer type declaration");
if (! flag_gen_aux_info && (TYPE_READONLY (type) || TYPE_VOLATILE (type)))
type = TYPE_MAIN_VARIANT (type);
*************** grokdeclarator (declarator, declspecs, d
*** 4693,4696 ****
--- 4710,4715 ----
else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
volatilep++;
+ else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_RESTRICT])
+ restrictp++;
else if (!erred)
{
*************** grokdeclarator (declarator, declspecs, d
*** 4703,4706 ****
--- 4722,4727 ----
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
+ if (restrictp > 1)
+ pedwarn ("duplicate `restrict'");
}
*************** grokdeclarator (declarator, declspecs, d
*** 4844,4847 ****
--- 4865,4875 ----
}
+ if (restrictp)
+ {
+ if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
+ error ("`restrict' applied to non-pointer");
+ DECL_RESTRICT (decl) = 1;
+ }
+
DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
}
*************** start_struct (code, name)
*** 5365,5368 ****
--- 5393,5397 ----
pushtag (name, ref);
C_TYPE_BEING_DEFINED (ref) = 1;
+ TYPE_PACKED (ref) = flag_pack_struct;
return ref;
}
*************** start_enum (name)
*** 5806,5809 ****
--- 5835,5841 ----
enum_overflow = 0;
+ if (flag_short_enums)
+ TYPE_PACKED (enumtype) = 1;
+
return enumtype;
}
*************** finish_enum (enumtype, values, attribute
*** 5862,5867 ****
precision = MAX (lowprec, highprec);
! if (flag_short_enums || TYPE_PACKED (enumtype)
! || precision > TYPE_PRECISION (integer_type_node))
/* Use the width of the narrowest normal C type which is wide enough. */
TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size (precision, 1));
--- 5894,5898 ----
precision = MAX (lowprec, highprec);
! if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
/* Use the width of the narrowest normal C type which is wide enough. */
TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size (precision, 1));
diff -rcp2N gcc-2.7.2.2/c-gperf.h g77-new/c-gperf.h
*** gcc-2.7.2.2/c-gperf.h Fri Mar 4 14:15:53 1994
--- g77-new/c-gperf.h Mon Aug 11 02:58:47 1997
***************
*** 1,15 ****
/* C code produced by gperf version 2.5 (GNU C++ version) */
! /* Command-line: gperf -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$ c-parse.gperf */
struct resword { char *name; short token; enum rid rid; };
! #define TOTAL_KEYWORDS 79
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 20
! #define MIN_HASH_VALUE 10
! #define MAX_HASH_VALUE 144
! /* maximum key range = 135, duplicates = 0 */
#ifdef __GNUC__
! __inline
#endif
static unsigned int
--- 1,16 ----
/* C code produced by gperf version 2.5 (GNU C++ version) */
! /* Command-line: gperf -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$ ../g77-new/c-parse.gperf */
! /* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
struct resword { char *name; short token; enum rid rid; };
! #define TOTAL_KEYWORDS 81
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 20
! #define MIN_HASH_VALUE 11
! #define MAX_HASH_VALUE 157
! /* maximum key range = 147, duplicates = 0 */
#ifdef __GNUC__
! inline
#endif
static unsigned int
*************** hash (str, len)
*** 20,36 ****
static unsigned char asso_values[] =
{
! 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 25, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
! 145, 145, 145, 145, 145, 1, 145, 46, 8, 15,
! 61, 6, 36, 48, 3, 5, 145, 18, 63, 25,
! 29, 76, 1, 145, 13, 2, 1, 51, 37, 9,
! 9, 1, 3, 145, 145, 145, 145, 145,
};
register int hval = len;
--- 21,37 ----
static unsigned char asso_values[] =
{
! 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 2, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
! 158, 158, 158, 158, 158, 1, 158, 18, 1, 58,
! 56, 6, 44, 64, 13, 45, 158, 4, 26, 68,
! 2, 74, 1, 158, 2, 13, 1, 33, 48, 5,
! 5, 3, 12, 158, 158, 158, 158, 158,
};
register int hval = len;
*************** hash (str, len)
*** 44,47 ****
--- 45,49 ----
case 1:
hval += asso_values[str[0]];
+ break;
}
return hval + asso_values[str[len - 1]];
*************** hash (str, len)
*** 50,166 ****
static struct resword wordlist[] =
{
! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
! {"",},
! {"int", TYPESPEC, RID_INT},
! {"",}, {"",},
! {"__typeof__", TYPEOF, NORID},
! {"__signed__", TYPESPEC, RID_SIGNED},
! {"__imag__", IMAGPART, NORID},
! {"switch", SWITCH, NORID},
! {"__inline__", SCSPEC, RID_INLINE},
! {"else", ELSE, NORID},
! {"__iterator__", SCSPEC, RID_ITERATOR},
! {"__inline", SCSPEC, RID_INLINE},
! {"__extension__", EXTENSION, NORID},
! {"struct", STRUCT, NORID},
! {"__real__", REALPART, NORID},
! {"__const", TYPE_QUAL, RID_CONST},
! {"while", WHILE, NORID},
! {"__const__", TYPE_QUAL, RID_CONST},
! {"case", CASE, NORID},
! {"__complex__", TYPESPEC, RID_COMPLEX},
! {"__iterator", SCSPEC, RID_ITERATOR},
! {"bycopy", TYPE_QUAL, RID_BYCOPY},
! {"",}, {"",}, {"",},
! {"__complex", TYPESPEC, RID_COMPLEX},
! {"",},
! {"in", TYPE_QUAL, RID_IN},
! {"break", BREAK, NORID},
! {"@defs", DEFS, NORID},
! {"",}, {"",}, {"",},
! {"extern", SCSPEC, RID_EXTERN},
! {"if", IF, NORID},
! {"typeof", TYPEOF, NORID},
! {"typedef", SCSPEC, RID_TYPEDEF},
! {"__typeof", TYPEOF, NORID},
! {"sizeof", SIZEOF, NORID},
! {"",},
! {"return", RETURN, NORID},
! {"const", TYPE_QUAL, RID_CONST},
! {"__volatile__", TYPE_QUAL, RID_VOLATILE},
! {"@private", PRIVATE, NORID},
! {"@selector", SELECTOR, NORID},
! {"__volatile", TYPE_QUAL, RID_VOLATILE},
! {"__asm__", ASM_KEYWORD, NORID},
! {"",}, {"",},
! {"continue", CONTINUE, NORID},
! {"__alignof__", ALIGNOF, NORID},
! {"__imag", IMAGPART, NORID},
! {"__attribute__", ATTRIBUTE, NORID},
! {"",}, {"",},
! {"__attribute", ATTRIBUTE, NORID},
! {"for", FOR, NORID},
! {"",},
! {"@encode", ENCODE, NORID},
! {"id", OBJECTNAME, RID_ID},
! {"static", SCSPEC, RID_STATIC},
! {"@interface", INTERFACE, NORID},
! {"",},
! {"__signed", TYPESPEC, RID_SIGNED},
! {"",},
! {"__label__", LABEL, NORID},
! {"",}, {"",},
! {"__asm", ASM_KEYWORD, NORID},
! {"char", TYPESPEC, RID_CHAR},
! {"",},
! {"inline", SCSPEC, RID_INLINE},
! {"out", TYPE_QUAL, RID_OUT},
! {"register", SCSPEC, RID_REGISTER},
! {"__real", REALPART, NORID},
! {"short", TYPESPEC, RID_SHORT},
! {"",},
! {"enum", ENUM, NORID},
! {"inout", TYPE_QUAL, RID_INOUT},
! {"",},
! {"oneway", TYPE_QUAL, RID_ONEWAY},
! {"union", UNION, NORID},
! {"",},
! {"__alignof", ALIGNOF, NORID},
! {"",},
! {"@implementation", IMPLEMENTATION, NORID},
! {"",},
! {"@class", CLASS, NORID},
! {"",},
! {"@public", PUBLIC, NORID},
! {"asm", ASM_KEYWORD, NORID},
! {"",}, {"",}, {"",}, {"",}, {"",},
! {"default", DEFAULT, NORID},
! {"",},
! {"void", TYPESPEC, RID_VOID},
! {"",},
! {"@protected", PROTECTED, NORID},
! {"@protocol", PROTOCOL, NORID},
! {"",}, {"",}, {"",},
! {"volatile", TYPE_QUAL, RID_VOLATILE},
! {"",}, {"",},
! {"signed", TYPESPEC, RID_SIGNED},
! {"float", TYPESPEC, RID_FLOAT},
! {"@end", END, NORID},
! {"",}, {"",},
! {"unsigned", TYPESPEC, RID_UNSIGNED},
! {"@compatibility_alias", ALIAS, NORID},
! {"double", TYPESPEC, RID_DOUBLE},
! {"",}, {"",},
! {"auto", SCSPEC, RID_AUTO},
! {"",},
! {"goto", GOTO, NORID},
! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
! {"do", DO, NORID},
! {"",}, {"",}, {"",}, {"",},
! {"long", TYPESPEC, RID_LONG},
};
#ifdef __GNUC__
! __inline
#endif
struct resword *
--- 52,167 ----
static struct resword wordlist[] =
{
! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
! {"",}, {"",},
! {"return", RETURN, NORID},
! {"__real__", REALPART, NORID},
! {"__typeof__", TYPEOF, NORID},
! {"__restrict", TYPE_QUAL, RID_RESTRICT},
! {"extern", SCSPEC, RID_EXTERN},
! {"break", BREAK, NORID},
! {"@encode", ENCODE, NORID},
! {"@private", PRIVATE, NORID},
! {"@selector", SELECTOR, NORID},
! {"@interface", INTERFACE, NORID},
! {"__extension__", EXTENSION, NORID},
! {"struct", STRUCT, NORID},
! {"",},
! {"restrict", TYPE_QUAL, RID_RESTRICT},
! {"__signed__", TYPESPEC, RID_SIGNED},
! {"@defs", DEFS, NORID},
! {"__asm__", ASM_KEYWORD, NORID},
! {"",},
! {"else", ELSE, NORID},
! {"",},
! {"__alignof__", ALIGNOF, NORID},
! {"",},
! {"__attribute__", ATTRIBUTE, NORID},
! {"",},
! {"__real", REALPART, NORID},
! {"__attribute", ATTRIBUTE, NORID},
! {"__label__", LABEL, NORID},
! {"",},
! {"@protocol", PROTOCOL, NORID},
! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
! {"@class", CLASS, NORID},
! {"",},
! {"in", TYPE_QUAL, RID_IN},
! {"int", TYPESPEC, RID_INT},
! {"for", FOR, NORID},
! {"typeof", TYPEOF, NORID},
! {"typedef", SCSPEC, RID_TYPEDEF},
! {"__typeof", TYPEOF, NORID},
! {"__imag__", IMAGPART, NORID},
! {"",},
! {"__inline__", SCSPEC, RID_INLINE},
! {"__iterator", SCSPEC, RID_ITERATOR},
! {"__iterator__", SCSPEC, RID_ITERATOR},
! {"__inline", SCSPEC, RID_INLINE},
! {"while", WHILE, NORID},
! {"__volatile__", TYPE_QUAL, RID_VOLATILE},
! {"",},
! {"@end", END, NORID},
! {"__volatile", TYPE_QUAL, RID_VOLATILE},
! {"const", TYPE_QUAL, RID_CONST},
! {"__const", TYPE_QUAL, RID_CONST},
! {"bycopy", TYPE_QUAL, RID_BYCOPY},
! {"__const__", TYPE_QUAL, RID_CONST},
! {"@protected", PROTECTED, NORID},
! {"__complex__", TYPESPEC, RID_COMPLEX},
! {"__alignof", ALIGNOF, NORID},
! {"__complex", TYPESPEC, RID_COMPLEX},
! {"continue", CONTINUE, NORID},
! {"sizeof", SIZEOF, NORID},
! {"register", SCSPEC, RID_REGISTER},
! {"switch", SWITCH, NORID},
! {"__signed", TYPESPEC, RID_SIGNED},
! {"out", TYPE_QUAL, RID_OUT},
! {"",},
! {"case", CASE, NORID},
! {"char", TYPESPEC, RID_CHAR},
! {"inline", SCSPEC, RID_INLINE},
! {"",},
! {"union", UNION, NORID},
! {"",},
! {"@implementation", IMPLEMENTATION, NORID},
! {"volatile", TYPE_QUAL, RID_VOLATILE},
! {"oneway", TYPE_QUAL, RID_ONEWAY},
! {"",},
! {"if", IF, NORID},
! {"__asm", ASM_KEYWORD, NORID},
! {"short", TYPESPEC, RID_SHORT},
! {"",},
! {"static", SCSPEC, RID_STATIC},
! {"long", TYPESPEC, RID_LONG},
! {"auto", SCSPEC, RID_AUTO},
! {"",}, {"",},
! {"@public", PUBLIC, NORID},
! {"double", TYPESPEC, RID_DOUBLE},
! {"",},
! {"id", OBJECTNAME, RID_ID},
! {"",}, {"",}, {"",}, {"",},
! {"default", DEFAULT, NORID},
! {"@compatibility_alias", ALIAS, NORID},
! {"unsigned", TYPESPEC, RID_UNSIGNED},
! {"enum", ENUM, NORID},
! {"",}, {"",}, {"",}, {"",},
! {"__imag", IMAGPART, NORID},
! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
! {"float", TYPESPEC, RID_FLOAT},
! {"inout", TYPE_QUAL, RID_INOUT},
! {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
! {"do", DO, NORID},
! {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
! {"signed", TYPESPEC, RID_SIGNED},
! {"",}, {"",}, {"",},
! {"goto", GOTO, NORID},
! {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
! {"void", TYPESPEC, RID_VOID},
! {"",}, {"",}, {"",},
! {"asm", ASM_KEYWORD, NORID},
};
#ifdef __GNUC__
! inline
#endif
struct resword *
diff -rcp2N gcc-2.7.2.2/c-lex.c g77-new/c-lex.c
*** gcc-2.7.2.2/c-lex.c Thu Jun 15 07:11:39 1995
--- g77-new/c-lex.c Sun Aug 10 18:46:49 1997
*************** init_lex ()
*** 173,176 ****
--- 173,177 ----
ridpointers[(int) RID_CONST] = get_identifier ("const");
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
+ ridpointers[(int) RID_RESTRICT] = get_identifier ("restrict");
ridpointers[(int) RID_AUTO] = get_identifier ("auto");
ridpointers[(int) RID_STATIC] = get_identifier ("static");
*************** init_lex ()
*** 206,209 ****
--- 207,211 ----
UNSET_RESERVED_WORD ("iterator");
UNSET_RESERVED_WORD ("complex");
+ UNSET_RESERVED_WORD ("restrict");
}
if (flag_no_asm)
*************** init_lex ()
*** 214,217 ****
--- 216,220 ----
UNSET_RESERVED_WORD ("iterator");
UNSET_RESERVED_WORD ("complex");
+ UNSET_RESERVED_WORD ("restrict");
}
}
*************** yylex ()
*** 1433,1437 ****
/* Create a node with determined type and value. */
if (imag)
! yylval.ttype = build_complex (convert (type, integer_zero_node),
build_real (type, value));
else
--- 1436,1441 ----
/* Create a node with determined type and value. */
if (imag)
! yylval.ttype = build_complex (NULL_TREE,
! convert (type, integer_zero_node),
build_real (type, value));
else
*************** yylex ()
*** 1624,1629 ****
<= TYPE_PRECISION (integer_type_node))
yylval.ttype
! = build_complex (integer_zero_node,
! convert (integer_type_node, yylval.ttype));
else
error ("complex integer constant is too wide for `complex int'");
--- 1628,1634 ----
<= TYPE_PRECISION (integer_type_node))
yylval.ttype
! = build_complex (NULL_TREE, integer_zero_node,
! convert (integer_type_node,
! yylval.ttype));
else
error ("complex integer constant is too wide for `complex int'");
diff -rcp2N gcc-2.7.2.2/c-lex.h g77-new/c-lex.h
*** gcc-2.7.2.2/c-lex.h Thu Jun 15 07:12:22 1995
--- g77-new/c-lex.h Sun Aug 10 18:10:55 1997
*************** enum rid
*** 43,47 ****
RID_VOLATILE,
RID_INLINE,
! RID_NOALIAS,
RID_ITERATOR,
RID_COMPLEX,
--- 43,47 ----
RID_VOLATILE,
RID_INLINE,
! RID_RESTRICT,
RID_ITERATOR,
RID_COMPLEX,
diff -rcp2N gcc-2.7.2.2/c-parse.gperf g77-new/c-parse.gperf
*** gcc-2.7.2.2/c-parse.gperf Fri Apr 9 19:00:44 1993
--- g77-new/c-parse.gperf Sun Aug 10 18:10:55 1997
*************** __label__, LABEL, NORID
*** 36,39 ****
--- 36,40 ----
__real, REALPART, NORID
__real__, REALPART, NORID
+ __restrict, TYPE_QUAL, RID_RESTRICT
__signed, TYPESPEC, RID_SIGNED
__signed__, TYPESPEC, RID_SIGNED
*************** oneway, TYPE_QUAL, RID_ONEWAY
*** 69,72 ****
--- 70,74 ----
out, TYPE_QUAL, RID_OUT
register, SCSPEC, RID_REGISTER
+ restrict, TYPE_QUAL, RID_RESTRICT
return, RETURN, NORID
short, TYPESPEC, RID_SHORT
diff -rcp2N gcc-2.7.2.2/c-typeck.c g77-new/c-typeck.c
*** gcc-2.7.2.2/c-typeck.c Thu Feb 20 19:24:11 1997
--- g77-new/c-typeck.c Sun Aug 10 18:46:29 1997
*************** pointer_int_sum (resultcode, ptrop, into
*** 2681,2686 ****
so the multiply won't overflow spuriously. */
! if (TYPE_PRECISION (TREE_TYPE (intop)) != POINTER_SIZE)
! intop = convert (type_for_size (POINTER_SIZE, 0), intop);
/* Replace the integer argument with a suitable product by the object size.
--- 2681,2688 ----
so the multiply won't overflow spuriously. */
! if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
! || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
! intop = convert (type_for_size (TYPE_PRECISION (sizetype),
! TREE_UNSIGNED (sizetype)), intop);
/* Replace the integer argument with a suitable product by the object size.
diff -rcp2N gcc-2.7.2.2/calls.c g77-new/calls.c
*** gcc-2.7.2.2/calls.c Thu Oct 26 21:53:43 1995
--- g77-new/calls.c Sun Aug 10 18:46:16 1997
*************** expand_call (exp, target, ignore)
*** 564,567 ****
--- 564,569 ----
/* Nonzero if it is plausible that this is a call to alloca. */
int may_be_alloca;
+ /* Nonzero if this is a call to malloc or a related function. */
+ int is_malloc;
/* Nonzero if this is a call to setjmp or a related function. */
int returns_twice;
*************** expand_call (exp, target, ignore)
*** 741,745 ****
if (stack_arg_under_construction || i >= 0)
{
! rtx insn = NEXT_INSN (before_call), seq;
/* Look for a call in the inline function code.
--- 743,749 ----
if (stack_arg_under_construction || i >= 0)
{
! rtx first_insn
! = before_call ? NEXT_INSN (before_call) : get_insns ();
! rtx insn, seq;
/* Look for a call in the inline function code.
*************** expand_call (exp, target, ignore)
*** 749,753 ****
if (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) == 0)
! for (; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == CALL_INSN)
break;
--- 753,757 ----
if (OUTGOING_ARGS_SIZE (DECL_SAVED_INSNS (fndecl)) == 0)
! for (insn = first_insn; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == CALL_INSN)
break;
*************** expand_call (exp, target, ignore)
*** 781,785 ****
seq = get_insns ();
end_sequence ();
! emit_insns_before (seq, NEXT_INSN (before_call));
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
}
--- 785,789 ----
seq = get_insns ();
end_sequence ();
! emit_insns_before (seq, first_insn);
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
}
*************** expand_call (exp, target, ignore)
*** 852,855 ****
--- 856,860 ----
returns_twice = 0;
is_longjmp = 0;
+ is_malloc = 0;
if (name != 0 && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 15)
*************** expand_call (exp, target, ignore)
*** 891,894 ****
--- 896,903 ----
&& ! strcmp (tname, "longjmp"))
is_longjmp = 1;
+ /* Only recognize malloc when alias analysis is enabled. */
+ else if (tname[0] == 'm' && flag_alias_check
+ && ! strcmp(tname, "malloc"))
+ is_malloc = 1;
}
*************** expand_call (exp, target, ignore)
*** 1087,1090 ****
--- 1096,1100 ----
store_expr (args[i].tree_value, copy, 0);
+ is_const = 0;
args[i].tree_value = build1 (ADDR_EXPR,
*************** expand_call (exp, target, ignore)
*** 1363,1367 ****
/* Now we are about to start emitting insns that can be deleted
if a libcall is deleted. */
! if (is_const)
start_sequence ();
--- 1373,1377 ----
/* Now we are about to start emitting insns that can be deleted
if a libcall is deleted. */
! if (is_const || is_malloc)
start_sequence ();
*************** expand_call (exp, target, ignore)
*** 1951,1954 ****
--- 1961,1978 ----
end_sequence ();
emit_insns (insns);
+ }
+ else if (is_malloc)
+ {
+ rtx temp = gen_reg_rtx (GET_MODE (valreg));
+ rtx last, insns;
+
+ emit_move_insn (temp, valreg);
+ last = get_last_insn ();
+ REG_NOTES (last) =
+ gen_rtx (EXPR_LIST, REG_NOALIAS, temp, REG_NOTES (last));
+ insns = get_insns ();
+ end_sequence ();
+ emit_insns (insns);
+ valreg = temp;
}
diff -rcp2N gcc-2.7.2.2/cccp.c g77-new/cccp.c
*** gcc-2.7.2.2/cccp.c Thu Oct 26 18:07:26 1995
--- g77-new/cccp.c Sun Aug 10 18:45:53 1997
*************** initialize_builtins (inp, outp)
*** 9626,9629 ****
--- 9626,9630 ----
so that it is present only when truly compiling with GNU C. */
/* install ((U_CHAR *) "__GNUC__", -1, T_CONST, "2", -1); */
+ install ((U_CHAR *) "__HAVE_BUILTIN_SETJMP__", -1, T_CONST, "1", -1);
if (debug_output)
diff -rcp2N gcc-2.7.2.2/combine.c g77-new/combine.c
*** gcc-2.7.2.2/combine.c Sun Nov 26 14:32:07 1995
--- g77-new/combine.c Mon Jul 28 21:44:17 1997
*************** num_sign_bit_copies (x, mode)
*** 7326,7329 ****
--- 7326,7335 ----
case NEG:
+ while (GET_MODE (XEXP (x, 0)) == GET_MODE (x)
+ && GET_CODE (XEXP (x, 0)) == NEG
+ && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == NEG)
+ x = XEXP (XEXP (x, 0), 0); /* Speed up 961126-1.c */
+
/* In general, this subtracts one sign bit copy. But if the value
is known to be positive, the number of sign bit copies is the
*************** distribute_notes (notes, from_insn, i3,
*** 10648,10651 ****
--- 10654,10658 ----
case REG_EQUIV:
case REG_NONNEG:
+ case REG_NOALIAS:
/* These notes say something about results of an insn. We can
only support them if they used to be on I3 in which case they
diff -rcp2N gcc-2.7.2.2/config/alpha/alpha.c g77-new/config/alpha/alpha.c
*** gcc-2.7.2.2/config/alpha/alpha.c Thu Feb 20 19:24:11 1997
--- g77-new/config/alpha/alpha.c Thu Jul 10 20:08:47 1997
*************** direct_return ()
*** 1239,1243 ****
cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */
! #if !defined(CROSS_COMPILE) && !defined(_WIN32)
#include <stamp.h>
#endif
--- 1239,1243 ----
cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */
! #if !defined(CROSS_COMPILE) && !defined(_WIN32) && !defined(__linux__)
#include <stamp.h>
#endif
*************** output_prolog (file, size)
*** 1370,1373 ****
--- 1370,1378 ----
alpha_function_needs_gp = 0;
+ #ifdef __linux__
+ if(profile_flag) {
+ alpha_function_needs_gp = 1;
+ }
+ #endif
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if ((GET_CODE (insn) == CALL_INSN)
diff -rcp2N gcc-2.7.2.2/config/alpha/alpha.h g77-new/config/alpha/alpha.h
*** gcc-2.7.2.2/config/alpha/alpha.h Thu Feb 20 19:24:12 1997
--- g77-new/config/alpha/alpha.h Sun Aug 10 19:21:39 1997
*************** extern int target_flags;
*** 112,116 ****
--- 112,118 ----
{"", TARGET_DEFAULT | TARGET_CPU_DEFAULT} }
+ #ifndef TARGET_DEFAULT
#define TARGET_DEFAULT 3
+ #endif
#ifndef TARGET_CPU_DEFAULT
*************** extern int target_flags;
*** 252,255 ****
--- 254,260 ----
/* No data type wants to be aligned rounder than this. */
#define BIGGEST_ALIGNMENT 64
+
+ /* For atomic access to objects, must have at least 32-bit alignment. */
+ #define MINIMUM_ATOMIC_ALIGNMENT 32
/* Make strings word-aligned so strcpy from constants will be faster. */
diff -rcp2N gcc-2.7.2.2/config/alpha/alpha.md g77-new/config/alpha/alpha.md
*** gcc-2.7.2.2/config/alpha/alpha.md Fri Oct 27 06:49:59 1995
--- g77-new/config/alpha/alpha.md Thu Jul 10 20:08:48 1997
***************
*** 1746,1752 ****
(if_then_else:DF
(match_operator 3 "signed_comparison_operator"
! [(match_operand:DF 1 "reg_or_fp0_operand" "fG,fG")
(match_operand:DF 2 "fp0_operand" "G,G")])
! (float_extend:DF (match_operand:SF 4 "reg_or_fp0_operand" "fG,0"))
(match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
"TARGET_FP"
--- 1746,1752 ----
(if_then_else:DF
(match_operator 3 "signed_comparison_operator"
! [(match_operand:DF 4 "reg_or_fp0_operand" "fG,fG")
(match_operand:DF 2 "fp0_operand" "G,G")])
! (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "fG,0"))
(match_operand:DF 5 "reg_or_fp0_operand" "0,fG")))]
"TARGET_FP"
diff -rcp2N gcc-2.7.2.2/config/alpha/elf.h g77-new/config/alpha/elf.h
*** gcc-2.7.2.2/config/alpha/elf.h Wed Dec 31 19:00:00 1969
--- g77-new/config/alpha/elf.h Thu Jul 10 20:08:49 1997
***************
*** 0 ****
--- 1,522 ----
+ /* Definitions of target machine for GNU compiler, for DEC Alpha w/ELF.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Contributed by Richard Henderson (rth@tamu.edu).
+
+ This file is part of GNU CC.
+
+ GNU CC 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.
+
+ GNU CC 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 GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+ /* This is used on Alpha platforms that use the ELF format.
+ Currently only Linux uses this. */
+
+ #include "alpha/linux.h"
+
+ #undef TARGET_VERSION
+ #define TARGET_VERSION fprintf (stderr, " (Alpha Linux/ELF)");
+
+ #undef OBJECT_FORMAT_COFF
+ #undef EXTENDED_COFF
+ #define OBJECT_FORMAT_ELF
+
+ #define SDB_DEBUGGING_INFO
+
+ #undef ASM_FINAL_SPEC
+
+ #undef CPP_PREDEFINES
+ #define CPP_PREDEFINES "\
+ -D__alpha -D__alpha__ -D__linux__ -D__linux -D_LONGLONG -Dlinux -Dunix \
+ -Asystem(linux) -Acpu(alpha) -Amachine(alpha) -D__ELF__"
+
+ #undef LINK_SPEC
+ #define LINK_SPEC "-m elf64alpha -G 8 %{O*:-O3} %{!O*:-O1} \
+ %{shared:-shared} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}} \
+ %{static:-static}}"
+
+ /* Output at beginning of assembler file. */
+
+ #undef ASM_FILE_START
+ #define ASM_FILE_START(FILE) \
+ { \
+ alpha_write_verstamp (FILE); \
+ output_file_directive (FILE, main_input_filename); \
+ fprintf (FILE, "\t.version\t\"01.01\"\n"); \
+ fprintf (FILE, "\t.set noat\n"); \
+ }
+
+ #define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE) \
+ alpha_output_lineno (STREAM, LINE)
+ extern void alpha_output_lineno ();
+
+ extern void output_file_directive ();
+
+ /* Attach a special .ident directive to the end of the file to identify
+ the version of GCC which compiled this code. The format of the
+ .ident string is patterned after the ones produced by native svr4
+ C compilers. */
+
+ #define IDENT_ASM_OP ".ident"
+
+ #ifdef IDENTIFY_WITH_IDENT
+ #define ASM_IDENTIFY_GCC(FILE) /* nothing */
+ #define ASM_IDENTIFY_LANGUAGE(FILE) \
+ fprintf(FILE, "\t%s \"GCC (%s) %s\"\n", IDENT_ASM_OP, \
+ lang_identify(), version_string)
+ #else
+ #define ASM_FILE_END(FILE) \
+ do { \
+ fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
+ IDENT_ASM_OP, version_string); \
+ } while (0)
+ #endif
+
+ /* Allow #sccs in preprocessor. */
+
+ #define SCCS_DIRECTIVE
+
+ /* Output #ident as a .ident. */
+
+ #define ASM_OUTPUT_IDENT(FILE, NAME) \
+ fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME);
+
+ /* This is how to allocate empty space in some section. The .zero
+ pseudo-op is used for this on most svr4 assemblers. */
+
+ #define SKIP_ASM_OP ".zero"
+
+ #undef ASM_OUTPUT_SKIP
+ #define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t%s\t%u\n", SKIP_ASM_OP, (SIZE))
+
+ /* Output the label which precedes a jumptable. Note that for all svr4
+ systems where we actually generate jumptables (which is to say every
+ svr4 target except i386, where we use casesi instead) we put the jump-
+ tables into the .rodata section and since other stuff could have been
+ put into the .rodata section prior to any given jumptable, we have to
+ make sure that the location counter for the .rodata section gets pro-
+ perly re-aligned prior to the actual beginning of the jump table. */
+
+ #define ALIGN_ASM_OP ".align"
+
+ #ifndef ASM_OUTPUT_BEFORE_CASE_LABEL
+ #define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
+ ASM_OUTPUT_ALIGN ((FILE), 2);
+ #endif
+
+ #undef ASM_OUTPUT_CASE_LABEL
+ #define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
+ do { \
+ ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \
+ ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
+ } while (0)
+
+ /* The standard SVR4 assembler seems to require that certain builtin
+ library routines (e.g. .udiv) be explicitly declared as .globl
+ in each assembly file where they are referenced. */
+
+ #define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
+ ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0))
+
+ /* This says how to output assembler code to declare an
+ uninitialized external linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here. */
+
+ #define COMMON_ASM_OP ".comm"
+
+ #undef ASM_OUTPUT_ALIGNED_COMMON
+ #define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ do { \
+ fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
+ } while (0)
+
+ /* This says how to output assembler code to declare an
+ uninitialized internal linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here. */
+
+ #define LOCAL_ASM_OP ".local"
+
+ #undef ASM_OUTPUT_ALIGNED_LOCAL
+ #define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+ do { \
+ fprintf ((FILE), "\t%s\t", LOCAL_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), "\n"); \
+ ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \
+ } while (0)
+
+ /* This is the pseudo-op used to generate a 64-bit word of data with a
+ specific value in some section. */
+
+ #define INT_ASM_OP ".quad"
+
+ /* This is the pseudo-op used to generate a contiguous sequence of byte
+ values from a double-quoted string WITHOUT HAVING A TERMINATING NUL
+ AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */
+
+ #undef ASCII_DATA_ASM_OP
+ #define ASCII_DATA_ASM_OP ".ascii"
+
+ /* Support const sections and the ctors and dtors sections for g++.
+ Note that there appears to be two different ways to support const
+ sections at the moment. You can either #define the symbol
+ READONLY_DATA_SECTION (giving it some code which switches to the
+ readonly data section) or else you can #define the symbols
+ EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
+ SELECT_RTX_SECTION. We do both here just to be on the safe side. */
+
+ #define USE_CONST_SECTION 1
+
+ #define CONST_SECTION_ASM_OP ".section\t.rodata"
+
+ /* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+
+ Note that we want to give these sections the SHF_WRITE attribute
+ because these sections will actually contain data (i.e. tables of
+ addresses of functions in the current root executable or shared library
+ file) and, in the case of a shared library, the relocatable addresses
+ will have to be properly resolved/relocated (and then written into) by
+ the dynamic linker when it actually attaches the given shared library
+ to the executing process. (Note that on SVR4, you may wish to use the
+ `-z text' option to the ELF linker, when building a shared library, as
+ an additional check that you are doing everything right. But if you do
+ use the `-z text' option when building a shared library, you will get
+ errors unless the .ctors and .dtors sections are marked as writable
+ via the SHF_WRITE attribute.) */
+
+ #define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\""
+ #define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
+
+ /* On svr4, we *do* have support for the .init and .fini sections, and we
+ can put stuff in there to be executed before and after `main'. We let
+ crtstuff.c and other files know this by defining the following symbols.
+ The definitions say how to change sections to the .init and .fini
+ sections. This is the same for all known svr4 assemblers. */
+
+ #define INIT_SECTION_ASM_OP ".section\t.init"
+ #define FINI_SECTION_ASM_OP ".section\t.fini"
+
+ /* Support non-common, uninitialized data in the .bss section. */
+
+ #define BSS_SECTION_ASM_OP ".section\t.bss"
+
+ /* A default list of other sections which we might be "in" at any given
+ time. For targets that use additional sections (e.g. .tdesc) you
+ should override this definition in the target-specific file which
+ includes this file. */
+
+ #undef EXTRA_SECTIONS
+ #define EXTRA_SECTIONS in_const, in_ctors, in_dtors, in_bss
+
+ /* A default list of extra section function definitions. For targets
+ that use additional sections (e.g. .tdesc) you should override this
+ definition in the target-specific file which includes this file. */
+
+ #undef EXTRA_SECTION_FUNCTIONS
+ #define EXTRA_SECTION_FUNCTIONS \
+ CONST_SECTION_FUNCTION \
+ CTORS_SECTION_FUNCTION \
+ DTORS_SECTION_FUNCTION \
+ BSS_SECTION_FUNCTION
+
+ #undef READONLY_DATA_SECTION
+ #define READONLY_DATA_SECTION() const_section ()
+
+ extern void text_section ();
+
+ #define CONST_SECTION_FUNCTION \
+ void \
+ const_section () \
+ { \
+ if (!USE_CONST_SECTION) \
+ text_section(); \
+ else if (in_section != in_const) \
+ { \
+ fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
+ in_section = in_const; \
+ } \
+ }
+
+ #define CTORS_SECTION_FUNCTION \
+ void \
+ ctors_section () \
+ { \
+ if (in_section != in_ctors) \
+ { \
+ fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
+ in_section = in_ctors; \
+ } \
+ }
+
+ #define DTORS_SECTION_FUNCTION \
+ void \
+ dtors_section () \
+ { \
+ if (in_section != in_dtors) \
+ { \
+ fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
+ in_section = in_dtors; \
+ } \
+ }
+
+ #define BSS_SECTION_FUNCTION \
+ void \
+ bss_section () \
+ { \
+ if (in_section != in_bss) \
+ { \
+ fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \
+ in_section = in_bss; \
+ } \
+ }
+
+
+ /* Switch into a generic section.
+ This is currently only used to support section attributes.
+
+ We make the section read-only and executable for a function decl,
+ read-only for a const data decl, and writable for a non-const data decl. */
+ #define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
+ fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \
+ (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \
+ (DECL) && TREE_READONLY (DECL) ? "a" : "aw")
+
+
+ /* A C statement (sans semicolon) to output an element in the table of
+ global constructors. */
+ #define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ ctors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+ /* A C statement (sans semicolon) to output an element in the table of
+ global destructors. */
+ #define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
+ do { \
+ dtors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+ /* A C statement or statements to switch to the appropriate
+ section for output of DECL. DECL is either a `VAR_DECL' node
+ or a constant of some sort. RELOC indicates whether forming
+ the initial value of DECL requires link-time relocations. */
+
+ #define SELECT_SECTION(DECL,RELOC) \
+ { \
+ if (TREE_CODE (DECL) == STRING_CST) \
+ { \
+ if (! flag_writable_strings) \
+ const_section (); \
+ else \
+ data_section (); \
+ } \
+ else if (TREE_CODE (DECL) == VAR_DECL) \
+ { \
+ if ((flag_pic && RELOC) \
+ || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
+ || !DECL_INITIAL (DECL) \
+ || (DECL_INITIAL (DECL) != error_mark_node \
+ && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
+ { \
+ if (DECL_COMMON (DECL) \
+ && !DECL_INITIAL (DECL)) \
+ /* || DECL_INITIAL (DECL) == error_mark_node)) */ \
+ bss_section(); \
+ else \
+ data_section (); \
+ } \
+ else \
+ const_section (); \
+ } \
+ else \
+ const_section (); \
+ }
+
+ /* A C statement or statements to switch to the appropriate
+ section for output of RTX in mode MODE. RTX is some kind
+ of constant in RTL. The argument MODE is redundant except
+ in the case of a `const_int' rtx. Currently, these always
+ go into the const section. */
+
+ #undef SELECT_RTX_SECTION
+ #define SELECT_RTX_SECTION(MODE,RTX) const_section()
+
+ /* Define the strings used for the special svr4 .type and .size directives.
+ These strings generally do not vary from one system running svr4 to
+ another, but if a given system (e.g. m88k running svr) needs to use
+ different pseudo-op names for these, they may be overridden in the
+ file which includes this one. */
+
+ #define TYPE_ASM_OP ".type"
+ #define SIZE_ASM_OP ".size"
+
+ /* This is how we tell the assembler that a symbol is weak. */
+
+ #define ASM_WEAKEN_LABEL(FILE,NAME) \
+ do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); } while (0)
+
+ /* This is how we tell the assembler that two symbols have the same value. */
+
+ #define ASM_OUTPUT_DEF(FILE,NAME1,NAME2) \
+ do { assemble_name(FILE, NAME1); \
+ fputs(" = ", FILE); \
+ assemble_name(FILE, NAME2); \
+ fputc('\n', FILE); } while (0)
+
+ /* The following macro defines the format used to output the second
+ operand of the .type assembler directive. Different svr4 assemblers
+ expect various different forms for this operand. The one given here
+ is just a default. You may need to override it in your machine-
+ specific tm.h file (depending upon the particulars of your assembler). */
+
+ #define TYPE_OPERAND_FMT "@%s"
+
+ /* Write the extra assembler code needed to declare a function's result.
+ Most svr4 assemblers don't require any special declaration of the
+ result value, but there are exceptions. */
+
+ #ifndef ASM_DECLARE_RESULT
+ #define ASM_DECLARE_RESULT(FILE, RESULT)
+ #endif
+
+ /* These macros generate the special .type and .size directives which
+ are used to set the corresponding fields of the linker symbol table
+ entries in an ELF object file under SVR4. These macros also output
+ the starting labels for the relevant functions/objects. */
+
+ /* Write the extra assembler code needed to declare an object properly. */
+
+ #define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do { \
+ fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ putc (',', FILE); \
+ fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
+ putc ('\n', FILE); \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
+ } \
+ ASM_OUTPUT_LABEL(FILE, NAME); \
+ } while (0)
+
+ /* Output the size directive for a decl in rest_of_decl_compilation
+ in the case where we did not do so before the initializer.
+ Once we find the error_mark_node, we know that the value of
+ size_directive_output was set
+ by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
+
+ #define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
+ do { \
+ char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
+ && ! AT_END && TOP_LEVEL \
+ && DECL_INITIAL (DECL) == error_mark_node \
+ && !size_directive_output) \
+ { \
+ size_directive_output = 1; \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, name); \
+ fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
+ } \
+ } while (0)
+
+ /* A table of bytes codes used by the ASM_OUTPUT_ASCII and
+ ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
+ corresponds to a particular byte value [0..255]. For any
+ given byte value, if the value in the corresponding table
+ position is zero, the given character can be output directly.
+ If the table value is 1, the byte must be output as a \ooo
+ octal escape. If the tables value is anything else, then the
+ byte value should be output as a \ followed by the value
+ in the table. Note that we can use standard UN*X escape
+ sequences for many control characters, but we don't use
+ \a to represent BEL because some svr4 assemblers (e.g. on
+ the i386) don't know about that. Also, we don't use \v
+ since some versions of gas, such as 2.2 did not accept it. */
+
+ #define ESCAPES \
+ "\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+ \0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
+ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
+ \1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+ \1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+ \1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+ \1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
+
+ /* Some svr4 assemblers have a limit on the number of characters which
+ can appear in the operand of a .string directive. If your assembler
+ has such a limitation, you should define STRING_LIMIT to reflect that
+ limit. Note that at least some svr4 assemblers have a limit on the
+ actual number of bytes in the double-quoted string, and that they
+ count each character in an escape sequence as one byte. Thus, an
+ escape sequence like \377 would count as four bytes.
+
+ If your target assembler doesn't support the .string directive, you
+ should define this to zero.
+ */
+
+ #define STRING_LIMIT ((unsigned) 256)
+
+ #define STRING_ASM_OP ".string"
+
+ /*
+ * We always use gas here, so we don't worry about ECOFF assembler problems.
+ */
+ #undef TARGET_GAS
+ #define TARGET_GAS (1)
+
+ #undef PREFERRED_DEBUGGING_TYPE
+ #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+ /* Provide a STARTFILE_SPEC appropriate for Linux. Here we add
+ the Linux magical crtbegin.o file (see crtstuff.c) which
+ provides part of the support for getting C++ file-scope static
+ object constructed before entering `main'. */
+
+ #undef STARTFILE_SPEC
+ #define STARTFILE_SPEC \
+ "%{!shared: \
+ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
+ crti.o%s crtbegin.o%s"
+
+ /* Provide a ENDFILE_SPEC appropriate for Linux. Here we tack on
+ the Linux magical crtend.o file (see crtstuff.c) which
+ provides part of the support for getting C++ file-scope static
+ object constructed before entering `main', followed by a normal
+ Linux "finalizer" file, `crtn.o'. */
+
+ #undef ENDFILE_SPEC
+ #define ENDFILE_SPEC \
+ "crtend.o%s crtn.o%s"
diff -rcp2N gcc-2.7.2.2/config/alpha/linux.h g77-new/config/alpha/linux.h
*** gcc-2.7.2.2/config/alpha/linux.h Wed Dec 31 19:00:00 1969
--- g77-new/config/alpha/linux.h Thu Jul 10 20:08:49 1997
***************
*** 0 ****
--- 1,72 ----
+ /* Definitions of target machine for GNU compiler, for Alpha Linux,
+ using ECOFF.
+ Copyright (C) 1995 Free Software Foundation, Inc.
+ Contributed by Bob Manson.
+ Derived from work contributed by Cygnus Support,
+ (c) 1993 Free Software Foundation.
+
+ This file is part of GNU CC.
+
+ GNU CC 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.
+
+ GNU CC 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 GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #define TARGET_DEFAULT (3 | MASK_GAS)
+
+ #include "alpha/alpha.h"
+
+ #undef TARGET_VERSION
+ #define TARGET_VERSION fprintf (stderr, " (Linux/Alpha)");
+
+ #undef CPP_PREDEFINES
+ #define CPP_PREDEFINES "\
+ -D__alpha -D__alpha__ -D__linux__ -D__linux -D_LONGLONG -Dlinux -Dunix \
+ -Asystem(linux) -Acpu(alpha) -Amachine(alpha)"
+
+ /* We don't actually need any of these; the MD_ vars are ignored
+ anyway for cross-compilers, and the other specs won't get picked up
+ 'coz the user is supposed to do ld -r (hmm, perhaps that should be
+ the default). In any case, setting them thus will catch some
+ common user errors. */
+
+ #undef MD_EXEC_PREFIX
+ #undef MD_STARTFILE_PREFIX
+
+ #undef LIB_SPEC
+ #define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}"
+
+ #undef LINK_SPEC
+ #define LINK_SPEC \
+ "-G 8 %{O*:-O3} %{!O*:-O1}"
+
+ #undef ASM_SPEC
+ #define ASM_SPEC "-nocpp"
+
+ /* Can't do stabs */
+ #undef SDB_DEBUGGING_INFO
+
+ /* Prefer dbx. */
+ #undef PREFERRED_DEBUGGING_TYPE
+ #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+ #undef FUNCTION_PROFILER
+
+ #define FUNCTION_PROFILER(FILE, LABELNO) \
+ do { \
+ fputs ("\tlda $27,_mcount\n", (FILE)); \
+ fputs ("\tjsr $26,($27),_mcount\n", (FILE)); \
+ fputs ("\tldgp $29,0($26)\n", (FILE)); \
+ } while (0);
+
+ /* Generate calls to memcpy, etc., not bcopy, etc. */
+ #define TARGET_MEM_FUNCTIONS
diff -rcp2N gcc-2.7.2.2/config/alpha/t-linux g77-new/config/alpha/t-linux
*** gcc-2.7.2.2/config/alpha/t-linux Wed Dec 31 19:00:00 1969
--- g77-new/config/alpha/t-linux Thu Jul 10 20:08:49 1997
***************
*** 0 ****
--- 1,3 ----
+ # Our header files are supposed to be correct, nein?
+ FIXINCLUDES =
+ STMP_FIXPROTO =
diff -rcp2N gcc-2.7.2.2/config/alpha/x-linux g77-new/config/alpha/x-linux
*** gcc-2.7.2.2/config/alpha/x-linux Wed Dec 31 19:00:00 1969
--- g77-new/config/alpha/x-linux Thu Jul 10 20:08:49 1997
***************
*** 0 ****
--- 1 ----
+ CLIB=-lbfd -liberty
diff -rcp2N gcc-2.7.2.2/config/alpha/xm-alpha.h g77-new/config/alpha/xm-alpha.h
*** gcc-2.7.2.2/config/alpha/xm-alpha.h Thu Aug 31 17:52:27 1995
--- g77-new/config/alpha/xm-alpha.h Thu Jul 10 20:08:49 1997
*************** Boston, MA 02111-1307, USA. */
*** 46,51 ****
--- 46,53 ----
#include <alloca.h>
#else
+ #ifndef alloca
extern void *alloca ();
#endif
+ #endif
/* The host compiler has problems with enum bitfields since it makes
*************** extern void *malloc (), *realloc (), *ca
*** 68,72 ****
--- 70,76 ----
/* OSF/1 has vprintf. */
+ #ifndef linux /* 1996/02/22 mauro@craftwork.com -- unreliable with Linux */
#define HAVE_VPRINTF
+ #endif
/* OSF/1 has putenv. */
diff -rcp2N gcc-2.7.2.2/config/alpha/xm-linux.h g77-new/config/alpha/xm-linux.h
*** gcc-2.7.2.2/config/alpha/xm-linux.h Wed Dec 31 19:00:00 1969
--- g77-new/config/alpha/xm-linux.h Thu Jul 10 20:08:49 1997
***************
*** 0 ****
--- 1,10 ----
+ #ifndef _XM_LINUX_H
+ #define _XM_LINUX_H
+
+ #include "xm-alpha.h"
+
+ #define HAVE_STRERROR
+
+ #define DONT_DECLARE_SYS_SIGLIST
+ #define USE_BFD
+ #endif
diff -rcp2N gcc-2.7.2.2/config/i386/i386.c g77-new/config/i386/i386.c
*** gcc-2.7.2.2/config/i386/i386.c Sun Oct 22 07:13:21 1995
--- g77-new/config/i386/i386.c Sun Aug 10 18:46:09 1997
*************** standard_80387_constant_p (x)
*** 1290,1294 ****
set_float_handler (handler);
REAL_VALUE_FROM_CONST_DOUBLE (d, x);
! is0 = REAL_VALUES_EQUAL (d, dconst0);
is1 = REAL_VALUES_EQUAL (d, dconst1);
set_float_handler (NULL_PTR);
--- 1290,1294 ----
set_float_handler (handler);
REAL_VALUE_FROM_CONST_DOUBLE (d, x);
! is0 = REAL_VALUES_EQUAL (d, dconst0) && !REAL_VALUE_MINUS_ZERO (d);
is1 = REAL_VALUES_EQUAL (d, dconst1);
set_float_handler (NULL_PTR);
diff -rcp2N gcc-2.7.2.2/config/mips/mips.c g77-new/config/mips/mips.c
*** gcc-2.7.2.2/config/mips/mips.c Thu Feb 20 19:24:13 1997
--- g77-new/config/mips/mips.c Sun Aug 10 18:45:43 1997
*************** expand_block_move (operands)
*** 2360,2365 ****
else if (constp && bytes <= 2*MAX_MOVE_BYTES)
! emit_insn (gen_movstrsi_internal (gen_rtx (MEM, BLKmode, dest_reg),
! gen_rtx (MEM, BLKmode, src_reg),
bytes_rtx, align_rtx));
--- 2360,2367 ----
else if (constp && bytes <= 2*MAX_MOVE_BYTES)
! emit_insn (gen_movstrsi_internal (change_address (operands[0],
! BLKmode, dest_reg),
! change_address (orig_src, BLKmode,
! src_reg),
bytes_rtx, align_rtx));
diff -rcp2N gcc-2.7.2.2/config/mips/mips.h g77-new/config/mips/mips.h
*** gcc-2.7.2.2/config/mips/mips.h Thu Nov 9 11:23:09 1995
--- g77-new/config/mips/mips.h Sun Aug 10 18:46:44 1997
*************** typedef struct mips_args {
*** 2160,2170 ****
} \
\
! /* Flush the instruction cache. */ \
! /* ??? Are the modes right? Maybe they should depend on -mint64/-mlong64? */\
/* ??? Should check the return value for errors. */ \
! emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "cacheflush"), \
0, VOIDmode, 3, addr, Pmode, \
GEN_INT (TRAMPOLINE_SIZE), SImode, \
! GEN_INT (1), SImode); \
}
--- 2160,2170 ----
} \
\
! /* Flush both caches. We need to flush the data cache in case \
! the system has a write-back cache. */ \
/* ??? Should check the return value for errors. */ \
! emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "_flush_cache"), \
0, VOIDmode, 3, addr, Pmode, \
GEN_INT (TRAMPOLINE_SIZE), SImode, \
! GEN_INT (3), TYPE_MODE (integer_type_node)); \
}
*************** typedef struct mips_args {
*** 2388,2392 ****
((GET_CODE (X) != CONST_DOUBLE \
|| mips_const_double_ok (X, GET_MODE (X))) \
! && ! (GET_CODE (X) == CONST && ABI_64BIT))
/* A C compound statement that attempts to replace X with a valid
--- 2388,2393 ----
((GET_CODE (X) != CONST_DOUBLE \
|| mips_const_double_ok (X, GET_MODE (X))) \
! && ! (GET_CODE (X) == CONST \
! && (ABI_64BIT || GET_CODE (XEXP (X, 0)) == MINUS)))
/* A C compound statement that attempts to replace X with a valid
diff -rcp2N gcc-2.7.2.2/config/mips/sni-gas.h g77-new/config/mips/sni-gas.h
*** gcc-2.7.2.2/config/mips/sni-gas.h Wed Dec 31 19:00:00 1969
--- g77-new/config/mips/sni-gas.h Sun Aug 10 18:46:33 1997
***************
*** 0 ****
--- 1,43 ----
+ #include "mips/sni-svr4.h"
+
+ /* Enable debugging. */
+ #define DBX_DEBUGGING_INFO
+ #define SDB_DEBUGGING_INFO
+ #define MIPS_DEBUGGING_INFO
+
+ #define DWARF_DEBUGGING_INFO
+ #undef PREFERRED_DEBUGGING_TYPE
+ #define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG
+
+ /* We need to use .esize and .etype instead of .size and .type to
+ avoid conflicting with ELF directives. These are only recognized
+ by gas, anyhow, not the native assembler. */
+ #undef PUT_SDB_SIZE
+ #define PUT_SDB_SIZE(a) \
+ do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.esize\t%d;", (a)); \
+ } while (0)
+
+ #undef PUT_SDB_TYPE
+ #define PUT_SDB_TYPE(a) \
+ do { \
+ extern FILE *asm_out_text_file; \
+ fprintf (asm_out_text_file, "\t.etype\t0x%x;", (a)); \
+ } while (0)
+
+
+ /* This is how to equate one symbol to another symbol. The syntax used is
+ `SYM1=SYM2'. Note that this is different from the way equates are done
+ with most svr4 assemblers, where the syntax is `.set SYM1,SYM2'. */
+
+ #define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
+ do { fprintf ((FILE), "\t"); \
+ assemble_name (FILE, LABEL1); \
+ fprintf (FILE, " = "); \
+ assemble_name (FILE, LABEL2); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+
+
+
diff -rcp2N gcc-2.7.2.2/config/mips/sni-svr4.h g77-new/config/mips/sni-svr4.h
*** gcc-2.7.2.2/config/mips/sni-svr4.h Wed Dec 31 19:00:00 1969
--- g77-new/config/mips/sni-svr4.h Sun Aug 10 18:46:33 1997
***************
*** 0 ****
--- 1,103 ----
+ /* Definitions of target machine for GNU compiler. SNI SINIX version.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Contributed by Marco Walther (Marco.Walther@mch.sni.de).
+
+ This file is part of GNU CC.
+
+ GNU CC 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.
+
+ GNU CC 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 GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+ #define MIPS_SVR4
+
+ #define CPP_PREDEFINES "\
+ -Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_SVR4 \
+ -D_mips -D_unix -D_host_mips -D_MIPSEB -D_R3000 -D_SYSTYPE_SVR4 \
+ -Asystem(unix) -Asystem(svr4) -Acpu(mips) -Amachine(mips)"
+
+ #define CPP_SPEC "\
+ %{.cc: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
+ %{.cxx: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
+ %{.C: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
+ %{.m: -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C} \
+ %{.S: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
+ %{.s: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
+ %{!.S:%{!.s: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}} \
+ -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int"
+
+ #define LINK_SPEC "\
+ %{G*} \
+ %{!mgas: \
+ %{dy} %{dn}}"
+
+ #define LIB_SPEC "\
+ %{p:-lprof1} \
+ %{!p:%{pg:-lprof1} \
+ %{!pg:-L/usr/ccs/lib/ -lc /usr/ccs/lib/crtn.o%s}}"
+
+ #define STARTFILE_SPEC "\
+ %{pg:gcrt0.o%s} \
+ %{!pg:%{p:mcrt0.o%s} \
+ %{!p:/usr/ccs/lib/crt1.o /usr/ccs/lib/crti.o /usr/ccs/lib/values-Xt.o%s}}"
+
+ /* Mips System V.4 doesn't have a getpagesize() function needed by the
+ trampoline code, so use the POSIX sysconf function to get it.
+ This is only done when compiling the trampoline code. */
+
+ #ifdef L_trampoline
+ #include <unistd.h>
+
+ #define getpagesize() sysconf(_SC_PAGE_SIZE)
+ #endif /* L_trampoline */
+
+ /* Use atexit for static constructors/destructors, instead of defining
+ our own exit function. */
+ #define HAVE_ATEXIT
+
+ /* Generate calls to memcpy, etc., not bcopy, etc. */
+ #define TARGET_MEM_FUNCTIONS
+
+ #define OBJECT_FORMAT_ELF
+
+ #define TARGET_DEFAULT MASK_ABICALLS
+ #define ABICALLS_ASM_OP ".option pic2"
+
+ #define MACHINE_TYPE "SNI running SINIX 5.42"
+
+ #define MIPS_DEFAULT_GVALUE 0
+
+ #define NM_FLAGS "-p"
+
+ /* wir haben ein Problem, wenn in einem Assembler-File keine .text-section
+ erzeugt wird. Dann landen diese Pseudo-Labels in irgendeiner anderen
+ section, z.B. .reginfo. Das macht den ld sehr ungluecklich. */
+
+ #define ASM_IDENTIFY_GCC(mw_stream) \
+ fprintf(mw_stream, "\t.ident \"gcc2_compiled.\"\n");
+
+ #define ASM_IDENTIFY_LANGUAGE(STREAM)
+
+ #define ASM_LONG ".word\t"
+ #define ASM_GLOBAL ".rdata\n\t\t.globl\t"
+
+ #include "mips/mips.h"
+
+ /* We do not want to run mips-tfile! */
+ #undef ASM_FINAL_SPEC
+
+ #undef OBJECT_FORMAT_COFF
+
+ /* We don't support debugging info for now. */
+ #undef DBX_DEBUGGING_INFO
+ #undef SDB_DEBUGGING_INFO
+ #undef MIPS_DEBUGGING_INFO
diff -rcp2N gcc-2.7.2.2/config/mips/x-sni-svr4 g77-new/config/mips/x-sni-svr4
*** gcc-2.7.2.2/config/mips/x-sni-svr4 Wed Dec 31 19:00:00 1969
--- g77-new/config/mips/x-sni-svr4 Sun Aug 10 18:46:33 1997
***************
*** 0 ****
--- 1,18 ----
+ # Define CC and OLDCC as the same, so that the tests:
+ # if [ x"$(OLDCC)" = x"$(CC)" ] ...
+ #
+ # will succeed (if OLDCC != CC, it is assumed that GCC is
+ # being used in secondary stage builds).
+ # -Olimit is so the user can use -O2. Down with fixed
+ # size tables!
+
+ CC = $(OLDCC)
+ OPT =
+ OLDCC = cc -Olimit 3000 $(OPT)
+
+ X_CFLAGS = -DNO_SYS_SIGLIST
+
+ # Show we need to use the C version of ALLOCA
+ # The SVR3 configurations have it, but the SVR4 configurations don't.
+ # For now, just try using it for all SVR* configurations.
+ ALLOCA = alloca.o
diff -rcp2N gcc-2.7.2.2/config/msdos/configur.bat g77-new/config/msdos/configur.bat
*** gcc-2.7.2.2/config/msdos/configur.bat Mon Aug 28 05:55:47 1995
--- g77-new/config/msdos/configur.bat Sun Aug 10 19:08:05 1997
*************** sed -f config/msdos/top.sed Makefile.in
*** 18,21 ****
--- 18,27 ----
set LANG=
+ if not exist ada\make-lang.in goto no_ada
+ sed -f config/msdos/top.sed ada\make-lang.in >> Makefile
+ sed -f config/msdos/top.sed ada\makefile.in > ada\Makefile
+ set LANG=%LANG% ada.&
+ :no_ada
+
if not exist cp\make-lang.in goto no_cp
sed -f config/msdos/top.sed cp\make-lang.in >> Makefile
diff -rcp2N gcc-2.7.2.2/config/pa/pa.c g77-new/config/pa/pa.c
*** gcc-2.7.2.2/config/pa/pa.c Sun Oct 22 07:45:20 1995
--- g77-new/config/pa/pa.c Sun Aug 10 18:45:44 1997
*************** output_move_double (operands)
*** 1344,1369 ****
do them in the other order.
! RMS says "This happens only for registers;
! such overlap can't happen in memory unless the user explicitly
! sets it up, and that is an undefined circumstance."
!
! but it happens on the HP-PA when loading parameter registers,
! so I am going to define that circumstance, and make it work
! as expected. */
! if (optype0 == REGOP && (optype1 == MEMOP || optype1 == OFFSOP)
! && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
{
- /* XXX THIS PROBABLY DOESN'T WORK. */
/* Do the late half first. */
if (addreg1)
output_asm_insn ("ldo 4(%0),%0", &addreg1);
output_asm_insn (singlemove_string (latehalf), latehalf);
if (addreg1)
output_asm_insn ("ldo -4(%0),%0", &addreg1);
- /* Then clobber. */
return singlemove_string (operands);
}
if (optype0 == REGOP && optype1 == REGOP
&& REGNO (operands[0]) == REGNO (operands[1]) + 1)
--- 1344,1377 ----
do them in the other order.
! This can happen in two cases:
! mem -> register where the first half of the destination register
! is the same register used in the memory's address. Reload
! can create such insns.
!
! mem in this case will be either register indirect or register
! indirect plus a valid offset.
!
! register -> register move where REGNO(dst) == REGNO(src + 1)
! someone (Tim/Tege?) claimed this can happen for parameter loads.
!
! Handle mem -> register case first. */
! if (optype0 == REGOP
! && (optype1 == MEMOP || optype1 == OFFSOP)
! && refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
! operands[1], 0))
{
/* Do the late half first. */
if (addreg1)
output_asm_insn ("ldo 4(%0),%0", &addreg1);
output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Then clobber. */
if (addreg1)
output_asm_insn ("ldo -4(%0),%0", &addreg1);
return singlemove_string (operands);
}
+ /* Now handle register -> register case. */
if (optype0 == REGOP && optype1 == REGOP
&& REGNO (operands[0]) == REGNO (operands[1]) + 1)
diff -rcp2N gcc-2.7.2.2/config/pa/pa.md g77-new/config/pa/pa.md
*** gcc-2.7.2.2/config/pa/pa.md Mon Aug 14 09:00:49 1995
--- g77-new/config/pa/pa.md Sun Aug 10 18:45:45 1997
***************
*** 1828,1832 ****
(define_insn ""
[(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
! "=f,*r,Q,?o,?Q,f,*&r,*&r")
(match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
"fG,*rG,f,*r,*r,Q,o,Q"))]
--- 1828,1832 ----
(define_insn ""
[(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
! "=f,*r,Q,?o,?Q,f,*r,*r")
(match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
"fG,*rG,f,*r,*r,Q,o,Q"))]
***************
*** 1846,1850 ****
(define_insn ""
[(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
! "=r,?o,?Q,&r,&r")
(match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
"rG,r,r,o,Q"))]
--- 1846,1850 ----
(define_insn ""
[(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
! "=r,?o,?Q,r,r")
(match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
"rG,r,r,o,Q"))]
***************
*** 2019,2023 ****
(define_insn ""
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
! "=r,o,Q,&r,&r,&r,f,f,*T")
(match_operand:DI 1 "general_operand"
"rM,r,r,o,Q,i,fM,*T,f"))]
--- 2019,2023 ----
(define_insn ""
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
! "=r,o,Q,r,r,r,f,f,*T")
(match_operand:DI 1 "general_operand"
"rM,r,r,o,Q,i,fM,*T,f"))]
***************
*** 2037,2041 ****
(define_insn ""
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
! "=r,o,Q,&r,&r,&r")
(match_operand:DI 1 "general_operand"
"rM,r,r,o,Q,i"))]
--- 2037,2041 ----
(define_insn ""
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
! "=r,o,Q,r,r,r")
(match_operand:DI 1 "general_operand"
"rM,r,r,o,Q,i"))]
diff -rcp2N gcc-2.7.2.2/config/rs6000/rs6000.c g77-new/config/rs6000/rs6000.c
*** gcc-2.7.2.2/config/rs6000/rs6000.c Thu Feb 20 19:24:14 1997
--- g77-new/config/rs6000/rs6000.c Sun Aug 10 04:44:05 1997
*************** input_operand (op, mode)
*** 724,730 ****
return 1;
! /* For HImode and QImode, any constant is valid. */
! if ((mode == HImode || mode == QImode)
! && GET_CODE (op) == CONST_INT)
return 1;
--- 724,729 ----
return 1;
! /* For integer modes, any constant is ok. */
! if (GET_CODE (op) == CONST_INT)
return 1;
diff -rcp2N gcc-2.7.2.2/config/sparc/sol2.h g77-new/config/sparc/sol2.h
*** gcc-2.7.2.2/config/sparc/sol2.h Sat Aug 19 17:36:45 1995
--- g77-new/config/sparc/sol2.h Sun Aug 10 18:45:53 1997
*************** do { \
*** 166,168 ****
/* Define for support of TFmode long double and REAL_ARITHMETIC.
Sparc ABI says that long double is 4 words. */
! #define LONG_DOUBLE_TYPE_SIZE 128
--- 166,168 ----
/* Define for support of TFmode long double and REAL_ARITHMETIC.
Sparc ABI says that long double is 4 words. */
! #define LONG_DOUBLE_TYPE_SIZE 64
diff -rcp2N gcc-2.7.2.2/config/sparc/sparc.c g77-new/config/sparc/sparc.c
*** gcc-2.7.2.2/config/sparc/sparc.c Tue Sep 12 18:32:24 1995
--- g77-new/config/sparc/sparc.c Sun Aug 10 18:46:03 1997
*************** Boston, MA 02111-1307, USA. */
*** 40,46 ****
/* 1 if the caller has placed an "unimp" insn immediately after the call.
This is used in v8 code when calling a function that returns a structure.
! v9 doesn't have this. */
! #define SKIP_CALLERS_UNIMP_P (!TARGET_V9 && current_function_returns_struct)
/* Global variables for machine-dependent things. */
--- 40,51 ----
/* 1 if the caller has placed an "unimp" insn immediately after the call.
This is used in v8 code when calling a function that returns a structure.
! v9 doesn't have this. Be careful to have this test be the same as that
! used on the call. */
! #define SKIP_CALLERS_UNIMP_P \
! (!TARGET_V9 && current_function_returns_struct \
! && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))) \
! && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl))) \
! == INTEGER_CST))
/* Global variables for machine-dependent things. */
diff -rcp2N gcc-2.7.2.2/config/sparc/sparc.h g77-new/config/sparc/sparc.h
*** gcc-2.7.2.2/config/sparc/sparc.h Thu Feb 20 19:24:15 1997
--- g77-new/config/sparc/sparc.h Sun Aug 10 18:46:13 1997
*************** extern int leaf_function;
*** 1526,1533 ****
/* Output assembler code to FILE to increment profiler label # LABELNO
! for profiling a function entry. */
#define FUNCTION_PROFILER(FILE, LABELNO) \
do { \
fputs ("\tsethi %hi(", (FILE)); \
ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO); \
--- 1526,1540 ----
/* Output assembler code to FILE to increment profiler label # LABELNO
! for profiling a function entry.
!
! 32 bit sparc uses %g2 as the STATIC_CHAIN_REGNUM which gets clobbered
! during profiling so we need to save/restore it around the call to mcount.
! We're guaranteed that a save has just been done, and we use the space
! allocated for intreg/fpreg value passing. */
#define FUNCTION_PROFILER(FILE, LABELNO) \
do { \
+ if (! TARGET_V9) \
+ fputs ("\tst %g2,[%fp-4]\n", FILE); \
fputs ("\tsethi %hi(", (FILE)); \
ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO); \
*************** extern int leaf_function;
*** 1539,1542 ****
--- 1546,1551 ----
ASM_OUTPUT_INTERNAL_LABELREF (FILE, "LP", LABELNO); \
fputs ("),%o0,%o0\n", (FILE)); \
+ if (! TARGET_V9) \
+ fputs ("\tld [%fp-4],%g2\n", FILE); \
} while (0)
diff -rcp2N gcc-2.7.2.2/config/sparc/sparc.md g77-new/config/sparc/sparc.md
*** gcc-2.7.2.2/config/sparc/sparc.md Tue Sep 12 18:57:35 1995
--- g77-new/config/sparc/sparc.md Sun Aug 10 18:46:27 1997
***************
*** 4799,4803 ****
abort ();
! if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
{
/* This is really a PIC sequence. We want to represent
--- 4799,4803 ----
abort ();
! if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
{
/* This is really a PIC sequence. We want to represent
***************
*** 4809,4824 ****
if (! TARGET_V9 && INTVAL (operands[3]) != 0)
! emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
! gen_rtx (SET, VOIDmode, pc_rtx,
! XEXP (operands[0], 0)),
! operands[3],
! gen_rtx (CLOBBER, VOIDmode,
! gen_rtx (REG, Pmode, 15)))));
else
! emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
! gen_rtx (SET, VOIDmode, pc_rtx,
! XEXP (operands[0], 0)),
! gen_rtx (CLOBBER, VOIDmode,
! gen_rtx (REG, Pmode, 15)))));
goto finish_call;
}
--- 4809,4828 ----
if (! TARGET_V9 && INTVAL (operands[3]) != 0)
! emit_jump_insn
! (gen_rtx (PARALLEL, VOIDmode,
! gen_rtvec (3,
! gen_rtx (SET, VOIDmode, pc_rtx,
! XEXP (operands[0], 0)),
! GEN_INT (INTVAL (operands[3]) & 0xfff),
! gen_rtx (CLOBBER, VOIDmode,
! gen_rtx (REG, Pmode, 15)))));
else
! emit_jump_insn
! (gen_rtx (PARALLEL, VOIDmode,
! gen_rtvec (2,
! gen_rtx (SET, VOIDmode, pc_rtx,
! XEXP (operands[0], 0)),
! gen_rtx (CLOBBER, VOIDmode,
! gen_rtx (REG, Pmode, 15)))));
goto finish_call;
}
***************
*** 4839,4852 ****
if (! TARGET_V9 && INTVAL (operands[3]) != 0)
! emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
! gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
! operands[3],
! gen_rtx (CLOBBER, VOIDmode,
! gen_rtx (REG, Pmode, 15)))));
else
! emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
! gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
! gen_rtx (CLOBBER, VOIDmode,
! gen_rtx (REG, Pmode, 15)))));
finish_call:
--- 4843,4858 ----
if (! TARGET_V9 && INTVAL (operands[3]) != 0)
! emit_call_insn
! (gen_rtx (PARALLEL, VOIDmode,
! gen_rtvec (3, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
! GEN_INT (INTVAL (operands[3]) & 0xfff),
! gen_rtx (CLOBBER, VOIDmode,
! gen_rtx (REG, Pmode, 15)))));
else
! emit_call_insn
! (gen_rtx (PARALLEL, VOIDmode,
! gen_rtvec (2, gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
! gen_rtx (CLOBBER, VOIDmode,
! gen_rtx (REG, Pmode, 15)))));
finish_call:
***************
*** 4911,4915 ****
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
! "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
"call %a0,%1\;nop\;unimp %2"
[(set_attr "type" "call_no_delay_slot")])
--- 4917,4921 ----
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
! "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
"call %a0,%1\;nop\;unimp %2"
[(set_attr "type" "call_no_delay_slot")])
***************
*** 4923,4927 ****
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
! "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
"call %a0,%1\;nop\;unimp %2"
[(set_attr "type" "call_no_delay_slot")])
--- 4929,4933 ----
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
! "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
"call %a0,%1\;nop\;unimp %2"
[(set_attr "type" "call_no_delay_slot")])
***************
*** 5178,5184 ****
emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
- emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, Pmode, 8)));
/* Return, restoring reg window and jumping to goto handler. */
emit_insn (gen_goto_handler_and_restore ());
DONE;
}")
--- 5184,5190 ----
emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
/* Return, restoring reg window and jumping to goto handler. */
emit_insn (gen_goto_handler_and_restore ());
+ emit_barrier ();
DONE;
}")
***************
*** 5192,5200 ****
(define_insn "goto_handler_and_restore"
! [(unspec_volatile [(const_int 0)] 2)]
""
"jmp %%o0+0\;restore"
[(set_attr "type" "misc")
(set_attr "length" "2")])
;; Special pattern for the FLUSH instruction.
--- 5198,5237 ----
(define_insn "goto_handler_and_restore"
! [(unspec_volatile [(const_int 0)] 2)
! (use (reg:SI 8))]
""
"jmp %%o0+0\;restore"
[(set_attr "type" "misc")
(set_attr "length" "2")])
+
+ ;; Pattern for use after a setjmp to store FP and the return register
+ ;; into the stack area.
+
+ (define_expand "setjmp"
+ [(const_int 0)]
+ ""
+ "
+ {
+ if (TARGET_V9)
+ emit_insn (gen_setjmp_64 ());
+ else
+ emit_insn (gen_setjmp_32 ());
+
+ DONE;
+ }")
+
+ (define_expand "setjmp_32"
+ [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
+ (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
+ ""
+ "
+ { operands[0] = frame_pointer_rtx; }")
+
+ (define_expand "setjmp_64"
+ [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
+ (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
+ ""
+ "
+ { operands[0] = frame_pointer_rtx; }")
;; Special pattern for the FLUSH instruction.
diff -rcp2N gcc-2.7.2.2/config/x-linux g77-new/config/x-linux
*** gcc-2.7.2.2/config/x-linux Tue Mar 28 07:43:37 1995
--- g77-new/config/x-linux Thu Jul 10 20:08:49 1997
*************** BOOT_CFLAGS = -O $(CFLAGS) -Iinclude
*** 13,14 ****
--- 13,17 ----
# Don't run fixproto
STMP_FIXPROTO =
+
+ # Don't install "assert.h" in gcc. We use the one in glibc.
+ INSTALL_ASSERT_H =
diff -rcp2N gcc-2.7.2.2/config/x-linux-aout g77-new/config/x-linux-aout
*** gcc-2.7.2.2/config/x-linux-aout Wed Dec 31 19:00:00 1969
--- g77-new/config/x-linux-aout Thu Jul 10 20:08:49 1997
***************
*** 0 ****
--- 1,14 ----
+ # It is defined in config/xm-linux.h.
+ # X_CFLAGS = -DPOSIX
+
+ # The following is needed when compiling stages 2 and 3 because gcc's
+ # limits.h must be picked up before /usr/include/limits.h. This is because
+ # each does an #include_next of the other if the other hasn't been included.
+ # /usr/include/limits.h loses if it gets found first because /usr/include is
+ # at the end of the search order. When a new version of gcc is released,
+ # gcc's limits.h hasn't been installed yet and hence isn't found.
+
+ BOOT_CFLAGS = -O $(CFLAGS) -Iinclude
+
+ # Don't run fixproto
+ STMP_FIXPROTO =
diff -rcp2N gcc-2.7.2.2/config.guess g77-new/config.guess
*** gcc-2.7.2.2/config.guess Thu Feb 20 19:24:32 1997
--- g77-new/config.guess Thu Jul 10 20:08:50 1997
*************** trap 'rm -f dummy.c dummy.o dummy; exit
*** 52,63 ****
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
- alpha:OSF1:V*:*)
- # After 1.2, OSF1 uses "V1.3" for uname -r.
- echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'`
- exit 0 ;;
alpha:OSF1:*:*)
# 1.2 uses "1.2" for uname -r.
! echo alpha-dec-osf${UNAME_RELEASE}
! exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
--- 52,62 ----
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
alpha:OSF1:*:*)
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
! echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
! exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
*************** case "${UNAME_MACHINE}:${UNAME_SYSTEM}:$
*** 154,161 ****
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit 0 ;;
! ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
! i[34]86:AIX:*:*)
echo i386-ibm-aix
exit 0 ;;
--- 153,160 ----
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit 0 ;;
! ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
! i?86:AIX:*:*)
echo i386-ibm-aix
exit 0 ;;
*************** EOF
*** 220,224 ****
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
! 9000/7?? | 9000/8?[79] ) HP_ARCH=hppa1.1 ;;
9000/8?? ) HP_ARCH=hppa1.0 ;;
esac
--- 219,223 ----
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
! 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
9000/8?? ) HP_ARCH=hppa1.0 ;;
esac
*************** EOF
*** 304,308 ****
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
! i[34]86:BSD/386:*:* | *:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit 0 ;;
--- 303,307 ----
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
! i?86:BSD/386:*:* | *:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit 0 ;;
*************** EOF
*** 314,318 ****
exit 0 ;;
*:GNU:*:*)
! echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
--- 313,317 ----
exit 0 ;;
*:GNU:*:*)
! echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
*************** EOF
*** 320,330 ****
# first see if it will tell us.
ld_help_string=`ld --help 2>&1`
! # if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: elf_i[345]86"; then
# echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
! if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i[345]86linux"; then
echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
! elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i[345]86coff"; then
echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0
elif test "${UNAME_MACHINE}" = "alpha" ; then
echo alpha-unknown-linux ; exit 0
else
--- 319,333 ----
# first see if it will tell us.
ld_help_string=`ld --help 2>&1`
! # if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: elf_i?86"; then
# echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
! if echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i?86linux"; then
echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
! elif echo $ld_help_string | grep >/dev/null 2>&1 "supported emulations: i?86coff"; then
echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0
elif test "${UNAME_MACHINE}" = "alpha" ; then
+ as_version_string=`as --version 2>&1`
+ if echo $as_version_string | grep >/dev/null 2>&1 " version 2.6 "; then
+ echo alpha-unknown-linuxoldas ; exit 0
+ fi
echo alpha-unknown-linux ; exit 0
else
*************** EOF
*** 363,370 ****
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
! i[34]86:DYNIX/ptx:4*:*)
echo i386-sequent-sysv4
exit 0 ;;
! i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*)
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
--- 366,373 ----
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
! i?86:DYNIX/ptx:4*:*)
echo i386-sequent-sysv4
exit 0 ;;
! i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
*************** EOF
*** 373,377 ****
fi
exit 0 ;;
! i[34]86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
--- 376,380 ----
fi
exit 0 ;;
! i?86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
*************** EOF
*** 380,383 ****
--- 383,388 ----
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL
else
*************** EOF
*** 402,406 ****
echo m68010-convergent-sysv
exit 0 ;;
! M680[234]0:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
--- 407,411 ----
echo m68010-convergent-sysv
exit 0 ;;
! M68*:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
*************** EOF
*** 410,414 ****
uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
! m680[234]0:LynxOS:2.[23]*:*)
echo m68k-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
--- 415,419 ----
uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
! m68*:LynxOS:2.*:*)
echo m68k-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
*************** EOF
*** 416,426 ****
echo m68k-atari-sysv4
exit 0 ;;
! i[34]86:LynxOS:2.[23]*:*)
echo i386-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
! TSUNAMI:LynxOS:2.[23]*:*)
echo sparc-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
! rs6000:LynxOS:2.[23]*:*)
echo rs6000-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
--- 421,431 ----
echo m68k-atari-sysv4
exit 0 ;;
! i?86:LynxOS:2.*:*)
echo i386-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
! TSUNAMI:LynxOS:2.*:*)
echo sparc-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
! rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
echo rs6000-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
*************** main ()
*** 479,483 ****
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
! printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3");
exit (0);
#endif
--- 484,488 ----
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
! printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
diff -rcp2N gcc-2.7.2.2/config.sub g77-new/config.sub
*** gcc-2.7.2.2/config.sub Thu Jun 15 17:01:49 1995
--- g77-new/config.sub Thu Jul 10 20:08:50 1997
*************** case $basic_machine in
*** 130,134 ****
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
! tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm \
| arme[lb] | pyramid \
| tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
--- 130,134 ----
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
! tahoe | i[3456]86 | i860 | m68k | m68000 | m88k | ns32k | arm \
| arme[lb] | pyramid \
| tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
*************** case $basic_machine in
*** 145,149 ****
;;
# Recognize the basic CPU types with company name.
! vax-* | tahoe-* | i[345]86-* | i860-* | m68k-* | m68000-* | m88k-* \
| sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
--- 145,149 ----
;;
# Recognize the basic CPU types with company name.
! vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
| sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
*************** case $basic_machine in
*** 309,325 ****
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
! i[345]86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
os=-sysv32
;;
! i[345]86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
os=-sysv4
;;
! i[345]86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
os=-sysv
;;
! i[345]86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
os=-solaris2
--- 309,325 ----
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
! i[3456]86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
os=-sysv32
;;
! i[3456]86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
os=-sysv4
;;
! i[3456]86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
os=-sysv
;;
! i[3456]86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'`
os=-solaris2
diff -rcp2N gcc-2.7.2.2/configure g77-new/configure
*** gcc-2.7.2.2/configure Thu Feb 20 19:24:33 1997
--- g77-new/configure Sun Aug 10 18:46:31 1997
*************** exec_prefix='$(prefix)'
*** 82,85 ****
--- 82,86 ----
# The default g++ include directory is $(libdir)/g++-include.
gxx_include_dir='$(libdir)/g++-include'
+ #gxx_include_dir='$(exec_prefix)/include/g++'
# Default --program-transform-name to nothing.
*************** for machine in $canon_build $canon_host
*** 548,551 ****
--- 549,578 ----
use_collect2=yes
;;
+ alpha-*-linux*oldas*)
+ tm_file=alpha/linux.h
+ tmake_file=alpha/t-linux
+ xmake_file=alpha/x-linux
+ fixincludes=Makefile.in
+ xm_file=alpha/xm-linux.h
+ gas=yes gnu_ld=yes
+ ;;
+ alpha-*-linux*ecoff*)
+ tm_file=alpha/linux.h
+ tmake_file=alpha/t-linux
+ xmake_file=alpha/x-linux
+ fixincludes=Makefile.in
+ xm_file=alpha/xm-linux.h
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gas=yes gnu_ld=yes
+ ;;
+ alpha-*-linux*)
+ tm_file=alpha/elf.h
+ tmake_file=alpha/t-linux
+ xmake_file=alpha/x-linux
+ fixincludes=Makefile.in
+ xm_file=alpha/xm-linux.h
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ gas=yes gnu_ld=yes
+ ;;
alpha-dec-osf[23456789]*)
tm_file=alpha/osf2.h
*************** for machine in $canon_build $canon_host
*** 985,989 ****
cpu_type=i386 # with a.out format using pre BFD linkers
xm_file=i386/xm-linux.h
! xmake_file=x-linux
tm_file=i386/linux-oldld.h
fixincludes=Makefile.in # The headers are ok already.
--- 1012,1016 ----
cpu_type=i386 # with a.out format using pre BFD linkers
xm_file=i386/xm-linux.h
! xmake_file=x-linux-aout
tm_file=i386/linux-oldld.h
fixincludes=Makefile.in # The headers are ok already.
*************** for machine in $canon_build $canon_host
*** 994,998 ****
cpu_type=i386 # with a.out format
xm_file=i386/xm-linux.h
! xmake_file=x-linux
tm_file=i386/linux-aout.h
fixincludes=Makefile.in # The headers are ok already.
--- 1021,1025 ----
cpu_type=i386 # with a.out format
xm_file=i386/xm-linux.h
! xmake_file=x-linux-aout
tm_file=i386/linux-aout.h
fixincludes=Makefile.in # The headers are ok already.
*************** for machine in $canon_build $canon_host
*** 1003,1007 ****
cpu_type=i386 # with ELF format, using GNU libc v1.
xm_file=i386/xm-linux.h
! xmake_file=x-linux
tmake_file=t-linux-libc1
tm_file=i386/linux.h
--- 1030,1034 ----
cpu_type=i386 # with ELF format, using GNU libc v1.
xm_file=i386/xm-linux.h
! xmake_file=x-linux-aout
tmake_file=t-linux-libc1
tm_file=i386/linux.h
*************** for machine in $canon_build $canon_host
*** 1651,1654 ****
--- 1678,1702 ----
use_collect2=yes
;;
+ mips-sni-sysv4)
+ if [ x$gas = xyes ]
+ then
+ if [ x$stabs = xyes ]
+ then
+ tm_file=mips/iris5gdb.h
+ else
+ tm_file=mips/sni-gas.h
+ fi
+ else
+ tm_file=mips/sni-svr4.h
+ fi
+ xm_file=mips/xm-sysv.h
+ xmake_file=mips/x-sni-svr4
+ tmake_file=mips/t-mips-gas
+ if [ x$gnu_ld != xyes ]
+ then
+ use_collect2=yes
+ fi
+ broken_install=yes
+ ;;
mips-sgi-irix5*) # SGI System V.4., IRIX 5
if [ x$gas = xyes ]
*************** MAYBE_TARGET_DEFAULT = -DTARGET_CPU_DEFA
*** 2980,2984 ****
rm Makefile.sed
echo 's| ||' > Makefile.sed
! echo "s|^target=.*$|target=${target}|" >> Makefile.sed
echo "s|^xmake_file=.*$|xmake_file=${dep_host_xmake_file}|" >> Makefile.sed
echo "s|^tmake_file=.*$|tmake_file=${dep_tmake_file}|" >> Makefile.sed
--- 3028,3032 ----
rm Makefile.sed
echo 's| ||' > Makefile.sed
! echo "s|^target=.*$|target=${canon_target}|" >> Makefile.sed
echo "s|^xmake_file=.*$|xmake_file=${dep_host_xmake_file}|" >> Makefile.sed
echo "s|^tmake_file=.*$|tmake_file=${dep_tmake_file}|" >> Makefile.sed
diff -rcp2N gcc-2.7.2.2/cse.c g77-new/cse.c
*** gcc-2.7.2.2/cse.c Sun Nov 26 14:47:05 1995
--- g77-new/cse.c Sun Aug 10 18:46:37 1997
*************** static struct table_elt *last_jump_equiv
*** 520,544 ****
static int constant_pool_entries_cost;
- /* Bits describing what kind of values in memory must be invalidated
- for a particular instruction. If all three bits are zero,
- no memory refs need to be invalidated. Each bit is more powerful
- than the preceding ones, and if a bit is set then the preceding
- bits are also set.
-
- Here is how the bits are set:
- Pushing onto the stack invalidates only the stack pointer,
- writing at a fixed address invalidates only variable addresses,
- writing in a structure element at variable address
- invalidates all but scalar variables,
- and writing in anything else at variable address invalidates everything. */
-
- struct write_data
- {
- int sp : 1; /* Invalidate stack pointer. */
- int var : 1; /* Invalidate variable addresses. */
- int nonscalar : 1; /* Invalidate all but scalar variables. */
- int all : 1; /* Invalidate all memory refs. */
- };
-
/* Define maximum length of a branch path. */
--- 520,523 ----
*************** static void merge_equiv_classes PROTO((s
*** 626,632 ****
struct table_elt *));
static void invalidate PROTO((rtx, enum machine_mode));
static void remove_invalid_refs PROTO((int));
static void rehash_using_reg PROTO((rtx));
! static void invalidate_memory PROTO((struct write_data *));
static void invalidate_for_call PROTO((void));
static rtx use_related_value PROTO((rtx, struct table_elt *));
--- 605,612 ----
struct table_elt *));
static void invalidate PROTO((rtx, enum machine_mode));
+ static int cse_rtx_varies_p PROTO((rtx));
static void remove_invalid_refs PROTO((int));
static void rehash_using_reg PROTO((rtx));
! static void invalidate_memory PROTO((void));
static void invalidate_for_call PROTO((void));
static rtx use_related_value PROTO((rtx, struct table_elt *));
*************** static void set_nonvarying_address_compo
*** 638,644 ****
HOST_WIDE_INT *));
static int refers_to_p PROTO((rtx, rtx));
- static int refers_to_mem_p PROTO((rtx, rtx, HOST_WIDE_INT,
- HOST_WIDE_INT));
- static int cse_rtx_addr_varies_p PROTO((rtx));
static rtx canon_reg PROTO((rtx, rtx));
static void find_best_addr PROTO((rtx, rtx *));
--- 618,621 ----
*************** static void record_jump_cond PROTO((enum
*** 656,661 ****
rtx, rtx, int));
static void cse_insn PROTO((rtx, int));
! static void note_mem_written PROTO((rtx, struct write_data *));
! static void invalidate_from_clobbers PROTO((struct write_data *, rtx));
static rtx cse_process_notes PROTO((rtx, rtx));
static void cse_around_loop PROTO((rtx));
--- 633,638 ----
rtx, rtx, int));
static void cse_insn PROTO((rtx, int));
! static int note_mem_written PROTO((rtx));
! static void invalidate_from_clobbers PROTO((rtx));
static rtx cse_process_notes PROTO((rtx, rtx));
static void cse_around_loop PROTO((rtx));
*************** invalidate (x, full_mode)
*** 1512,1517 ****
register int i;
register struct table_elt *p;
- rtx base;
- HOST_WIDE_INT start, end;
/* If X is a register, dependencies on its contents
--- 1489,1492 ----
*************** invalidate (x, full_mode)
*** 1605,1611 ****
full_mode = GET_MODE (x);
- set_nonvarying_address_components (XEXP (x, 0), GET_MODE_SIZE (full_mode),
- &base, &start, &end);
-
for (i = 0; i < NBUCKETS; i++)
{
--- 1580,1583 ----
*************** invalidate (x, full_mode)
*** 1614,1618 ****
{
next = p->next_same_hash;
! if (refers_to_mem_p (p->exp, base, start, end))
remove_from_table (p, i);
}
--- 1586,1594 ----
{
next = p->next_same_hash;
! /* Invalidate ASM_OPERANDS which reference memory (this is easier
! than checking all the aliases). */
! if (p->in_memory
! && (GET_CODE (p->exp) != MEM
! || true_dependence (x, full_mode, p->exp, cse_rtx_varies_p)))
remove_from_table (p, i);
}
*************** rehash_using_reg (x)
*** 1695,1722 ****
}
- /* Remove from the hash table all expressions that reference memory,
- or some of them as specified by *WRITES. */
-
- static void
- invalidate_memory (writes)
- struct write_data *writes;
- {
- register int i;
- register struct table_elt *p, *next;
- int all = writes->all;
- int nonscalar = writes->nonscalar;
-
- for (i = 0; i < NBUCKETS; i++)
- for (p = table[i]; p; p = next)
- {
- next = p->next_same_hash;
- if (p->in_memory
- && (all
- || (nonscalar && p->in_struct)
- || cse_rtx_addr_varies_p (p->exp)))
- remove_from_table (p, i);
- }
- }
-
/* Remove from the hash table any expression that is a call-clobbered
register. Also update their TICK values. */
--- 1671,1674 ----
*************** invalidate_for_call ()
*** 1756,1759 ****
--- 1708,1717 ----
next = p->next_same_hash;
+ if (p->in_memory)
+ {
+ remove_from_table (p, hash);
+ continue;
+ }
+
if (GET_CODE (p->exp) != REG
|| REGNO (p->exp) >= FIRST_PSEUDO_REGISTER)
*************** canon_hash (x, mode)
*** 1946,1950 ****
return 0;
}
! if (! RTX_UNCHANGING_P (x))
{
hash_arg_in_memory = 1;
--- 1904,1908 ----
return 0;
}
! if (! RTX_UNCHANGING_P (x) || FIXED_BASE_PLUS_P (XEXP (x, 0)))
{
hash_arg_in_memory = 1;
*************** set_nonvarying_address_components (addr,
*** 2395,2477 ****
}
! /* Return 1 iff any subexpression of X refers to memory
! at an address of BASE plus some offset
! such that any of the bytes' offsets fall between START (inclusive)
! and END (exclusive).
!
! The value is undefined if X is a varying address (as determined by
! cse_rtx_addr_varies_p). This function is not used in such cases.
!
! When used in the cse pass, `qty_const' is nonzero, and it is used
! to treat an address that is a register with a known constant value
! as if it were that constant value.
! In the loop pass, `qty_const' is zero, so this is not done. */
!
! static int
! refers_to_mem_p (x, base, start, end)
! rtx x, base;
! HOST_WIDE_INT start, end;
! {
! register HOST_WIDE_INT i;
! register enum rtx_code code;
! register char *fmt;
!
! repeat:
! if (x == 0)
! return 0;
!
! code = GET_CODE (x);
! if (code == MEM)
! {
! register rtx addr = XEXP (x, 0); /* Get the address. */
! rtx mybase;
! HOST_WIDE_INT mystart, myend;
!
! set_nonvarying_address_components (addr, GET_MODE_SIZE (GET_MODE (x)),
! &mybase, &mystart, &myend);
!
!
! /* refers_to_mem_p is never called with varying addresses.
! If the base addresses are not equal, there is no chance
! of the memory addresses conflicting. */
! if (! rtx_equal_p (mybase, base))
! return 0;
!
! return myend > start && mystart < end;
! }
!
! /* X does not match, so try its subexpressions. */
!
! fmt = GET_RTX_FORMAT (code);
! for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
! if (fmt[i] == 'e')
! {
! if (i == 0)
! {
! x = XEXP (x, 0);
! goto repeat;
! }
! else
! if (refers_to_mem_p (XEXP (x, i), base, start, end))
! return 1;
! }
! else if (fmt[i] == 'E')
! {
! int j;
! for (j = 0; j < XVECLEN (x, i); j++)
! if (refers_to_mem_p (XVECEXP (x, i, j), base, start, end))
! return 1;
! }
!
! return 0;
! }
!
! /* Nonzero if X refers to memory at a varying address;
except that a register which has at the moment a known constant value
isn't considered variable. */
static int
! cse_rtx_addr_varies_p (x)
! rtx x;
{
/* We need not check for X and the equivalence class being of the same
--- 2353,2363 ----
}
! /* Nonzero if X, a memory address, refers to a varying address;
except that a register which has at the moment a known constant value
isn't considered variable. */
static int
! cse_rtx_varies_p (x)
! register rtx x;
{
/* We need not check for X and the equivalence class being of the same
*************** cse_rtx_addr_varies_p (x)
*** 2479,2497 ****
doesn't vary in any mode. */
! if (GET_CODE (x) == MEM
! && GET_CODE (XEXP (x, 0)) == REG
! && REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
! && GET_MODE (XEXP (x, 0)) == qty_mode[reg_qty[REGNO (XEXP (x, 0))]]
! && qty_const[reg_qty[REGNO (XEXP (x, 0))]] != 0)
return 0;
! if (GET_CODE (x) == MEM
! && GET_CODE (XEXP (x, 0)) == PLUS
! && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
! && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
! && REGNO_QTY_VALID_P (REGNO (XEXP (XEXP (x, 0), 0)))
! && (GET_MODE (XEXP (XEXP (x, 0), 0))
! == qty_mode[reg_qty[REGNO (XEXP (XEXP (x, 0), 0))]])
! && qty_const[reg_qty[REGNO (XEXP (XEXP (x, 0), 0))]])
return 0;
--- 2365,2381 ----
doesn't vary in any mode. */
! if (GET_CODE (x) == REG
! && REGNO_QTY_VALID_P (REGNO (x))
! && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]]
! && qty_const[reg_qty[REGNO (x)]] != 0)
return 0;
! if (GET_CODE (x) == PLUS
! && GET_CODE (XEXP (x, 1)) == CONST_INT
! && GET_CODE (XEXP (x, 0)) == REG
! && REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
! && (GET_MODE (XEXP (x, 0))
! == qty_mode[reg_qty[REGNO (XEXP (x, 0))]])
! && qty_const[reg_qty[REGNO (XEXP (x, 0))]])
return 0;
*************** cse_rtx_addr_varies_p (x)
*** 2501,2519 ****
load fp minus a constant into a register, then a MEM which is the
sum of the two `constant' registers. */
! if (GET_CODE (x) == MEM
! && GET_CODE (XEXP (x, 0)) == PLUS
! && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
! && GET_CODE (XEXP (XEXP (x, 0), 1)) == REG
! && REGNO_QTY_VALID_P (REGNO (XEXP (XEXP (x, 0), 0)))
! && (GET_MODE (XEXP (XEXP (x, 0), 0))
! == qty_mode[reg_qty[REGNO (XEXP (XEXP (x, 0), 0))]])
! && qty_const[reg_qty[REGNO (XEXP (XEXP (x, 0), 0))]]
! && REGNO_QTY_VALID_P (REGNO (XEXP (XEXP (x, 0), 1)))
! && (GET_MODE (XEXP (XEXP (x, 0), 1))
! == qty_mode[reg_qty[REGNO (XEXP (XEXP (x, 0), 1))]])
! && qty_const[reg_qty[REGNO (XEXP (XEXP (x, 0), 1))]])
return 0;
! return rtx_addr_varies_p (x);
}
--- 2385,2402 ----
load fp minus a constant into a register, then a MEM which is the
sum of the two `constant' registers. */
! if (GET_CODE (x) == PLUS
! && GET_CODE (XEXP (x, 0)) == REG
! && GET_CODE (XEXP (x, 1)) == REG
! && REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
! && (GET_MODE (XEXP (x, 0))
! == qty_mode[reg_qty[REGNO (XEXP (x, 0))]])
! && qty_const[reg_qty[REGNO (XEXP (x, 0))]]
! && REGNO_QTY_VALID_P (REGNO (XEXP (x, 1)))
! && (GET_MODE (XEXP (x, 1))
! == qty_mode[reg_qty[REGNO (XEXP (x, 1))]])
! && qty_const[reg_qty[REGNO (XEXP (x, 1))]])
return 0;
! return rtx_varies_p (x);
}
*************** cse_insn (insn, in_libcall_block)
*** 6105,6110 ****
rtx this_insn_cc0 = 0;
enum machine_mode this_insn_cc0_mode;
- struct write_data writes_memory;
- static struct write_data init = {0, 0, 0, 0};
rtx src_eqv = 0;
--- 5988,5991 ----
*************** cse_insn (insn, in_libcall_block)
*** 6118,6122 ****
this_insn = insn;
- writes_memory = init;
/* Find all the SETs and CLOBBERs in this instruction.
--- 5999,6002 ----
*************** cse_insn (insn, in_libcall_block)
*** 6220,6232 ****
else if (GET_CODE (y) == CLOBBER)
{
! /* If we clobber memory, take note of that,
! and canon the address.
This does nothing when a register is clobbered
because we have already invalidated the reg. */
if (GET_CODE (XEXP (y, 0)) == MEM)
! {
! canon_reg (XEXP (y, 0), NULL_RTX);
! note_mem_written (XEXP (y, 0), &writes_memory);
! }
}
else if (GET_CODE (y) == USE
--- 6100,6108 ----
else if (GET_CODE (y) == CLOBBER)
{
! /* If we clobber memory, canon the address.
This does nothing when a register is clobbered
because we have already invalidated the reg. */
if (GET_CODE (XEXP (y, 0)) == MEM)
! canon_reg (XEXP (y, 0), NULL_RTX);
}
else if (GET_CODE (y) == USE
*************** cse_insn (insn, in_libcall_block)
*** 6247,6254 ****
{
if (GET_CODE (XEXP (x, 0)) == MEM)
! {
! canon_reg (XEXP (x, 0), NULL_RTX);
! note_mem_written (XEXP (x, 0), &writes_memory);
! }
}
--- 6123,6127 ----
{
if (GET_CODE (XEXP (x, 0)) == MEM)
! canon_reg (XEXP (x, 0), NULL_RTX);
}
*************** cse_insn (insn, in_libcall_block)
*** 6674,6678 ****
}
#endif /* LOAD_EXTEND_OP */
!
if (src == src_folded)
src_folded = 0;
--- 6547,6551 ----
}
#endif /* LOAD_EXTEND_OP */
!
if (src == src_folded)
src_folded = 0;
*************** cse_insn (insn, in_libcall_block)
*** 6860,6864 ****
|| (GET_CODE (src_folded) != MEM
&& ! src_folded_force_flag))
! && GET_MODE_CLASS (mode) != MODE_CC)
{
src_folded_force_flag = 1;
--- 6733,6738 ----
|| (GET_CODE (src_folded) != MEM
&& ! src_folded_force_flag))
! && GET_MODE_CLASS (mode) != MODE_CC
! && mode != VOIDmode)
{
src_folded_force_flag = 1;
*************** cse_insn (insn, in_libcall_block)
*** 6983,6993 ****
if (GET_CODE (dest) == MEM)
{
dest = fold_rtx (dest, insn);
-
- /* Decide whether we invalidate everything in memory,
- or just things at non-fixed places.
- Writing a large aggregate must invalidate everything
- because we don't know how long it is. */
- note_mem_written (dest, &writes_memory);
}
--- 6857,6869 ----
if (GET_CODE (dest) == MEM)
{
+ #ifdef PUSH_ROUNDING
+ /* Stack pushes invalidate the stack pointer. */
+ rtx addr = XEXP (dest, 0);
+ if ((GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
+ || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
+ && XEXP (addr, 0) == stack_pointer_rtx)
+ invalidate (stack_pointer_rtx, Pmode);
+ #endif
dest = fold_rtx (dest, insn);
}
*************** cse_insn (insn, in_libcall_block)
*** 7234,7238 ****
sets[i].src_elt = src_eqv_elt;
! invalidate_from_clobbers (&writes_memory, x);
/* Some registers are invalidated by subroutine calls. Memory is
--- 7110,7114 ----
sets[i].src_elt = src_eqv_elt;
! invalidate_from_clobbers (x);
/* Some registers are invalidated by subroutine calls. Memory is
*************** cse_insn (insn, in_libcall_block)
*** 7241,7248 ****
if (GET_CODE (insn) == CALL_INSN)
{
- static struct write_data everything = {0, 1, 1, 1};
-
if (! CONST_CALL_P (insn))
! invalidate_memory (&everything);
invalidate_for_call ();
}
--- 7117,7122 ----
if (GET_CODE (insn) == CALL_INSN)
{
if (! CONST_CALL_P (insn))
! invalidate_memory ();
invalidate_for_call ();
}
*************** cse_insn (insn, in_libcall_block)
*** 7265,7270 ****
we have just done an invalidate_memory that covers even those. */
if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
! || (GET_CODE (dest) == MEM && ! writes_memory.all
! && ! cse_rtx_addr_varies_p (dest)))
invalidate (dest, VOIDmode);
else if (GET_CODE (dest) == STRICT_LOW_PART
--- 7139,7143 ----
we have just done an invalidate_memory that covers even those. */
if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
! || GET_CODE (dest) == MEM)
invalidate (dest, VOIDmode);
else if (GET_CODE (dest) == STRICT_LOW_PART
*************** cse_insn (insn, in_libcall_block)
*** 7359,7363 ****
sets[i].dest_hash, GET_MODE (dest));
elt->in_memory = (GET_CODE (sets[i].inner_dest) == MEM
! && ! RTX_UNCHANGING_P (sets[i].inner_dest));
if (elt->in_memory)
--- 7232,7238 ----
sets[i].dest_hash, GET_MODE (dest));
elt->in_memory = (GET_CODE (sets[i].inner_dest) == MEM
! && (! RTX_UNCHANGING_P (sets[i].inner_dest)
! || FIXED_BASE_PLUS_P (XEXP (sets[i].inner_dest,
! 0))));
if (elt->in_memory)
*************** cse_insn (insn, in_libcall_block)
*** 7532,7580 ****
}
- /* Store 1 in *WRITES_PTR for those categories of memory ref
- that must be invalidated when the expression WRITTEN is stored in.
- If WRITTEN is null, say everything must be invalidated. */
-
static void
! note_mem_written (written, writes_ptr)
! rtx written;
! struct write_data *writes_ptr;
! {
! static struct write_data everything = {0, 1, 1, 1};
!
! if (written == 0)
! *writes_ptr = everything;
! else if (GET_CODE (written) == MEM)
! {
! /* Pushing or popping the stack invalidates just the stack pointer. */
! rtx addr = XEXP (written, 0);
! if ((GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
! || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
! && GET_CODE (XEXP (addr, 0)) == REG
! && REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
! {
! writes_ptr->sp = 1;
! return;
! }
! else if (GET_MODE (written) == BLKmode)
! *writes_ptr = everything;
! /* (mem (scratch)) means clobber everything. */
! else if (GET_CODE (addr) == SCRATCH)
! *writes_ptr = everything;
! else if (cse_rtx_addr_varies_p (written))
! {
! /* A varying address that is a sum indicates an array element,
! and that's just as good as a structure element
! in implying that we need not invalidate scalar variables.
! However, we must allow QImode aliasing of scalars, because the
! ANSI C standard allows character pointers to alias anything. */
! if (! ((MEM_IN_STRUCT_P (written)
! || GET_CODE (XEXP (written, 0)) == PLUS)
! && GET_MODE (written) != QImode))
! writes_ptr->all = 1;
! writes_ptr->nonscalar = 1;
! }
! writes_ptr->var = 1;
}
}
--- 7407,7450 ----
}
static void
! invalidate_memory ()
! {
! register int i;
! register struct table_elt *p, *next;
!
! for (i = 0; i < NBUCKETS; i++)
! for (p = table[i]; p; p = next)
! {
! next = p->next_same_hash;
! if (p->in_memory)
! remove_from_table (p, i);
! }
! }
!
! static int
! note_mem_written (mem)
! register rtx mem;
! {
! if (mem == 0 || GET_CODE(mem) != MEM )
! return 0;
! else
! {
! register rtx addr = XEXP (mem, 0);
! /* Pushing or popping the stack invalidates just the stack pointer. */
! if ((GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
! || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
! && GET_CODE (XEXP (addr, 0)) == REG
! && REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
! {
! if (reg_tick[STACK_POINTER_REGNUM] >= 0)
! reg_tick[STACK_POINTER_REGNUM]++;
!
! /* This should be *very* rare. */
! if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM))
! invalidate (stack_pointer_rtx, VOIDmode);
! return 1;
}
+ return 0;
+ }
}
*************** note_mem_written (written, writes_ptr)
*** 7584,7612 ****
alias with something that is SET or CLOBBERed.
- W points to the writes_memory for this insn, a struct write_data
- saying which kinds of memory references must be invalidated.
X is the pattern of the insn. */
static void
! invalidate_from_clobbers (w, x)
! struct write_data *w;
rtx x;
{
- /* If W->var is not set, W specifies no action.
- If W->all is set, this step gets all memory refs
- so they can be ignored in the rest of this function. */
- if (w->var)
- invalidate_memory (w);
-
- if (w->sp)
- {
- if (reg_tick[STACK_POINTER_REGNUM] >= 0)
- reg_tick[STACK_POINTER_REGNUM]++;
-
- /* This should be *very* rare. */
- if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM))
- invalidate (stack_pointer_rtx, VOIDmode);
- }
-
if (GET_CODE (x) == CLOBBER)
{
--- 7454,7463 ----
alias with something that is SET or CLOBBERed.
X is the pattern of the insn. */
static void
! invalidate_from_clobbers (x)
rtx x;
{
if (GET_CODE (x) == CLOBBER)
{
*************** invalidate_from_clobbers (w, x)
*** 7615,7619 ****
{
if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
! || (GET_CODE (ref) == MEM && ! w->all))
invalidate (ref, VOIDmode);
else if (GET_CODE (ref) == STRICT_LOW_PART
--- 7466,7470 ----
{
if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
! || GET_CODE (ref) == MEM)
invalidate (ref, VOIDmode);
else if (GET_CODE (ref) == STRICT_LOW_PART
*************** invalidate_from_clobbers (w, x)
*** 7631,7643 ****
{
rtx ref = XEXP (y, 0);
! if (ref)
! {
! if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
! || (GET_CODE (ref) == MEM && !w->all))
! invalidate (ref, VOIDmode);
! else if (GET_CODE (ref) == STRICT_LOW_PART
! || GET_CODE (ref) == ZERO_EXTRACT)
! invalidate (XEXP (ref, 0), GET_MODE (ref));
! }
}
}
--- 7482,7491 ----
{
rtx ref = XEXP (y, 0);
! if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
! || GET_CODE (ref) == MEM)
! invalidate (ref, VOIDmode);
! else if (GET_CODE (ref) == STRICT_LOW_PART
! || GET_CODE (ref) == ZERO_EXTRACT)
! invalidate (XEXP (ref, 0), GET_MODE (ref));
}
}
*************** cse_around_loop (loop_start)
*** 7800,7807 ****
}
- /* Variable used for communications between the next two routines. */
-
- static struct write_data skipped_writes_memory;
-
/* Process one SET of an insn that was skipped. We ignore CLOBBERs
since they are done elsewhere. This function is called via note_stores. */
--- 7648,7651 ----
*************** invalidate_skipped_set (dest, set)
*** 7812,7815 ****
--- 7656,7675 ----
rtx dest;
{
+ enum rtx_code code = GET_CODE (dest);
+
+ if (code == MEM
+ && ! note_mem_written (dest) /* If this is not a stack push ... */
+ /* There are times when an address can appear varying and be a PLUS
+ during this scan when it would be a fixed address were we to know
+ the proper equivalences. So invalidate all memory if there is
+ a BLKmode or nonscalar memory reference or a reference to a
+ variable address. */
+ && (MEM_IN_STRUCT_P (dest) || GET_MODE (dest) == BLKmode
+ || cse_rtx_varies_p (XEXP (dest, 0))))
+ {
+ invalidate_memory ();
+ return;
+ }
+
if (GET_CODE (set) == CLOBBER
#ifdef HAVE_cc0
*************** invalidate_skipped_set (dest, set)
*** 7819,7837 ****
return;
! if (GET_CODE (dest) == MEM)
! note_mem_written (dest, &skipped_writes_memory);
!
! /* There are times when an address can appear varying and be a PLUS
! during this scan when it would be a fixed address were we to know
! the proper equivalences. So promote "nonscalar" to be "all". */
! if (skipped_writes_memory.nonscalar)
! skipped_writes_memory.all = 1;
!
! if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
! || (! skipped_writes_memory.all && ! cse_rtx_addr_varies_p (dest)))
! invalidate (dest, VOIDmode);
! else if (GET_CODE (dest) == STRICT_LOW_PART
! || GET_CODE (dest) == ZERO_EXTRACT)
invalidate (XEXP (dest, 0), GET_MODE (dest));
}
--- 7679,7686 ----
return;
! if (code == STRICT_LOW_PART || code == ZERO_EXTRACT)
invalidate (XEXP (dest, 0), GET_MODE (dest));
+ else if (code == REG || code == SUBREG || code == MEM)
+ invalidate (dest, VOIDmode);
}
*************** invalidate_skipped_block (start)
*** 7845,7850 ****
{
rtx insn;
- static struct write_data init = {0, 0, 0, 0};
- static struct write_data everything = {0, 1, 1, 1};
for (insn = start; insn && GET_CODE (insn) != CODE_LABEL;
--- 7694,7697 ----
*************** invalidate_skipped_block (start)
*** 7854,7867 ****
continue;
- skipped_writes_memory = init;
-
if (GET_CODE (insn) == CALL_INSN)
{
invalidate_for_call ();
- skipped_writes_memory = everything;
}
note_stores (PATTERN (insn), invalidate_skipped_set);
- invalidate_from_clobbers (&skipped_writes_memory, PATTERN (insn));
}
}
--- 7701,7712 ----
continue;
if (GET_CODE (insn) == CALL_INSN)
{
+ if (! CONST_CALL_P (insn))
+ invalidate_memory ();
invalidate_for_call ();
}
note_stores (PATTERN (insn), invalidate_skipped_set);
}
}
*************** cse_set_around_loop (x, insn, loop_start
*** 7913,7920 ****
{
struct table_elt *src_elt;
- static struct write_data init = {0, 0, 0, 0};
- struct write_data writes_memory;
-
- writes_memory = init;
/* If this is a SET, see if we can replace SET_SRC, but ignore SETs that
--- 7758,7761 ----
*************** cse_set_around_loop (x, insn, loop_start
*** 7976,7991 ****
/* Now invalidate anything modified by X. */
! note_mem_written (SET_DEST (x), &writes_memory);
!
! if (writes_memory.var)
! invalidate_memory (&writes_memory);
!
! /* See comment on similar code in cse_insn for explanation of these tests. */
if (GET_CODE (SET_DEST (x)) == REG || GET_CODE (SET_DEST (x)) == SUBREG
! || (GET_CODE (SET_DEST (x)) == MEM && ! writes_memory.all
! && ! cse_rtx_addr_varies_p (SET_DEST (x))))
invalidate (SET_DEST (x), VOIDmode);
else if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
! || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
invalidate (XEXP (SET_DEST (x), 0), GET_MODE (SET_DEST (x)));
}
--- 7817,7828 ----
/* Now invalidate anything modified by X. */
! note_mem_written (SET_DEST (x));
!
! /* See comment on similar code in cse_insn for explanation of these tests. */
if (GET_CODE (SET_DEST (x)) == REG || GET_CODE (SET_DEST (x)) == SUBREG
! || GET_CODE (SET_DEST (x)) == MEM)
invalidate (SET_DEST (x), VOIDmode);
else if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
! || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
invalidate (XEXP (SET_DEST (x), 0), GET_MODE (SET_DEST (x)));
}
*************** cse_main (f, nregs, after_loop, file)
*** 8234,8237 ****
--- 8071,8075 ----
init_recog ();
+ init_alias_analysis ();
max_reg = nregs;
*************** cse_basic_block (from, to, next_branch,
*** 8405,8408 ****
--- 8243,8247 ----
int to_usage = 0;
int in_libcall_block = 0;
+ int num_insns = 0;
/* Each of these arrays is undefined before max_reg, so only allocate
*************** cse_basic_block (from, to, next_branch,
*** 8437,8440 ****
--- 8276,8299 ----
{
register enum rtx_code code;
+ int i;
+ struct table_elt *p, *next;
+
+ /* If we have processed 1,000 insns, flush the hash table to avoid
+ extreme quadratic behavior. */
+ if (num_insns++ > 1000)
+ {
+ for (i = 0; i < NBUCKETS; i++)
+ for (p = table[i]; p; p = next)
+ {
+ next = p->next_same_hash;
+
+ if (GET_CODE (p->exp) == REG)
+ invalidate (p->exp, p->mode);
+ else
+ remove_from_table (p, i);
+ }
+
+ num_insns = 0;
+ }
/* See if this is a branch that is part of the path. If so, and it is
diff -rcp2N gcc-2.7.2.2/dwarfout.c g77-new/dwarfout.c
*** gcc-2.7.2.2/dwarfout.c Thu Oct 26 21:40:07 1995
--- g77-new/dwarfout.c Sun Aug 10 18:47:19 1997
*************** output_bound_representation (bound, dim_
*** 1629,1705 ****
{
! case ERROR_MARK:
! return;
/* All fixed-bounds are represented by INTEGER_CST nodes. */
! case INTEGER_CST:
! ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
! (unsigned) TREE_INT_CST_LOW (bound));
! break;
!
! /* Dynamic bounds may be represented by NOP_EXPR nodes containing
! SAVE_EXPR nodes. */
!
! case NOP_EXPR:
! bound = TREE_OPERAND (bound, 0);
! /* ... fall thru... */
!
! case SAVE_EXPR:
! {
! char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
! char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
!
! sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
! current_dienum, dim_num, u_or_l);
! sprintf (end_label, BOUND_END_LABEL_FMT,
! current_dienum, dim_num, u_or_l);
! ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
! ASM_OUTPUT_LABEL (asm_out_file, begin_label);
! /* If we are working on a bound for a dynamic dimension in C,
! the dynamic dimension in question had better have a static
! (zero) lower bound and a dynamic *upper* bound. */
! if (u_or_l != 'u')
! abort ();
! /* If optimization is turned on, the SAVE_EXPRs that describe
! how to access the upper bound values are essentially bogus.
! They only describe (at best) how to get at these values at
! the points in the generated code right after they have just
! been computed. Worse yet, in the typical case, the upper
! bound values will not even *be* computed in the optimized
! code, so these SAVE_EXPRs are entirely bogus.
!
! In order to compensate for this fact, we check here to see
! if optimization is enabled, and if so, we effectively create
! an empty location description for the (unknown and unknowable)
! upper bound.
!
! This should not cause too much trouble for existing (stupid?)
! debuggers because they have to deal with empty upper bounds
! location descriptions anyway in order to be able to deal with
! incomplete array types.
!
! Of course an intelligent debugger (GDB?) should be able to
! comprehend that a missing upper bound specification in a
! array type used for a storage class `auto' local array variable
! indicates that the upper bound is both unknown (at compile-
! time) and unknowable (at run-time) due to optimization.
! */
!
! if (! optimize)
! output_loc_descriptor
! (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));
! ASM_OUTPUT_LABEL (asm_out_file, end_label);
! }
! break;
- default:
- abort ();
}
}
--- 1629,1699 ----
{
! case ERROR_MARK:
! return;
/* All fixed-bounds are represented by INTEGER_CST nodes. */
! case INTEGER_CST:
! ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
! (unsigned) TREE_INT_CST_LOW (bound));
! break;
! default:
! /* Dynamic bounds may be represented by NOP_EXPR nodes containing
! SAVE_EXPR nodes, in which case we can do something, or as
! an expression, which we cannot represent. */
! {
! char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
! char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
! sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
! current_dienum, dim_num, u_or_l);
! sprintf (end_label, BOUND_END_LABEL_FMT,
! current_dienum, dim_num, u_or_l);
! ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
! ASM_OUTPUT_LABEL (asm_out_file, begin_label);
!
! /* If optimization is turned on, the SAVE_EXPRs that describe
! how to access the upper bound values are essentially bogus.
! They only describe (at best) how to get at these values at
! the points in the generated code right after they have just
! been computed. Worse yet, in the typical case, the upper
! bound values will not even *be* computed in the optimized
! code, so these SAVE_EXPRs are entirely bogus.
!
! In order to compensate for this fact, we check here to see
! if optimization is enabled, and if so, we effectively create
! an empty location description for the (unknown and unknowable)
! upper bound.
!
! This should not cause too much trouble for existing (stupid?)
! debuggers because they have to deal with empty upper bounds
! location descriptions anyway in order to be able to deal with
! incomplete array types.
!
! Of course an intelligent debugger (GDB?) should be able to
! comprehend that a missing upper bound specification in a
! array type used for a storage class `auto' local array variable
! indicates that the upper bound is both unknown (at compile-
! time) and unknowable (at run-time) due to optimization. */
!
! if (! optimize)
! {
! while (TREE_CODE (bound) == NOP_EXPR
! || TREE_CODE (bound) == CONVERT_EXPR)
! bound = TREE_OPERAND (bound, 0);
!
! if (TREE_CODE (bound) == SAVE_EXPR)
! output_loc_descriptor
! (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));
! }
! ASM_OUTPUT_LABEL (asm_out_file, end_label);
! }
! break;
}
}
*************** type_attribute (type, decl_const, decl_v
*** 2857,2861 ****
register int root_type_modified;
! if (TREE_CODE (type) == ERROR_MARK)
return;
--- 2851,2855 ----
register int root_type_modified;
! if (code == ERROR_MARK)
return;
*************** type_attribute (type, decl_const, decl_v
*** 2864,2869 ****
type `void', so this only applies to function return types. */
! if (TREE_CODE (type) == VOID_TYPE)
return;
root_type_modified = (code == POINTER_TYPE || code == REFERENCE_TYPE
--- 2858,2869 ----
type `void', so this only applies to function return types. */
! if (code == VOID_TYPE)
return;
+
+ /* If this is a subtype, find the underlying type. Eventually,
+ this should write out the appropriate subtype info. */
+ while ((code == INTEGER_TYPE || code == REAL_TYPE)
+ && TREE_TYPE (type) != 0)
+ type = TREE_TYPE (type), code = TREE_CODE (type);
root_type_modified = (code == POINTER_TYPE || code == REFERENCE_TYPE
diff -rcp2N gcc-2.7.2.2/emit-rtl.c g77-new/emit-rtl.c
*** gcc-2.7.2.2/emit-rtl.c Thu Sep 14 16:09:30 1995
--- g77-new/emit-rtl.c Sun Aug 10 18:47:08 1997
*************** max_label_num ()
*** 545,548 ****
--- 545,565 ----
}
+ /* Identify REG (which may be a CONCAT) as a user register. */
+
+ void
+ mark_user_reg (reg)
+ rtx reg;
+ {
+ if (GET_CODE (reg) == CONCAT)
+ {
+ REG_USERVAR_P (XEXP (reg, 0)) = 1;
+ REG_USERVAR_P (XEXP (reg, 1)) = 1;
+ }
+ else if (GET_CODE (reg) == REG)
+ REG_USERVAR_P (reg) = 1;
+ else
+ abort ();
+ }
+
/* Return first label number used in this function (if any were used). */
*************** change_address (memref, mode, addr)
*** 1315,1318 ****
--- 1332,1338 ----
addr = memory_address (mode, addr);
+ if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref))
+ return memref;
+
new = gen_rtx (MEM, mode, addr);
MEM_VOLATILE_P (new) = MEM_VOLATILE_P (memref);
diff -rcp2N gcc-2.7.2.2/explow.c g77-new/explow.c
*** gcc-2.7.2.2/explow.c Thu Jun 15 07:30:10 1995
--- g77-new/explow.c Sun Aug 10 18:46:30 1997
*************** convert_memory_address (to_mode, x)
*** 305,310 ****
--- 305,313 ----
rtx x;
{
+ enum machine_mode from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
rtx temp;
+ /* Here we handle some special cases. If none of them apply, fall through
+ to the default case. */
switch (GET_CODE (x))
{
*************** convert_memory_address (to_mode, x)
*** 321,339 ****
return temp;
- case PLUS:
- case MULT:
- return gen_rtx (GET_CODE (x), to_mode,
- convert_memory_address (to_mode, XEXP (x, 0)),
- convert_memory_address (to_mode, XEXP (x, 1)));
-
case CONST:
return gen_rtx (CONST, to_mode,
convert_memory_address (to_mode, XEXP (x, 0)));
! default:
! return convert_modes (to_mode,
! to_mode == ptr_mode ? Pmode : ptr_mode,
! x, POINTERS_EXTEND_UNSIGNED);
}
}
#endif
--- 324,348 ----
return temp;
case CONST:
return gen_rtx (CONST, to_mode,
convert_memory_address (to_mode, XEXP (x, 0)));
! case PLUS:
! case MULT:
! /* For addition the second operand is a small constant, we can safely
! permute the converstion and addition operation. We can always safely
! permute them if we are making the address narrower. In addition,
! always permute the operations if this is a constant. */
! if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
! || (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT
! && (INTVAL (XEXP (x, 1)) + 20000 < 40000
! || CONSTANT_P (XEXP (x, 0)))))
! return gen_rtx (GET_CODE (x), to_mode,
! convert_memory_address (to_mode, XEXP (x, 0)),
! convert_memory_address (to_mode, XEXP (x, 1)));
}
+
+ return convert_modes (to_mode, from_mode,
+ x, POINTERS_EXTEND_UNSIGNED);
}
#endif
diff -rcp2N gcc-2.7.2.2/expmed.c g77-new/expmed.c
*** gcc-2.7.2.2/expmed.c Thu Jul 13 19:25:37 1995
--- g77-new/expmed.c Sun Aug 10 18:46:23 1997
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 399,402 ****
--- 399,403 ----
#ifdef HAVE_insv
if (HAVE_insv
+ && GET_MODE (value) != BLKmode
&& !(bitsize == 1 && GET_CODE (value) == CONST_INT)
/* Ensure insv's size is wide enough for this field. */
*************** store_split_bit_field (op0, bitsize, bit
*** 777,781 ****
done in extract_bit_field, so that the two calls to
extract_fixed_bit_field will have comparable arguments. */
! if (GET_CODE (value) != MEM)
total_bits = BITS_PER_WORD;
else
--- 778,782 ----
done in extract_bit_field, so that the two calls to
extract_fixed_bit_field will have comparable arguments. */
! if (GET_CODE (value) != MEM || GET_MODE (value) == BLKmode)
total_bits = BITS_PER_WORD;
else
*************** store_split_bit_field (op0, bitsize, bit
*** 790,797 ****
/* The args are chosen so that the last part includes the
lsb. Give extract_bit_field the value it needs (with
! endianness compensation) to fetch the piece we want. */
! part = extract_fixed_bit_field (word_mode, value, 0, thissize,
! total_bits - bitsize + bitsdone,
! NULL_RTX, 1, align);
}
else
--- 791,807 ----
/* The args are chosen so that the last part includes the
lsb. Give extract_bit_field the value it needs (with
! endianness compensation) to fetch the piece we want.
!
! ??? We have no idea what the alignment of VALUE is, so
! we have to use a guess. */
! part
! = extract_fixed_bit_field
! (word_mode, value, 0, thissize,
! total_bits - bitsize + bitsdone, NULL_RTX, 1,
! GET_MODE (value) == VOIDmode
! ? UNITS_PER_WORD
! : (GET_MODE (value) == BLKmode
! ? 1
! : GET_MODE_ALIGNMENT (GET_MODE (value)) / BITS_PER_UNIT));
}
else
*************** store_split_bit_field (op0, bitsize, bit
*** 803,808 ****
& (((HOST_WIDE_INT) 1 << thissize) - 1));
else
! part = extract_fixed_bit_field (word_mode, value, 0, thissize,
! bitsdone, NULL_RTX, 1, align);
}
--- 813,824 ----
& (((HOST_WIDE_INT) 1 << thissize) - 1));
else
! part
! = extract_fixed_bit_field
! (word_mode, value, 0, thissize, bitsdone, NULL_RTX, 1,
! GET_MODE (value) == VOIDmode
! ? UNITS_PER_WORD
! : (GET_MODE (value) == BLKmode
! ? 1
! : GET_MODE_ALIGNMENT (GET_MODE (value)) / BITS_PER_UNIT));
}
*************** extract_bit_field (str_rtx, bitsize, bit
*** 876,882 ****
rtx spec_target_subreg = 0;
- if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx))
- abort ();
-
/* Discount the part of the structure before the desired byte.
We need to know how many bytes are safe to reference after it. */
--- 892,895 ----
*************** expand_divmod (rem_flag, code, mode, op0
*** 3189,3193 ****
Notice that we compute also the final remainder value here,
and return the result right away. */
! if (target == 0)
target = gen_reg_rtx (compute_mode);
--- 3202,3206 ----
Notice that we compute also the final remainder value here,
and return the result right away. */
! if (target == 0 || GET_MODE (target) != compute_mode)
target = gen_reg_rtx (compute_mode);
*************** expand_divmod (rem_flag, code, mode, op0
*** 3316,3320 ****
remainder. Notice that we compute also the final remainder
value here, and return the result right away. */
! if (target == 0)
target = gen_reg_rtx (compute_mode);
--- 3329,3333 ----
remainder. Notice that we compute also the final remainder
value here, and return the result right away. */
! if (target == 0 || GET_MODE (target) != compute_mode)
target = gen_reg_rtx (compute_mode);
*************** expand_divmod (rem_flag, code, mode, op0
*** 3418,3422 ****
remainder. Notice that we compute also the final remainder
value here, and return the result right away. */
! if (target == 0)
target = gen_reg_rtx (compute_mode);
if (rem_flag)
--- 3431,3435 ----
remainder. Notice that we compute also the final remainder
value here, and return the result right away. */
! if (target == 0 || GET_MODE (target) != compute_mode)
target = gen_reg_rtx (compute_mode);
if (rem_flag)
*************** expand_divmod (rem_flag, code, mode, op0
*** 3602,3605 ****
--- 3615,3621 ----
if (quotient == 0)
{
+ if (target && GET_MODE (target) != compute_mode)
+ target = 0;
+
if (rem_flag)
{
*************** expand_divmod (rem_flag, code, mode, op0
*** 3653,3656 ****
--- 3669,3675 ----
if (rem_flag)
{
+ if (target && GET_MODE (target) != compute_mode)
+ target = 0;
+
if (quotient == 0)
/* No divide instruction either. Use library for remainder. */
diff -rcp2N gcc-2.7.2.2/expr.c g77-new/expr.c
*** gcc-2.7.2.2/expr.c Thu Feb 20 19:24:17 1997
--- g77-new/expr.c Sun Aug 10 18:47:21 1997
*************** Boston, MA 02111-1307, USA. */
*** 27,30 ****
--- 27,31 ----
#include "flags.h"
#include "regs.h"
+ #include "hard-reg-set.h"
#include "function.h"
#include "insn-flags.h"
*************** extern int stack_depth;
*** 139,143 ****
extern int max_stack_depth;
extern struct obstack permanent_obstack;
!
static rtx enqueue_insn PROTO((rtx, rtx));
--- 140,144 ----
extern int max_stack_depth;
extern struct obstack permanent_obstack;
! extern rtx arg_pointer_save_area;
static rtx enqueue_insn PROTO((rtx, rtx));
*************** expand_assignment (to, from, want_value,
*** 2498,2503 ****
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,
--- 2499,2504 ----
push_temp_slots ();
! tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
! &unsignedp, &volatilep, &alignment);
/* If we are going to use store_bit_field and extract_bit_field,
*************** expand_assignment (to, from, want_value,
*** 2507,2511 ****
tem = stabilize_reference (tem);
- alignment = TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT;
to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
if (offset != 0)
--- 2508,2511 ----
*************** expand_assignment (to, from, want_value,
*** 2518,2529 ****
gen_rtx (PLUS, ptr_mode, XEXP (to_rtx, 0),
force_reg (ptr_mode, offset_rtx)));
- /* If we have a variable offset, the known alignment
- is only that of the innermost structure containing the field.
- (Actually, we could sometimes do better by using the
- align of an element of the innermost array, but no need.) */
- if (TREE_CODE (to) == COMPONENT_REF
- || TREE_CODE (to) == BIT_FIELD_REF)
- alignment
- = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (to, 0))) / BITS_PER_UNIT;
}
if (volatilep)
--- 2518,2521 ----
*************** store_expr (exp, target, want_value)
*** 2775,2780 ****
which will often result in some optimizations. Do the conversion
in two steps: first change the signedness, if needed, then
! the extend. */
! if (! want_value)
{
if (TREE_UNSIGNED (TREE_TYPE (exp))
--- 2767,2775 ----
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 && INTEGRAL_TYPE_P (TREE_TYPE (exp))
! && TREE_TYPE (TREE_TYPE (exp)) == 0)
{
if (TREE_UNSIGNED (TREE_TYPE (exp))
*************** store_constructor (exp, target)
*** 3071,3074 ****
--- 3066,3077 ----
}
+ if (TREE_READONLY (field))
+ {
+ if (GET_CODE (to_rtx) == MEM)
+ to_rtx = change_address (to_rtx, GET_MODE (to_rtx),
+ XEXP (to_rtx, 0));
+ RTX_UNCHANGING_P (to_rtx) = 1;
+ }
+
store_field (to_rtx, bitsize, bitpos, mode, TREE_VALUE (elt),
/* The alignment of TARGET is
*************** store_field (target, bitsize, bitpos, mo
*** 3414,3417 ****
--- 3417,3432 ----
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 < 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. */
*************** store_field (target, bitsize, bitpos, mo
*** 3420,3423 ****
--- 3435,3459 ----
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 = change_address (target, VOIDmode,
+ plus_constant (XEXP (target, 0),
+ bitpos / BITS_PER_UNIT));
+
+ emit_block_move (target, temp,
+ GEN_INT ((bitsize + BITS_PER_UNIT - 1)
+ / BITS_PER_UNIT),
+ 1);
+
+ return value_mode == VOIDmode ? const0_rtx : target;
+ }
+
/* Store the value in the bitfield. */
store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size);
*************** get_inner_unaligned_p (exp)
*** 3515,3518 ****
--- 3551,3557 ----
This offset is in addition to the bit position.
If the position is not variable, we store 0 in *POFFSET.
+ We set *PALIGNMENT to the alignment in bytes of the address that will be
+ computed. This is the alignment of the thing we return if *POFFSET
+ is zero, but can be more less strictly aligned if *POFFSET is nonzero.
If any of the extraction expressions is volatile,
*************** get_inner_unaligned_p (exp)
*** 3525,3533 ****
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;
int *pbitsize;
--- 3564,3572 ----
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, palignment)
tree exp;
int *pbitsize;
*************** get_inner_reference (exp, pbitsize, pbit
*** 3537,3540 ****
--- 3576,3580 ----
int *punsignedp;
int *pvolatilep;
+ int *palignment;
{
tree orig_exp = exp;
*************** get_inner_reference (exp, pbitsize, pbit
*** 3542,3545 ****
--- 3582,3586 ----
enum machine_mode mode = VOIDmode;
tree offset = integer_zero_node;
+ int alignment = BIGGEST_ALIGNMENT;
if (TREE_CODE (exp) == COMPONENT_REF)
*************** get_inner_reference (exp, pbitsize, pbit
*** 3599,3607 ****
*pbitpos += TREE_INT_CST_LOW (constant);
!
! if (var)
! offset = size_binop (PLUS_EXPR, offset,
! size_binop (EXACT_DIV_EXPR, var,
! size_int (BITS_PER_UNIT)));
}
--- 3640,3646 ----
*pbitpos += TREE_INT_CST_LOW (constant);
! offset = size_binop (PLUS_EXPR, offset,
! size_binop (EXACT_DIV_EXPR, var,
! size_int (BITS_PER_UNIT)));
}
*************** get_inner_reference (exp, pbitsize, pbit
*** 3629,3633 ****
index = fold (build (MULT_EXPR, index_type, index,
! TYPE_SIZE (TREE_TYPE (exp))));
if (TREE_CODE (index) == INTEGER_CST
--- 3668,3673 ----
index = fold (build (MULT_EXPR, index_type, index,
! convert (index_type,
! TYPE_SIZE (TREE_TYPE (exp)))));
if (TREE_CODE (index) == INTEGER_CST
*************** get_inner_reference (exp, pbitsize, pbit
*** 3652,3666 ****
if (TREE_THIS_VOLATILE (exp))
*pvolatilep = 1;
exp = TREE_OPERAND (exp, 0);
}
! /* If this was a bit-field, see if there is a mode that allows direct
! access in case EXP is in memory. */
! if (mode == VOIDmode && *pbitsize != 0 && *pbitpos % *pbitsize == 0)
! {
! mode = mode_for_size (*pbitsize, MODE_INT, 0);
! if (mode == BLKmode)
! mode = VOIDmode;
! }
if (integer_zerop (offset))
--- 3692,3708 ----
if (TREE_THIS_VOLATILE (exp))
*pvolatilep = 1;
+
+ /* If the offset is non-constant already, then we can't assume any
+ alignment more than the alignment here. */
+ if (! integer_zerop (offset))
+ alignment = MIN (alignment, TYPE_ALIGN (TREE_TYPE (exp)));
+
exp = TREE_OPERAND (exp, 0);
}
! if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
! alignment = MIN (alignment, DECL_ALIGN (exp));
! else if (TREE_TYPE (exp) != 0)
! alignment = MIN (alignment, TYPE_ALIGN (TREE_TYPE (exp)));
if (integer_zerop (offset))
*************** get_inner_reference (exp, pbitsize, pbit
*** 3672,3675 ****
--- 3714,3718 ----
*pmode = mode;
*poffset = offset;
+ *palignment = alignment / BITS_PER_UNIT;
return exp;
}
*************** init_noncopied_parts (lhs, list)
*** 3812,3820 ****
}
! /* Subroutine of expand_expr: return nonzero iff there is no way that
EXP can reference X, which is being modified. */
static int
! safe_from_p (x, exp)
rtx x;
tree exp;
--- 3855,3867 ----
}
! static int safe_from_p_count;
! static int safe_from_p_size;
! static tree *safe_from_p_rewritten;
!
! /* Subroutine of safe_from_p: return nonzero iff there is no way that
EXP can reference X, which is being modified. */
static int
! safe_from_p_1 (x, exp)
rtx x;
tree exp;
*************** safe_from_p (x, exp)
*** 3822,3825 ****
--- 3869,3873 ----
rtx exp_rtl = 0;
int i, nops;
+ int is_save_expr = 0;
if (x == 0
*************** safe_from_p (x, exp)
*** 3860,3878 ****
case 'x':
! if (TREE_CODE (exp) == TREE_LIST)
! return ((TREE_VALUE (exp) == 0
! || safe_from_p (x, TREE_VALUE (exp)))
! && (TREE_CHAIN (exp) == 0
! || safe_from_p (x, TREE_CHAIN (exp))));
! else
! return 0;
case '1':
! return safe_from_p (x, TREE_OPERAND (exp, 0));
case '2':
case '<':
! return (safe_from_p (x, TREE_OPERAND (exp, 0))
! && safe_from_p (x, TREE_OPERAND (exp, 1)));
case 'e':
--- 3908,3933 ----
case 'x':
! switch (TREE_CODE (exp))
! {
! case TREE_LIST:
! return ((TREE_VALUE (exp) == 0
! || safe_from_p_1 (x, TREE_VALUE (exp)))
! && (TREE_CHAIN (exp) == 0
! || safe_from_p_1 (x, TREE_CHAIN (exp))));
!
! case ERROR_MARK:
! return 1;
!
! default:
! return 0;
! }
case '1':
! return safe_from_p_1 (x, TREE_OPERAND (exp, 0));
case '2':
case '<':
! return (safe_from_p_1 (x, TREE_OPERAND (exp, 0))
! && safe_from_p_1 (x, TREE_OPERAND (exp, 1)));
case 'e':
*************** safe_from_p (x, exp)
*** 3887,3891 ****
case ADDR_EXPR:
return (staticp (TREE_OPERAND (exp, 0))
! || safe_from_p (x, TREE_OPERAND (exp, 0)));
case INDIRECT_REF:
--- 3942,3946 ----
case ADDR_EXPR:
return (staticp (TREE_OPERAND (exp, 0))
! || safe_from_p_1 (x, TREE_OPERAND (exp, 0)));
case INDIRECT_REF:
*************** safe_from_p (x, exp)
*** 3922,3928 ****
case CLEANUP_POINT_EXPR:
! return safe_from_p (x, TREE_OPERAND (exp, 0));
case SAVE_EXPR:
exp_rtl = SAVE_EXPR_RTL (exp);
break;
--- 3977,3984 ----
case CLEANUP_POINT_EXPR:
! return safe_from_p_1 (x, TREE_OPERAND (exp, 0));
case SAVE_EXPR:
+ is_save_expr = 1;
exp_rtl = SAVE_EXPR_RTL (exp);
break;
*************** safe_from_p (x, exp)
*** 3931,3935 ****
/* 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));
case METHOD_CALL_EXPR:
--- 3987,3991 ----
/* The only operand we look at is operand 1. The rest aren't
part of the expression. */
! return safe_from_p_1 (x, TREE_OPERAND (exp, 1));
case METHOD_CALL_EXPR:
*************** safe_from_p (x, exp)
*** 3945,3949 ****
for (i = 0; i < nops; i++)
if (TREE_OPERAND (exp, i) != 0
! && ! safe_from_p (x, TREE_OPERAND (exp, i)))
return 0;
}
--- 4001,4005 ----
for (i = 0; i < nops; i++)
if (TREE_OPERAND (exp, i) != 0
! && ! safe_from_p_1 (x, TREE_OPERAND (exp, i)))
return 0;
}
*************** safe_from_p (x, exp)
*** 3969,3975 ****
--- 4025,4087 ----
/* If we reach here, it is safe. */
+ if (is_save_expr)
+ {
+ /* This SAVE_EXPR might appear many times in the top-level
+ safe_from_p() expression, and if it has a complex
+ subexpression, examining it multiple times could result
+ in a combinatorial explosion. E.g. on an Alpha Cabriolet
+ 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, and the complicated line causing
+ so much time to be spent in the earlier version of safe_from_p()
+ had only 293 or so unique nodes.
+
+ So, turn this SAVE_EXPR into an ERROR_MARK for now, but remember
+ where it is so we can turn it back in the top-level safe_from_p()
+ when we're done. */
+
+ if (safe_from_p_count > safe_from_p_size)
+ return 0; /* For now, don't bother re-sizing the array. */
+ safe_from_p_rewritten[safe_from_p_count++] = exp;
+ TREE_SET_CODE (exp, ERROR_MARK);
+ }
+
return 1;
}
+ /* Subroutine of expand_expr: return nonzero iff there is no way that
+ EXP can reference X, which is being modified. */
+
+ static int
+ safe_from_p (x, exp)
+ rtx x;
+ tree exp;
+ {
+ int rtn;
+ int i;
+ tree trees[128];
+
+ safe_from_p_count = 0;
+ safe_from_p_size = sizeof (trees) / sizeof (trees[0]);
+ safe_from_p_rewritten = &trees[0];
+
+ rtn = safe_from_p_1 (x, exp);
+
+ #if 0
+ if (safe_from_p_count != 0)
+ fprintf (stderr, "%s:%d: safe_from_p_count = %d\n",
+ input_filename, lineno, safe_from_p_count);
+ #endif
+
+ for (i = 0; i < safe_from_p_count; ++i)
+ {
+ if (TREE_CODE (trees [i]) != ERROR_MARK)
+ abort ();
+ TREE_SET_CODE (trees[i], SAVE_EXPR);
+ }
+
+ return rtn;
+ }
+
/* Subroutine of expand_expr: return nonzero iff EXP is an
expression whose type is statically determinable. */
*************** expand_expr (exp, target, tmode, modifie
*** 4534,4537 ****
--- 4646,4658 ----
}
}
+
+ if (TREE_READONLY (exp))
+ {
+ if (GET_CODE (target) == MEM)
+ target = change_address (target, GET_MODE (target),
+ XEXP (target, 0));
+ RTX_UNCHANGING_P (target) = 1;
+ }
+
store_constructor (exp, target);
return target;
*************** expand_expr (exp, target, tmode, modifie
*** 4543,4567 ****
tree exp2;
! /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated
! for *PTR += ANYTHING where PTR is put inside the SAVE_EXPR.
! This code has the same general effect as simply doing
! expand_expr on the save expr, except that the expression PTR
! is computed for use as a memory address. This means different
! code, suitable for indexing, may be generated. */
! if (TREE_CODE (exp1) == SAVE_EXPR
! && SAVE_EXPR_RTL (exp1) == 0
! && TYPE_MODE (TREE_TYPE (exp1)) == ptr_mode)
! {
! temp = expand_expr (TREE_OPERAND (exp1, 0), NULL_RTX,
! VOIDmode, EXPAND_SUM);
! op0 = memory_address (mode, temp);
! op0 = copy_all_regs (op0);
! SAVE_EXPR_RTL (exp1) = op0;
! }
! else
! {
! op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
! op0 = memory_address (mode, op0);
! }
temp = gen_rtx (MEM, mode, op0);
--- 4664,4669 ----
tree exp2;
! op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
! op0 = memory_address (mode, op0);
temp = gen_rtx (MEM, mode, op0);
*************** expand_expr (exp, target, tmode, modifie
*** 4770,4776 ****
tree offset;
int volatilep = 0;
- tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
- &mode1, &unsignedp, &volatilep);
int alignment;
/* If we got back the original object, something is wrong. Perhaps
--- 4872,4879 ----
tree offset;
int volatilep = 0;
int alignment;
+ tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
+ &mode1, &unsignedp, &volatilep,
+ &alignment);
/* If we got back the original object, something is wrong. Perhaps
*************** expand_expr (exp, target, tmode, modifie
*** 4793,4797 ****
!= INTEGER_CST)
? target : NULL_RTX),
! VOIDmode, EXPAND_SUM);
/* If this is a constant, put it into a register if it is a
--- 4896,4901 ----
!= INTEGER_CST)
? target : NULL_RTX),
! VOIDmode,
! modifier == EXPAND_INITIALIZER ? modifier : 0);
/* If this is a constant, put it into a register if it is a
*************** expand_expr (exp, target, tmode, modifie
*** 4806,4810 ****
}
- alignment = TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT;
if (offset != 0)
{
--- 4910,4913 ----
*************** expand_expr (exp, target, tmode, modifie
*** 4816,4827 ****
gen_rtx (PLUS, ptr_mode, XEXP (op0, 0),
force_reg (ptr_mode, offset_rtx)));
- /* If we have a variable offset, the known alignment
- is only that of the innermost structure containing the field.
- (Actually, we could sometimes do better by using the
- size of an element of the innermost array, but no need.) */
- if (TREE_CODE (exp) == COMPONENT_REF
- || TREE_CODE (exp) == BIT_FIELD_REF)
- alignment = (TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (exp, 0)))
- / BITS_PER_UNIT);
}
--- 4919,4922 ----
*************** expand_expr (exp, target, tmode, modifie
*** 4844,4848 ****
&& modifier != EXPAND_SUM
&& modifier != EXPAND_INITIALIZER
! && ((mode1 != BLKmode && ! direct_load[(int) mode1])
/* If the field isn't aligned enough to fetch as a memref,
fetch it as a bit field. */
--- 4939,4945 ----
&& modifier != EXPAND_SUM
&& modifier != EXPAND_INITIALIZER
! && ((mode1 != BLKmode && ! direct_load[(int) mode1]
! && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
! && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
/* If the field isn't aligned enough to fetch as a memref,
fetch it as a bit field. */
*************** expand_expr (exp, target, tmode, modifie
*** 4857,4861 ****
if (ext_mode == BLKmode)
! abort ();
op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos,
--- 4954,4982 ----
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 = change_address (op0, VOIDmode,
! plus_constant (XEXP (op0, 0),
! bitpos / BITS_PER_UNIT));
! if (target == 0)
! {
! target
! = assign_stack_temp (mode, int_size_in_bytes (type), 0);
! MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (type);
! }
!
! emit_block_move (target, op0,
! GEN_INT ((bitsize + BITS_PER_UNIT - 1)
! / BITS_PER_UNIT),
! 1);
!
! return target;
! }
op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos,
*************** expand_expr (exp, target, tmode, modifie
*** 4863,4866 ****
--- 4984,4999 ----
alignment,
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 < 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)
{
*************** expand_expr (exp, target, tmode, modifie
*** 4877,4880 ****
--- 5010,5018 ----
}
+ /* 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
*************** expand_expr (exp, target, tmode, modifie
*** 4888,4895 ****
MEM_IN_STRUCT_P (op0) = 1;
MEM_VOLATILE_P (op0) |= volatilep;
! if (mode == mode1 || mode1 == BLKmode || mode1 == tmode)
return op0;
! if (target == 0)
target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
convert_move (target, op0, unsignedp);
return target;
--- 5026,5036 ----
MEM_IN_STRUCT_P (op0) = 1;
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;
*************** expand_builtin (exp, target, subtarget,
*** 7986,7989 ****
--- 8127,8365 ----
#endif
+ /* __builtin_setjmp is passed a pointer to an array of five words
+ (not all will be used on all machines). It operates similarly to
+ the C library function of the same name, but is more efficient.
+ Much of the code below (and for longjmp) is copied from the handling
+ of non-local gotos.
+
+ NOTE: This is intended for use by GNAT and will only work in
+ the method used by it. This code will likely NOT survive to
+ the GCC 2.8.0 release. */
+ case BUILT_IN_SETJMP:
+ if (arglist == 0
+ || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
+ break;
+
+ {
+ rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
+ VOIDmode, 0);
+ rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
+ enum machine_mode sa_mode = Pmode;
+ rtx stack_save;
+ int old_inhibit_defer_pop = inhibit_defer_pop;
+ int return_pops = RETURN_POPS_ARGS (get_identifier ("__dummy"),
+ get_identifier ("__dummy"), 0);
+ rtx next_arg_reg;
+ CUMULATIVE_ARGS args_so_far;
+ int current_call_is_indirect = 1;
+ int i;
+
+ #ifdef POINTERS_EXTEND_UNSIGNED
+ buf_addr = convert_memory_address (Pmode, buf_addr);
+ #endif
+
+ buf_addr = force_reg (Pmode, buf_addr);
+
+ if (target == 0 || GET_CODE (target) != REG
+ || REGNO (target) < FIRST_PSEUDO_REGISTER)
+ target = gen_reg_rtx (value_mode);
+
+ emit_queue ();
+
+ CONST_CALL_P (emit_note (NULL_PTR, NOTE_INSN_SETJMP)) = 1;
+ current_function_calls_setjmp = 1;
+
+ /* We store the frame pointer and the address of lab1 in the buffer
+ and use the rest of it for the stack save area, which is
+ machine-dependent. */
+ emit_move_insn (gen_rtx (MEM, Pmode, buf_addr),
+ virtual_stack_vars_rtx);
+ emit_move_insn
+ (validize_mem (gen_rtx (MEM, Pmode,
+ plus_constant (buf_addr,
+ GET_MODE_SIZE (Pmode)))),
+ gen_rtx (LABEL_REF, Pmode, lab1));
+
+ #ifdef HAVE_save_stack_nonlocal
+ if (HAVE_save_stack_nonlocal)
+ sa_mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0];
+ #endif
+
+ current_function_has_nonlocal_goto = 1;
+
+ stack_save = gen_rtx (MEM, sa_mode,
+ plus_constant (buf_addr,
+ 2 * GET_MODE_SIZE (Pmode)));
+ emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
+
+ #ifdef HAVE_setjmp
+ if (HAVE_setjmp)
+ emit_insn (gen_setjmp ());
+ #endif
+
+ /* Set TARGET to zero and branch around the other case. */
+ emit_move_insn (target, const0_rtx);
+ emit_jump_insn (gen_jump (lab2));
+ emit_barrier ();
+ emit_label (lab1);
+
+ /* Note that setjmp clobbers FP when we get here, so we have to
+ make sure it's marked as used by this function. */
+ emit_insn (gen_rtx (USE, VOIDmode, hard_frame_pointer_rtx));
+
+ /* Mark the static chain as clobbered here so life information
+ doesn't get messed up for it. */
+ emit_insn (gen_rtx (CLOBBER, VOIDmode, static_chain_rtx));
+
+ /* Now put in the code to restore the frame pointer, and argument
+ pointer, if needed. The code below is from expand_end_bindings
+ in stmt.c; see detailed documentation there. */
+ #ifdef HAVE_nonlocal_goto
+ if (! HAVE_nonlocal_goto)
+ #endif
+ emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
+
+ #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ if (fixed_regs[ARG_POINTER_REGNUM])
+ {
+ #ifdef ELIMINABLE_REGS
+ static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
+
+ for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
+ if (elim_regs[i].from == ARG_POINTER_REGNUM
+ && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
+ break;
+
+ if (i == sizeof elim_regs / sizeof elim_regs [0])
+ #endif
+ {
+ /* Now restore our arg pointer from the address at which it
+ was saved in our stack frame.
+ If there hasn't be space allocated for it yet, make
+ some now. */
+ if (arg_pointer_save_area == 0)
+ arg_pointer_save_area
+ = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
+ emit_move_insn (virtual_incoming_args_rtx,
+ copy_to_reg (arg_pointer_save_area));
+ }
+ }
+ #endif
+
+ #ifdef HAVE_nonlocal_goto_receiver
+ if (HAVE_nonlocal_goto_receiver)
+ emit_insn (gen_nonlocal_goto_receiver ());
+ #endif
+ /* The static chain pointer contains the address of dummy function.
+ We need to call it here to handle some PIC cases of restoring
+ a global pointer. Then return 1. */
+ op0 = copy_to_mode_reg (Pmode, static_chain_rtx);
+
+ /* We can't actually call emit_library_call here, so do everything
+ it does, which isn't much for a libfunc with no args. */
+ op0 = memory_address (FUNCTION_MODE, op0);
+
+ INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE,
+ gen_rtx (SYMBOL_REF, Pmode, "__dummy"));
+ next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
+
+ #ifndef ACCUMULATE_OUTGOING_ARGS
+ #ifdef HAVE_call_pop
+ if (HAVE_call_pop)
+ emit_call_insn (gen_call_pop (gen_rtx (MEM, FUNCTION_MODE, op0),
+ const0_rtx, next_arg_reg,
+ GEN_INT (return_pops)));
+ else
+ #endif
+ #endif
+
+ #ifdef HAVE_call
+ if (HAVE_call)
+ emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, op0),
+ const0_rtx, next_arg_reg, const0_rtx));
+ else
+ #endif
+ abort ();
+
+ emit_move_insn (target, const1_rtx);
+ emit_label (lab2);
+ return target;
+ }
+
+ /* __builtin_longjmp is passed a pointer to an array of five words
+ and a value, which is a dummy. It's similar to the C library longjmp
+ function but works with __builtin_setjmp above. */
+ case BUILT_IN_LONGJMP:
+ if (arglist == 0 || TREE_CHAIN (arglist) == 0
+ || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
+ break;
+
+ {
+ tree dummy_id = get_identifier ("__dummy");
+ tree dummy_type = build_function_type (void_type_node, NULL_TREE);
+ tree dummy_decl = build_decl (FUNCTION_DECL, dummy_id, dummy_type);
+ #ifdef POINTERS_EXTEND_UNSIGNED
+ rtx buf_addr
+ = force_reg (Pmode,
+ convert_memory_address
+ (Pmode,
+ expand_expr (TREE_VALUE (arglist),
+ NULL_RTX, VOIDmode, 0)));
+ #else
+ rtx buf_addr
+ = force_reg (Pmode, expand_expr (TREE_VALUE (arglist),
+ NULL_RTX,
+ VOIDmode, 0));
+ #endif
+ rtx fp = gen_rtx (MEM, Pmode, buf_addr);
+ rtx lab = gen_rtx (MEM, Pmode,
+ plus_constant (buf_addr, GET_MODE_SIZE (Pmode)));
+ enum machine_mode sa_mode
+ #ifdef HAVE_save_stack_nonlocal
+ = (HAVE_save_stack_nonlocal
+ ? insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0]
+ : Pmode);
+ #else
+ = Pmode;
+ #endif
+ rtx stack = gen_rtx (MEM, sa_mode,
+ plus_constant (buf_addr,
+ 2 * GET_MODE_SIZE (Pmode)));
+
+ DECL_EXTERNAL (dummy_decl) = 1;
+ TREE_PUBLIC (dummy_decl) = 1;
+ make_decl_rtl (dummy_decl, NULL_PTR, 1);
+
+ /* Expand the second expression just for side-effects. */
+ expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
+ const0_rtx, VOIDmode, 0);
+
+ assemble_external (dummy_decl);
+
+ /* Pick up FP, label, and SP from the block and jump. This code is
+ from expand_goto in stmt.c; see there for detailed comments. */
+ #if HAVE_nonlocal_goto
+ if (HAVE_nonlocal_goto)
+ emit_insn (gen_nonlocal_goto (fp, lab, stack,
+ XEXP (DECL_RTL (dummy_decl), 0)));
+ else
+ #endif
+ {
+ lab = copy_to_reg (lab);
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+ emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+
+ /* Put in the static chain register the address of the dummy
+ function. */
+ emit_move_insn (static_chain_rtx, XEXP (DECL_RTL (dummy_decl), 0));
+ emit_insn (gen_rtx (USE, VOIDmode, hard_frame_pointer_rtx));
+ emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
+ emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
+ emit_indirect_jump (lab);
+ }
+
+ return const0_rtx;
+ }
+
default: /* just do library call, if unknown builtin */
error ("built-in function `%s' not currently supported",
*************** preexpand_calls (exp)
*** 8688,8701 ****
case CALL_EXPR:
/* Do nothing if already expanded. */
! if (CALL_EXPR_RTL (exp) != 0)
return;
! /* Do nothing to built-in functions. */
! 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))
! /* Do nothing if the call returns a variable-sized object. */
! || TREE_CODE (TYPE_SIZE (TREE_TYPE(exp))) != INTEGER_CST)
! CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0);
return;
--- 9064,9078 ----
case CALL_EXPR:
/* Do nothing if already expanded. */
! if (CALL_EXPR_RTL (exp) != 0
! /* Do nothing if the call returns a variable-sized object. */
! || TREE_CODE (TYPE_SIZE (TREE_TYPE(exp))) != INTEGER_CST
! /* Do nothing to built-in functions. */
! || (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))))
return;
! CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0);
return;
*************** do_jump (exp, if_false_label, if_true_la
*** 9087,9090 ****
--- 9464,9468 ----
push_temp_slots ();
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
+ preserve_temp_slots (NULL_RTX);
free_temp_slots ();
pop_temp_slots ();
*************** do_jump (exp, if_false_label, if_true_la
*** 9103,9111 ****
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 = type_for_size (bitsize, unsignedp);
--- 9481,9491 ----
tree offset;
int volatilep = 0;
+ int alignment;
/* 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,
! &alignment);
type = type_for_size (bitsize, unsignedp);
diff -rcp2N gcc-2.7.2.2/final.c g77-new/final.c
*** gcc-2.7.2.2/final.c Sun Nov 26 13:50:00 1995
--- g77-new/final.c Thu Jul 10 20:11:16 1997
*************** profile_function (file)
*** 983,991 ****
text_section ();
! #ifdef STRUCT_VALUE_INCOMING_REGNUM
if (sval)
ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);
#else
! #ifdef STRUCT_VALUE_REGNUM
if (sval)
ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);
--- 983,991 ----
text_section ();
! #if defined(STRUCT_VALUE_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (sval)
ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);
#else
! #if defined(STRUCT_VALUE_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (sval)
ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);
*************** profile_function (file)
*** 993,1027 ****
#endif
! #if 0
! #ifdef STATIC_CHAIN_INCOMING_REGNUM
if (cxt)
ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
#else
! #ifdef STATIC_CHAIN_REGNUM
if (cxt)
ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
#endif
#endif
- #endif /* 0 */
FUNCTION_PROFILER (file, profile_label_no);
! #if 0
! #ifdef STATIC_CHAIN_INCOMING_REGNUM
if (cxt)
ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
#else
! #ifdef STATIC_CHAIN_REGNUM
if (cxt)
ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
#endif
#endif
- #endif /* 0 */
! #ifdef STRUCT_VALUE_INCOMING_REGNUM
if (sval)
ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);
#else
! #ifdef STRUCT_VALUE_REGNUM
if (sval)
ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);
--- 993,1023 ----
#endif
! #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
#else
! #if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
#endif
#endif
FUNCTION_PROFILER (file, profile_label_no);
! #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
#else
! #if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
#endif
#endif
! #if defined(STRUCT_VALUE_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (sval)
ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);
#else
! #if defined(STRUCT_VALUE_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (sval)
ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);
diff -rcp2N gcc-2.7.2.2/flags.h g77-new/flags.h
*** gcc-2.7.2.2/flags.h Thu Jun 15 07:34:11 1995
--- g77-new/flags.h Thu Jul 10 20:08:56 1997
*************** extern int flag_unroll_loops;
*** 204,207 ****
--- 204,221 ----
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 forces all general induction variables in loops to be
+ strength reduced. */
+
+ extern int flag_reduce_all_givs;
+
+ /* Nonzero gets another run of loop_optimize performed. */
+
+ extern int flag_rerun_loop_opt;
+
/* Nonzero for -fcse-follow-jumps:
have cse follow jumps to do a more extensive job. */
*************** extern int flag_gnu_linker;
*** 339,342 ****
--- 353,369 ----
/* Tag all structures with __attribute__(packed) */
extern int flag_pack_struct;
+
+ /* 1 if alias checking is enabled: symbols do not alias each other
+ and parameters do not alias the current stack frame. */
+ extern int flag_alias_check;
+
+ /* 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;
/* Other basic status info about current function. */
diff -rcp2N gcc-2.7.2.2/flow.c g77-new/flow.c
*** gcc-2.7.2.2/flow.c Mon Aug 28 06:23:34 1995
--- g77-new/flow.c Sun Aug 10 18:46:11 1997
*************** static HARD_REG_SET elim_reg_set;
*** 288,292 ****
/* Forward declarations */
static void find_basic_blocks PROTO((rtx, rtx));
! static int uses_reg_or_mem PROTO((rtx));
static void mark_label_ref PROTO((rtx, rtx, int));
static void life_analysis PROTO((rtx, int));
--- 288,292 ----
/* Forward declarations */
static void find_basic_blocks PROTO((rtx, rtx));
! static int jmp_uses_reg_or_mem PROTO((rtx));
static void mark_label_ref PROTO((rtx, rtx, int));
static void life_analysis PROTO((rtx, int));
*************** find_basic_blocks (f, nonlocal_label_lis
*** 554,563 ****
if (GET_CODE (XVECEXP (pat, 0, i)) == SET
&& SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
! && uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
computed_jump = 1;
}
else if (GET_CODE (pat) == SET
&& SET_DEST (pat) == pc_rtx
! && uses_reg_or_mem (SET_SRC (pat)))
computed_jump = 1;
--- 554,563 ----
if (GET_CODE (XVECEXP (pat, 0, i)) == SET
&& SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
! && jmp_uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
computed_jump = 1;
}
else if (GET_CODE (pat) == SET
&& SET_DEST (pat) == pc_rtx
! && jmp_uses_reg_or_mem (SET_SRC (pat)))
computed_jump = 1;
*************** find_basic_blocks (f, nonlocal_label_lis
*** 760,767 ****
/* Subroutines of find_basic_blocks. */
! /* Return 1 if X contain a REG or MEM that is not in the constant pool. */
static int
! uses_reg_or_mem (x)
rtx x;
{
--- 760,768 ----
/* Subroutines of find_basic_blocks. */
! /* Return 1 if X, the SRC_SRC of SET of (pc) contain a REG or MEM that is
! not in the constant pool and not in the condition of an IF_THEN_ELSE. */
static int
! jmp_uses_reg_or_mem (x)
rtx x;
{
*************** uses_reg_or_mem (x)
*** 770,778 ****
char *fmt;
! if (code == REG
! || (code == MEM
! && ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
! && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))))
! return 1;
fmt = GET_RTX_FORMAT (code);
--- 771,796 ----
char *fmt;
! switch (code)
! {
! case CONST:
! case LABEL_REF:
! case PC:
! return 0;
!
! case REG:
! return 1;
!
! case MEM:
! return ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
! && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)));
!
! case IF_THEN_ELSE:
! return (jmp_uses_reg_or_mem (XEXP (x, 1))
! || jmp_uses_reg_or_mem (XEXP (x, 2)));
!
! case PLUS: case MINUS: case MULT:
! return (jmp_uses_reg_or_mem (XEXP (x, 0))
! || jmp_uses_reg_or_mem (XEXP (x, 1)));
! }
fmt = GET_RTX_FORMAT (code);
*************** uses_reg_or_mem (x)
*** 780,789 ****
{
if (fmt[i] == 'e'
! && uses_reg_or_mem (XEXP (x, i)))
return 1;
if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
! if (uses_reg_or_mem (XVECEXP (x, i, j)))
return 1;
}
--- 798,807 ----
{
if (fmt[i] == 'e'
! && jmp_uses_reg_or_mem (XEXP (x, i)))
return 1;
if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
! if (jmp_uses_reg_or_mem (XVECEXP (x, i, j)))
return 1;
}
*************** propagate_block (old, first, last, final
*** 1605,1614 ****
/* Each call clobbers all call-clobbered regs that are not
! global. Note that the function-value reg is a
call-clobbered reg, and mark_set_regs has already had
a chance to handle it. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! if (call_used_regs[i] && ! global_regs[i])
dead[i / REGSET_ELT_BITS]
|= ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS));
--- 1623,1633 ----
/* Each call clobbers all call-clobbered regs that are not
! global or fixed. Note that the function-value reg is a
call-clobbered reg, and mark_set_regs has already had
a chance to handle it. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! if (call_used_regs[i] && ! global_regs[i]
! && ! fixed_regs[i])
dead[i / REGSET_ELT_BITS]
|= ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS));
diff -rcp2N gcc-2.7.2.2/fold-const.c g77-new/fold-const.c
*** gcc-2.7.2.2/fold-const.c Fri Sep 15 18:26:12 1995
--- g77-new/fold-const.c Sun Aug 10 18:47:18 1997
*************** static tree unextend PROTO((tree, int, i
*** 80,83 ****
--- 80,84 ----
static tree fold_truthop PROTO((enum tree_code, tree, tree, tree));
static tree strip_compound_expr PROTO((tree, tree));
+ static int multiple_of_p PROTO((tree, tree, tree));
#ifndef BRANCH_COST
*************** const_binop (code, arg1, arg2, notrunc)
*** 1077,1080 ****
--- 1078,1083 ----
if (int2h == 0 && int2l > 0
&& TREE_TYPE (arg1) == sizetype
+ && ! TREE_CONSTANT_OVERFLOW (arg1)
+ && ! TREE_CONSTANT_OVERFLOW (arg2)
&& int1h == 0 && int1l >= 0)
{
*************** const_binop (code, arg1, arg2, notrunc)
*** 1230,1233 ****
--- 1233,1237 ----
if (TREE_CODE (arg1) == COMPLEX_CST)
{
+ register tree type = TREE_TYPE (arg1);
register tree r1 = TREE_REALPART (arg1);
register tree i1 = TREE_IMAGPART (arg1);
*************** const_binop (code, arg1, arg2, notrunc)
*** 1239,1253 ****
{
case PLUS_EXPR:
! t = build_complex (const_binop (PLUS_EXPR, r1, r2, notrunc),
const_binop (PLUS_EXPR, i1, i2, notrunc));
break;
case MINUS_EXPR:
! t = build_complex (const_binop (MINUS_EXPR, r1, r2, notrunc),
const_binop (MINUS_EXPR, i1, i2, notrunc));
break;
case MULT_EXPR:
! t = build_complex (const_binop (MINUS_EXPR,
const_binop (MULT_EXPR,
r1, r2, notrunc),
--- 1243,1260 ----
{
case PLUS_EXPR:
! t = build_complex (type,
! const_binop (PLUS_EXPR, r1, r2, notrunc),
const_binop (PLUS_EXPR, i1, i2, notrunc));
break;
case MINUS_EXPR:
! t = build_complex (type,
! const_binop (MINUS_EXPR, r1, r2, notrunc),
const_binop (MINUS_EXPR, i1, i2, notrunc));
break;
case MULT_EXPR:
! t = build_complex (type,
! const_binop (MINUS_EXPR,
const_binop (MULT_EXPR,
r1, r2, notrunc),
*************** const_binop (code, arg1, arg2, notrunc)
*** 1271,1293 ****
notrunc);
! t = build_complex
! (const_binop (INTEGRAL_TYPE_P (TREE_TYPE (r1))
! ? TRUNC_DIV_EXPR : RDIV_EXPR,
! const_binop (PLUS_EXPR,
! const_binop (MULT_EXPR, r1, r2,
! notrunc),
! const_binop (MULT_EXPR, i1, i2,
! notrunc),
! notrunc),
! magsquared, notrunc),
! const_binop (INTEGRAL_TYPE_P (TREE_TYPE (r1))
! ? TRUNC_DIV_EXPR : RDIV_EXPR,
! const_binop (MINUS_EXPR,
! const_binop (MULT_EXPR, i1, r2,
! notrunc),
! const_binop (MULT_EXPR, r1, i2,
! notrunc),
! notrunc),
! magsquared, notrunc));
}
break;
--- 1278,1302 ----
notrunc);
! t = build_complex (type,
! const_binop
! (INTEGRAL_TYPE_P (TREE_TYPE (r1))
! ? TRUNC_DIV_EXPR : RDIV_EXPR,
! const_binop (PLUS_EXPR,
! const_binop (MULT_EXPR, r1, r2,
! notrunc),
! const_binop (MULT_EXPR, i1, i2,
! notrunc),
! notrunc),
! magsquared, notrunc),
! const_binop
! (INTEGRAL_TYPE_P (TREE_TYPE (r1))
! ? TRUNC_DIV_EXPR : RDIV_EXPR,
! const_binop (MINUS_EXPR,
! const_binop (MULT_EXPR, i1, r2,
! notrunc),
! const_binop (MULT_EXPR, r1, i2,
! notrunc),
! notrunc),
! magsquared, notrunc));
}
break;
*************** const_binop (code, arg1, arg2, notrunc)
*** 1296,1300 ****
abort ();
}
- TREE_TYPE (t) = TREE_TYPE (arg1);
return t;
}
--- 1305,1308 ----
*************** size_binop (code, arg0, arg1)
*** 1346,1363 ****
{
/* And some specific cases even faster than that. */
! if (code == PLUS_EXPR
! && TREE_INT_CST_LOW (arg0) == 0
! && TREE_INT_CST_HIGH (arg0) == 0)
return arg1;
! if (code == MINUS_EXPR
! && TREE_INT_CST_LOW (arg1) == 0
! && TREE_INT_CST_HIGH (arg1) == 0)
return arg0;
! if (code == MULT_EXPR
! && TREE_INT_CST_LOW (arg0) == 1
! && TREE_INT_CST_HIGH (arg0) == 0)
return arg1;
/* Handle general case of two integer constants. */
! return const_binop (code, arg0, arg1, 0);
}
--- 1354,1367 ----
{
/* And some specific cases even faster than that. */
! if (code == PLUS_EXPR && integer_zerop (arg0))
return arg1;
! else if ((code == MINUS_EXPR || code == PLUS_EXPR)
! && integer_zerop (arg1))
return arg0;
! else if (code == MULT_EXPR && integer_onep (arg0))
return arg1;
+
/* Handle general case of two integer constants. */
! return const_binop (code, arg0, arg1, 1);
}
*************** fold_convert (t, arg1)
*** 1482,1486 ****
{
if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
! return arg1;
else if (setjmp (float_error))
{
--- 1486,1494 ----
{
if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
! {
! t = arg1;
! TREE_TYPE (arg1) = type;
! return t;
! }
else if (setjmp (float_error))
{
*************** operand_equal_p (arg0, arg1, only_const)
*** 1644,1687 ****
STRIP_NOPS (arg1);
! /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal.
! We don't care about side effects in that case because the SAVE_EXPR
! takes care of that for us. */
! if (TREE_CODE (arg0) == SAVE_EXPR && arg0 == arg1)
! return ! only_const;
!
! if (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1))
return 0;
! if (TREE_CODE (arg0) == TREE_CODE (arg1)
! && TREE_CODE (arg0) == ADDR_EXPR
! && TREE_OPERAND (arg0, 0) == TREE_OPERAND (arg1, 0))
! return 1;
!
! if (TREE_CODE (arg0) == TREE_CODE (arg1)
! && TREE_CODE (arg0) == INTEGER_CST
! && TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1)
! && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1))
return 1;
! /* Detect when real constants are equal. */
! if (TREE_CODE (arg0) == TREE_CODE (arg1)
! && TREE_CODE (arg0) == REAL_CST)
! return !bcmp ((char *) &TREE_REAL_CST (arg0),
! (char *) &TREE_REAL_CST (arg1),
! sizeof (REAL_VALUE_TYPE));
if (only_const)
return 0;
- if (arg0 == arg1)
- return 1;
-
- if (TREE_CODE (arg0) != TREE_CODE (arg1))
- return 0;
- /* This is needed for conversions and for COMPONENT_REF.
- Might as well play it safe and always test this. */
- if (TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1)))
- return 0;
-
switch (TREE_CODE_CLASS (TREE_CODE (arg0)))
{
--- 1652,1705 ----
STRIP_NOPS (arg1);
! if (TREE_CODE (arg0) != TREE_CODE (arg1)
! /* This is needed for conversions and for COMPONENT_REF.
! Might as well play it safe and always test this. */
! || TYPE_MODE (TREE_TYPE (arg0)) != TYPE_MODE (TREE_TYPE (arg1)))
return 0;
! /* If ARG0 and ARG1 are the same SAVE_EXPR, they are necessarily equal.
! We don't care about side effects in that case because the SAVE_EXPR
! takes care of that for us. In all other cases, two expressions are
! equal if they have no side effects. If we have two identical
! expressions with side effects that should be treated the same due
! to the only side effects being identical SAVE_EXPR's, that will
! be detected in the recursive calls below. */
! if (arg0 == arg1 && ! only_const
! && (TREE_CODE (arg0) == SAVE_EXPR
! || (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
return 1;
! /* Next handle constant cases, those for which we can return 1 even
! if ONLY_CONST is set. */
! if (TREE_CONSTANT (arg0) && TREE_CONSTANT (arg1))
! switch (TREE_CODE (arg0))
! {
! case INTEGER_CST:
! return (TREE_INT_CST_LOW (arg0) == TREE_INT_CST_LOW (arg1)
! && TREE_INT_CST_HIGH (arg0) == TREE_INT_CST_HIGH (arg1));
!
! case REAL_CST:
! return REAL_VALUES_EQUAL (TREE_REAL_CST (arg0), TREE_REAL_CST (arg1));
!
! case COMPLEX_CST:
! return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1),
! only_const)
! && operand_equal_p (TREE_IMAGPART (arg0), TREE_IMAGPART (arg1),
! only_const));
!
! case STRING_CST:
! return (TREE_STRING_LENGTH (arg0) == TREE_STRING_LENGTH (arg1)
! && ! strncmp (TREE_STRING_POINTER (arg0),
! TREE_STRING_POINTER (arg1),
! TREE_STRING_LENGTH (arg0)));
!
! case ADDR_EXPR:
! return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
! 0);
! }
if (only_const)
return 0;
switch (TREE_CODE_CLASS (TREE_CODE (arg0)))
{
*************** operand_equal_p (arg0, arg1, only_const)
*** 1698,1705 ****
case '<':
case '2':
! return (operand_equal_p (TREE_OPERAND (arg0, 0),
! TREE_OPERAND (arg1, 0), 0)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
! TREE_OPERAND (arg1, 1), 0));
case 'r':
--- 1716,1735 ----
case '<':
case '2':
! if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0)
! && operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1),
! 0))
! return 1;
!
! /* For commutative ops, allow the other order. */
! return ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MULT_EXPR
! || TREE_CODE (arg0) == MIN_EXPR || TREE_CODE (arg0) == MAX_EXPR
! || TREE_CODE (arg0) == BIT_IOR_EXPR
! || TREE_CODE (arg0) == BIT_XOR_EXPR
! || TREE_CODE (arg0) == BIT_AND_EXPR
! || TREE_CODE (arg0) == NE_EXPR || TREE_CODE (arg0) == EQ_EXPR)
! && operand_equal_p (TREE_OPERAND (arg0, 0),
! TREE_OPERAND (arg1, 1), 0)
&& operand_equal_p (TREE_OPERAND (arg0, 1),
! TREE_OPERAND (arg1, 0), 0));
case 'r':
*************** optimize_bit_field_compare (code, compar
*** 2212,2215 ****
--- 2242,2246 ----
int lunsignedp, runsignedp;
int lvolatilep = 0, rvolatilep = 0;
+ int alignment;
tree linner, rinner;
tree mask;
*************** optimize_bit_field_compare (code, compar
*** 2220,2224 ****
extraction at all and so can do nothing. */
linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
! &lunsignedp, &lvolatilep);
if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
|| offset != 0)
--- 2251,2255 ----
extraction at all and so can do nothing. */
linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
! &lunsignedp, &lvolatilep, &alignment);
if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
|| offset != 0)
*************** optimize_bit_field_compare (code, compar
*** 2229,2234 ****
/* If this is not a constant, we can only do something if bit positions,
sizes, and signedness are the same. */
! rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset,
! &rmode, &runsignedp, &rvolatilep);
if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
--- 2260,2265 ----
/* If this is not a constant, we can only do something if bit positions,
sizes, and signedness are the same. */
! rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
! &runsignedp, &rvolatilep, &alignment);
if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
*************** decode_field_reference (exp, pbitsize, p
*** 2403,2406 ****
--- 2434,2438 ----
tree unsigned_type;
int precision;
+ int alignment;
/* All the optimizations using this function assume integer fields.
*************** decode_field_reference (exp, pbitsize, p
*** 2423,2427 ****
inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
! punsignedp, pvolatilep);
if ((inner == exp && and_mask == 0)
|| *pbitsize < 0 || offset != 0)
--- 2455,2459 ----
inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
! punsignedp, pvolatilep, &alignment);
if ((inner == exp && and_mask == 0)
|| *pbitsize < 0 || offset != 0)
*************** strip_compound_expr (t, s)
*** 3065,3068 ****
--- 3097,3200 ----
}
+ /* Determine if first argument is a multiple of second argument.
+ Return 0 if it is not, or is not easily determined to so be.
+
+ An example of the sort of thing we care about (at this point --
+ this routine could surely be made more general, and expanded
+ to do what the *_DIV_EXPR's fold() cases do now) is discovering
+ that
+
+ SAVE_EXPR (I) * SAVE_EXPR (J * 8)
+
+ is a multiple of
+
+ SAVE_EXPR (J * 8)
+
+ when we know that the two `SAVE_EXPR (J * 8)' nodes are the
+ same node (which means they will have the same value at run
+ time, even though we don't know when they'll be assigned).
+
+ This code also handles discovering that
+
+ SAVE_EXPR (I) * SAVE_EXPR (J * 8)
+
+ is a multiple of
+
+ 8
+
+ (of course) so we don't have to worry about dealing with a
+ possible remainder.
+
+ Note that we _look_ inside a SAVE_EXPR only to determine
+ how it was calculated; it is not safe for fold() to do much
+ of anything else with the internals of a SAVE_EXPR, since
+ fold() cannot know when it will be evaluated at run time.
+ For example, the latter example above _cannot_ be implemented
+ as
+
+ SAVE_EXPR (I) * J
+
+ or any variant thereof, since the value of J at evaluation time
+ of the original SAVE_EXPR is not necessarily the same at the time
+ the new expression is evaluated. The only optimization of this
+ sort that would be valid is changing
+
+ SAVE_EXPR (I) * SAVE_EXPR (SAVE_EXPR (J) * 8)
+ divided by
+ 8
+
+ to
+
+ SAVE_EXPR (I) * SAVE_EXPR (J)
+
+ (where the same SAVE_EXPR (J) is used in the original and the
+ transformed version). */
+
+ static int
+ multiple_of_p (type, top, bottom)
+ tree type;
+ tree top;
+ tree bottom;
+ {
+ if (operand_equal_p (top, bottom, 0))
+ return 1;
+
+ if (TREE_CODE (type) != INTEGER_TYPE)
+ return 0;
+
+ switch (TREE_CODE (top))
+ {
+ case MULT_EXPR:
+ return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
+ || multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
+ && multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
+
+ case NOP_EXPR:
+ /* Punt if conversion from non-integral or wider integral type. */
+ if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE)
+ || (TYPE_PRECISION (type)
+ < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (top, 0)))))
+ return 0;
+ /* Fall through. */
+ case SAVE_EXPR:
+ return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
+
+ case INTEGER_CST:
+ if ((TREE_CODE (bottom) != INTEGER_CST)
+ || (tree_int_cst_sgn (top) < 0)
+ || (tree_int_cst_sgn (bottom) < 0))
+ return 0;
+ return integer_zerop (const_binop (TRUNC_MOD_EXPR,
+ top, bottom, 0));
+
+ default:
+ return 0;
+ }
+ }
+
/* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc.,
*************** fold (expr)
*** 3611,3615 ****
TREE_OPERAND (arg0, 1))));
else if (TREE_CODE (arg0) == COMPLEX_CST)
! return build_complex (TREE_OPERAND (arg0, 0),
fold (build1 (NEGATE_EXPR,
TREE_TYPE (TREE_TYPE (arg0)),
--- 3743,3747 ----
TREE_OPERAND (arg0, 1))));
else if (TREE_CODE (arg0) == COMPLEX_CST)
! return build_complex (type, TREE_OPERAND (arg0, 0),
fold (build1 (NEGATE_EXPR,
TREE_TYPE (TREE_TYPE (arg0)),
*************** fold (expr)
*** 4014,4018 ****
return non_lvalue (convert (type, arg0));
if (integer_zerop (arg1))
! return t;
/* If we have ((a / C1) / C2) where both division are the same type, try
--- 4146,4166 ----
return non_lvalue (convert (type, arg0));
if (integer_zerop (arg1))
! {
! if (extra_warnings)
! warning ("integer division by zero");
! return t;
! }
!
! /* If arg0 is a multiple of arg1, then rewrite to the fastest div
! operation, EXACT_DIV_EXPR. Otherwise, handle folding of
! general divide. Note that only CEIL_DIV_EXPR is rewritten now,
! only because the others seem to be faster in some cases, e.g. the
! nonoptimized TRUNC_DIV_EXPR or FLOOR_DIV_EXPR on DEC Alpha. This
! is probably just due to more work being done on it in expmed.c than
! on EXACT_DIV_EXPR, and could presumably be fixed, since
! EXACT_DIV_EXPR should _never_ be slower than *_DIV_EXPR. */
! if ((code == CEIL_DIV_EXPR)
! && multiple_of_p (type, arg0, arg1))
! return fold (build (EXACT_DIV_EXPR, type, arg0, arg1));
/* If we have ((a / C1) / C2) where both division are the same type, try
*************** fold (expr)
*** 4049,4053 ****
tree xarg0 = arg0;
! if (TREE_CODE (xarg0) == SAVE_EXPR)
have_save_expr = 1, xarg0 = TREE_OPERAND (xarg0, 0);
--- 4197,4201 ----
tree xarg0 = arg0;
! if (TREE_CODE (xarg0) == SAVE_EXPR && SAVE_EXPR_RTL (xarg0) == 0)
have_save_expr = 1, xarg0 = TREE_OPERAND (xarg0, 0);
*************** fold (expr)
*** 4067,4071 ****
}
! if (TREE_CODE (xarg0) == SAVE_EXPR)
have_save_expr = 1, xarg0 = TREE_OPERAND (xarg0, 0);
--- 4215,4219 ----
}
! if (TREE_CODE (xarg0) == SAVE_EXPR && SAVE_EXPR_RTL (xarg0) == 0)
have_save_expr = 1, xarg0 = TREE_OPERAND (xarg0, 0);
*************** fold (expr)
*** 5050,5054 ****
case COMPLEX_EXPR:
if (wins)
! return build_complex (arg0, arg1);
return t;
--- 5198,5202 ----
case COMPLEX_EXPR:
if (wins)
! return build_complex (type, arg0, arg1);
return t;
diff -rcp2N gcc-2.7.2.2/function.c g77-new/function.c
*** gcc-2.7.2.2/function.c Sun Nov 26 14:50:26 1995
--- g77-new/function.c Sun Aug 10 18:47:24 1997
*************** free_temps_for_rtl_expr (t)
*** 1184,1187 ****
--- 1184,1202 ----
}
+ /* Mark all temporaries ever allocated in this functon as not suitable
+ for reuse until the current level is exited. */
+
+ void
+ mark_all_temps_used ()
+ {
+ struct temp_slot *p;
+
+ for (p = temp_slots; p; p = p->next)
+ {
+ p->in_use = 1;
+ p->level = MIN (p->level, temp_slot_level);
+ }
+ }
+
/* Push deeper into the nesting level for stack temporaries. */
*************** pop_temp_slots ()
*** 1208,1211 ****
--- 1223,1237 ----
temp_slot_level--;
}
+
+ /* Initialize temporary slots. */
+
+ void
+ init_temp_slots ()
+ {
+ /* We have not allocated any temporaries yet. */
+ temp_slots = 0;
+ temp_slot_level = 0;
+ target_temp_slot_level = 0;
+ }
/* Retroactively move an auto variable from a register to a stack slot.
*************** instantiate_virtual_regs_1 (loc, object,
*** 2838,2842 ****
case MEM:
/* Most cases of MEM that convert to valid addresses have already been
! handled by our scan of regno_reg_rtx. The only special handling we
need here is to make a copy of the rtx to ensure it isn't being
shared if we have to change it to a pseudo.
--- 2864,2868 ----
case MEM:
/* Most cases of MEM that convert to valid addresses have already been
! handled by our scan of decls. The only special handling we
need here is to make a copy of the rtx to ensure it isn't being
shared if we have to change it to a pseudo.
*************** instantiate_virtual_regs_1 (loc, object,
*** 2896,2900 ****
has less restrictions on an address that some other insn.
In that case, we will modify the shared address. This case
! doesn't seem very likely, though. */
if (instantiate_virtual_regs_1 (&XEXP (x, 0),
--- 2922,2928 ----
has less restrictions on an address that some other insn.
In that case, we will modify the shared address. This case
! doesn't seem very likely, though. One case where this could
! happen is in the case of a USE or CLOBBER reference, but we
! take care of that below. */
if (instantiate_virtual_regs_1 (&XEXP (x, 0),
*************** instantiate_virtual_regs_1 (loc, object,
*** 2909,2914 ****
/* Fall through to generic unary operation case. */
- case USE:
- case CLOBBER:
case SUBREG:
case STRICT_LOW_PART:
--- 2937,2940 ----
*************** instantiate_virtual_regs_1 (loc, object,
*** 2927,2930 ****
--- 2953,2973 ----
goto restart;
+ case USE:
+ case CLOBBER:
+ /* If the operand is a MEM, see if the change is a valid MEM. If not,
+ go ahead and make the invalid one, but do it to a copy. For a REG,
+ just make the recursive call, since there's no chance of a problem. */
+
+ if ((GET_CODE (XEXP (x, 0)) == MEM
+ && instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 0), XEXP (x, 0),
+ 0))
+ || (GET_CODE (XEXP (x, 0)) == REG
+ && instantiate_virtual_regs_1 (&XEXP (x, 0), 0, 0)))
+ return 1;
+
+ XEXP (x, 0) = copy_rtx (XEXP (x, 0));
+ loc = &XEXP (x, 0);
+ goto restart;
+
case REG:
/* Try to replace with a PLUS. If that doesn't work, compute the sum
*************** assign_parms (fndecl, second_time)
*** 3404,3409 ****
/* If this is a memory ref that contains aggregate components,
! mark it as such for cse and loop optimize. */
MEM_IN_STRUCT_P (stack_parm) = aggregate;
}
--- 3447,3454 ----
/* If this is a memory ref that contains aggregate components,
! mark it as such for cse and loop optimize. Likewise if it
! is readonly. */
MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
}
*************** assign_parms (fndecl, second_time)
*** 3627,3631 ****
parmreg = gen_reg_rtx (promoted_nominal_mode);
! REG_USERVAR_P (parmreg) = 1;
/* If this was an item that we received a pointer to, set DECL_RTL
--- 3672,3676 ----
parmreg = gen_reg_rtx (promoted_nominal_mode);
! mark_user_reg (parmreg);
/* If this was an item that we received a pointer to, set DECL_RTL
*************** assign_parms (fndecl, second_time)
*** 3695,3699 ****
Pmode above. We must use the actual mode of the parm. */
parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
! REG_USERVAR_P (parmreg) = 1;
emit_move_insn (parmreg, DECL_RTL (parm));
DECL_RTL (parm) = parmreg;
--- 3740,3744 ----
Pmode above. We must use the actual mode of the parm. */
parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
! mark_user_reg (parmreg);
emit_move_insn (parmreg, DECL_RTL (parm));
DECL_RTL (parm) = parmreg;
*************** init_function_start (subr, filename, lin
*** 4814,4821 ****
rtl_expr_chain = 0;
! /* We have not allocated any temporaries yet. */
! temp_slots = 0;
! temp_slot_level = 0;
! target_temp_slot_level = 0;
/* Within function body, compute a type's size as soon it is laid out. */
--- 4859,4864 ----
rtl_expr_chain = 0;
! /* Set up to allocate temporaries. */
! init_temp_slots ();
/* Within function body, compute a type's size as soon it is laid out. */
diff -rcp2N gcc-2.7.2.2/gcc.c g77-new/gcc.c
*** gcc-2.7.2.2/gcc.c Tue Sep 12 17:15:11 1995
--- g77-new/gcc.c Sun Aug 10 18:47:14 1997
*************** static int is_directory PROTO((char *,
*** 296,300 ****
static void validate_switches PROTO((char *));
static void validate_all_switches PROTO((void));
! static void give_switch PROTO((int, int));
static int used_arg PROTO((char *, int));
static int default_arg PROTO((char *, int));
--- 296,300 ----
static void validate_switches PROTO((char *));
static void validate_all_switches PROTO((void));
! static void give_switch PROTO((int, int, int));
static int used_arg PROTO((char *, int));
static int default_arg PROTO((char *, int));
*************** or with constant text in a single argume
*** 405,408 ****
--- 405,409 ----
name starts with `o'. %{o*} would substitute this text,
including the space; thus, two arguments would be generated.
+ %{^S*} likewise, but don't put a blank between a switch and any args.
%{S*:X} substitutes X if one or more switches whose names start with -S are
specified to CC. Note that the tail part of the -S option
*************** process_command (argc, argv)
*** 2828,2831 ****
--- 2829,2835 ----
infiles[n_infiles++].name = argv[i];
}
+ /* -save-temps overrides -pipe, so that temp files are produced */
+ else if (save_temps_flag && strcmp (argv[i], "-pipe") == 0)
+ ;
else if (argv[i][0] == '-' && argv[i][1] != 0)
{
*************** handle_braces (p)
*** 3832,3835 ****
--- 3836,3844 ----
int negate = 0;
int suffix = 0;
+ int include_blanks = 1;
+
+ if (*p == '^')
+ /* A '^' after the open-brace means to not give blanks before args. */
+ include_blanks = 0, ++p;
if (*p == '|')
*************** handle_braces (p)
*** 3897,3901 ****
if (!strncmp (switches[i].part1, filter, p - filter)
&& check_live_switch (i, p - filter))
! give_switch (i, 0);
}
else
--- 3906,3910 ----
if (!strncmp (switches[i].part1, filter, p - filter)
&& check_live_switch (i, p - filter))
! give_switch (i, 0, include_blanks);
}
else
*************** handle_braces (p)
*** 3936,3940 ****
do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
/* Pass any arguments this switch has. */
! give_switch (i, 1);
}
--- 3945,3949 ----
do_spec_1 (string, 0, &switches[i].part1[hard_match_len]);
/* Pass any arguments this switch has. */
! give_switch (i, 1, 1);
}
*************** handle_braces (p)
*** 3980,3984 ****
if (*p == '}')
{
! give_switch (i, 0);
}
else
--- 3989,3993 ----
if (*p == '}')
{
! give_switch (i, 0, include_blanks);
}
else
*************** check_live_switch (switchnum, prefix_len
*** 4081,4090 ****
This cannot fail since it never finishes a command line.
! If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */
static void
! give_switch (switchnum, omit_first_word)
int switchnum;
int omit_first_word;
{
if (!omit_first_word)
--- 4090,4103 ----
This cannot fail since it never finishes a command line.
! If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument.
!
! If INCLUDE_BLANKS is nonzero, then we include blanks before each argument
! of the switch. */
static void
! give_switch (switchnum, omit_first_word, include_blanks)
int switchnum;
int omit_first_word;
+ int include_blanks;
{
if (!omit_first_word)
*************** give_switch (switchnum, omit_first_word)
*** 4093,4097 ****
do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
}
! do_spec_1 (" ", 0, NULL_PTR);
if (switches[switchnum].args != 0)
{
--- 4106,4110 ----
do_spec_1 (switches[switchnum].part1, 1, NULL_PTR);
}
!
if (switches[switchnum].args != 0)
{
*************** give_switch (switchnum, omit_first_word)
*** 4099,4106 ****
for (p = switches[switchnum].args; *p; p++)
{
do_spec_1 (*p, 1, NULL_PTR);
- do_spec_1 (" ", 0, NULL_PTR);
}
}
switches[switchnum].valid = 1;
}
--- 4112,4122 ----
for (p = switches[switchnum].args; *p; p++)
{
+ if (include_blanks)
+ do_spec_1 (" ", 0, NULL_PTR);
do_spec_1 (*p, 1, NULL_PTR);
}
}
+
+ do_spec_1 (" ", 0, NULL_PTR);
switches[switchnum].valid = 1;
}
diff -rcp2N gcc-2.7.2.2/gcc.texi g77-new/gcc.texi
*** gcc-2.7.2.2/gcc.texi Thu Feb 20 19:24:19 1997
--- g77-new/gcc.texi Thu Jul 10 20:08:58 1997
*************** original English.
*** 149,152 ****
--- 149,153 ----
@sp 3
@center Last updated 29 June 1996
+ @center (Revised for GNU Fortran 1997-01-10)
@sp 1
@c The version number appears twice more in this file.
diff -rcp2N gcc-2.7.2.2/glimits.h g77-new/glimits.h
*** gcc-2.7.2.2/glimits.h Wed Sep 29 17:30:54 1993
--- g77-new/glimits.h Thu Jul 10 20:08:58 1997
***************
*** 64,68 ****
(Same as `int'). */
#ifndef __LONG_MAX__
! #define __LONG_MAX__ 2147483647L
#endif
#undef LONG_MIN
--- 64,72 ----
(Same as `int'). */
#ifndef __LONG_MAX__
! # ifndef __alpha__
! # define __LONG_MAX__ 2147483647L
! # else
! # define __LONG_MAX__ 9223372036854775807LL
! # endif /* __alpha__ */
#endif
#undef LONG_MIN
diff -rcp2N gcc-2.7.2.2/integrate.c g77-new/integrate.c
*** gcc-2.7.2.2/integrate.c Fri Oct 20 18:48:13 1995
--- g77-new/integrate.c Sun Aug 10 18:46:31 1997
*************** static rtx copy_for_inline PROTO((rtx));
*** 67,70 ****
--- 67,71 ----
static void integrate_parm_decls PROTO((tree, struct inline_remap *, rtvec));
static void integrate_decl_tree PROTO((tree, int, struct inline_remap *));
+ static void save_constants_in_decl_trees PROTO ((tree));
static void subst_constants PROTO((rtx *, rtx, struct inline_remap *));
static void restore_constants PROTO((rtx *));
*************** save_for_inline_copying (fndecl)
*** 435,438 ****
--- 436,443 ----
}
+ /* Also scan all decls, and replace any constant pool references with the
+ actual constant. */
+ save_constants_in_decl_trees (DECL_INITIAL (fndecl));
+
/* Clear out the constant pool so that we can recreate it with the
copied constants below. */
*************** save_for_inline_nocopy (fndecl)
*** 781,784 ****
--- 786,793 ----
}
+ /* Also scan all decls, and replace any constant pool references with the
+ actual constant. */
+ save_constants_in_decl_trees (DECL_INITIAL (fndecl));
+
/* We have now allocated all that needs to be allocated permanently
on the rtx obstack. Set our high-water mark, so that we
*************** expand_inline_function (fndecl, parms, t
*** 1571,1575 ****
if (GET_CODE (XEXP (loc, 0)) == REG)
{
! temp = force_reg (Pmode, structure_value_addr);
map->reg_map[REGNO (XEXP (loc, 0))] = temp;
if ((CONSTANT_P (structure_value_addr)
--- 1580,1585 ----
if (GET_CODE (XEXP (loc, 0)) == REG)
{
! temp = force_reg (Pmode,
! force_operand (structure_value_addr, NULL_RTX));
map->reg_map[REGNO (XEXP (loc, 0))] = temp;
if ((CONSTANT_P (structure_value_addr)
*************** integrate_decl_tree (let, level, map)
*** 2029,2032 ****
--- 2039,2059 ----
}
}
+ }
+
+ /* Given a BLOCK node LET, search for all DECL_RTL fields, and pass them
+ through save_constants. */
+
+ static void
+ save_constants_in_decl_trees (let)
+ tree let;
+ {
+ tree t;
+
+ for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
+ if (DECL_RTL (t) != 0)
+ save_constants (&DECL_RTL (t));
+
+ for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
+ save_constants_in_decl_trees (t);
}
diff -rcp2N gcc-2.7.2.2/invoke.texi g77-new/invoke.texi
*** gcc-2.7.2.2/invoke.texi Tue Oct 3 11:40:43 1995
--- g77-new/invoke.texi Thu Jul 10 20:09:00 1997
***************
*** 1,3 ****
! @c Copyright (C) 1988, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
--- 1,3 ----
! @c Copyright (C) 1988, 89, 92-95, 1997 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
*************** in the following sections.
*** 149,152 ****
--- 149,153 ----
-fschedule-insns2 -fstrength-reduce -fthread-jumps
-funroll-all-loops -funroll-loops
+ -fmove-all-movables -freduce-all-givs -frerun-loop-opt
-O -O0 -O1 -O2 -O3
@end smallexample
*************** in addition to the above:
*** 331,334 ****
--- 332,337 ----
-fshort-double -fvolatile -fvolatile-global
-fverbose-asm -fpack-struct +e0 +e1
+ -fargument-alias -fargument-noalias
+ -fargument-noalias-global
@end smallexample
@end table
*************** Print extra warning messages for these e
*** 1253,1256 ****
--- 1256,1304 ----
@itemize @bullet
+ @cindex division by zero
+ @cindex zero, division by
+ @item
+ An integer division by zero is detected.
+
+ Some cases of division by zero might occur as the result
+ of using so-called ``safe'' macros.
+ For example:
+
+ @smallexample
+ #define BUCKETS(b) (((b) != NULL) ? (b)->buckets : 0)
+ @dots{...}
+ i = j / BUCKETS(b);
+ @end smallexample
+
+ Although analysis of the context of the above code could
+ prove that @samp{b} is never null when it is executed,
+ the division-by-zero warning is still useful, because
+ @code{gcc} generates code to do the division by zero at
+ run time so as to generate a run-time fault,
+ and tidy programmers will want to find ways to prevent
+ this needless code from being generated.
+
+ Note that @code{gcc} transforms expressions so as to find
+ opportunities for performing expensive operations
+ (such as division) at compile time instead of generating
+ code to perform them at run time.
+ For example, @code{gcc} transforms:
+
+ @smallexample
+ 2 / (i == 0)
+ @end smallexample
+
+ into:
+
+ @smallexample
+ (i == 0) ? (2 / 1) : (2 / 0)
+ @end smallexample
+
+ As a result, the division-by-zero warning might occur
+ in contexts where the divisor seems to be a non-constant.
+ It is useful in this case as well, because programmers might want
+ to clean up the code so the compiled code does not include
+ dead code to divide by zero.
+
@cindex @code{longjmp} warnings
@item
*************** and usually makes programs run more slow
*** 1941,1944 ****
--- 1989,2037 ----
implies @samp{-fstrength-reduce} as well as @samp{-frerun-cse-after-loop}.
+ @item -fmove-all-movables
+ Forces all invariant computations in loops to be moved
+ outside the loop.
+ This option is provided primarily to improve performance
+ for some Fortran code, though it might improve code written
+ in other languages.
+
+ @emph{Note:} When compiling programs written in Fortran,
+ this option is enabled by default.
+
+ Analysis of Fortran code optimization and the resulting
+ optimizations triggered by this option, and the
+ @samp{-freduce-all-givs} and @samp{-frerun-loop-opt}
+ options as well, were
+ contributed by Toon Moene (@code{toon@@moene.indiv.nluug.nl}).
+
+ These three options are intended to be removed someday, once
+ they have helped determine the efficacy of various
+ approaches to improving the performance of Fortran code.
+
+ Please let us (@code{fortran@@gnu.ai.mit.edu})
+ know how use of these options affects
+ the performance of your production code.
+ We're very interested in code that runs @emph{slower}
+ when these options are @emph{enabled}.
+
+ @item -freduce-all-givs
+ Forces all general-induction variables in loops to be
+ strength-reduced.
+ This option is provided primarily to improve performance
+ for some Fortran code, though it might improve code written
+ in other languages.
+
+ @emph{Note:} When compiling programs written in Fortran,
+ this option is enabled by default.
+
+ @item -frerun-loop-opt
+ Runs loop optimizations a second time.
+ This option is provided primarily to improve performance
+ for some Fortran code, though it might improve code written
+ in other languages.
+
+ @emph{Note:} When compiling programs written in Fortran,
+ this option is enabled by default.
+
@item -fno-peephole
Disable any machine-specific peephole optimizations.
*************** compilation).
*** 4229,4232 ****
--- 4322,4397 ----
With @samp{+e1}, G++ actually generates the code implementing virtual
functions defined in the code, and makes them publicly visible.
+
+ @cindex aliasing of parameters
+ @cindex parameters, aliased
+ @item -fargument-alias
+ @item -fargument-noalias
+ @item -fargument-noalias-global
+ Specify the possible relationships among parameters and between
+ parameters and global data.
+
+ @samp{-fargument-alias} specifies that arguments (parameters) may
+ alias each other and may alias global storage.
+ @samp{-fargument-noalias} specifies that arguments do not alias
+ each other, but may alias global storage.
+ @samp{-fargument-noalias-global} specifies that arguments do not
+ alias each other and do not alias global storage.
+
+ For code written in C, C++, and Objective-C, @samp{-fargument-alias}
+ is the default.
+ For code written in Fortran, @samp{-fargument-noalias-global} is
+ the default, though this is pertinent only on systems where
+ @code{g77} is installed.
+ (See the documentation for other compilers for information on the
+ defaults for their respective languages.)
+
+ Normally, @code{gcc} assumes that a write through a pointer
+ passed as a parameter to the current function might modify a
+ value pointed to by another pointer passed as a parameter, or
+ in global storage.
+
+ For example, consider this code:
+
+ @example
+ void x(int *i, int *j)
+ @{
+ extern int k;
+
+ ++*i;
+ ++*j;
+ ++k;
+ @}
+ @end example
+
+ When compiling the above function, @code{gcc} assumes that @samp{i} might
+ be a pointer to the same variable as @samp{j}, and that either @samp{i},
+ @samp{j}, or both might be a pointer to @samp{k}.
+
+ Therefore, @code{gcc} does not assume it can generate code to read
+ @samp{*i}, @samp{*j}, and @samp{k} into separate registers, increment
+ each register, then write the incremented values back out.
+
+ Instead, @code{gcc} must generate code that reads @samp{*i},
+ increments it, and writes it back before reading @samp{*j},
+ in case @samp{i} and @samp{j} are aliased, and, similarly,
+ that writes @samp{*j} before reading @samp{k}.
+ The result is code that, on many systems, takes longer to execute,
+ due to the way many processors schedule instruction execution.
+
+ Compiling the above code with the @samp{-fargument-noalias} option
+ allows @code{gcc} to assume that @samp{i} and @samp{j} do not alias
+ each other, but either might alias @samp{k}.
+
+ Compiling the above code with the @samp{-fargument-noalias-global}
+ option allows @code{gcc} to assume that no combination of @samp{i},
+ @samp{j}, and @samp{k} are aliases for each other.
+
+ @emph{Note:} Use the @samp{-fargument-noalias} and
+ @samp{-fargument-noalias-global} options with care.
+ While they can result in faster executables, they can
+ also result in executables with subtle bugs, bugs that
+ show up only when compiled for specific target systems,
+ or bugs that show up only when compiled by specific versions
+ of @code{g77}.
@end table
diff -rcp2N gcc-2.7.2.2/libgcc2.c g77-new/libgcc2.c
*** gcc-2.7.2.2/libgcc2.c Sun Nov 26 14:39:21 1995
--- g77-new/libgcc2.c Sun Aug 10 18:46:07 1997
*************** __gcc_bcmp (s1, s2, size)
*** 1193,1196 ****
--- 1193,1201 ----
#endif
+ #ifdef L__dummy
+ void
+ __dummy () {}
+ #endif
+
#ifdef L_varargs
#ifdef __i860__
diff -rcp2N gcc-2.7.2.2/local-alloc.c g77-new/local-alloc.c
*** gcc-2.7.2.2/local-alloc.c Mon Aug 21 13:15:44 1995
--- g77-new/local-alloc.c Sun Aug 10 18:46:10 1997
*************** static int this_insn_number;
*** 243,246 ****
--- 243,250 ----
static rtx this_insn;
+ /* Used to communicate changes made by update_equiv_regs to
+ memref_referenced_p. */
+ static rtx *reg_equiv_replacement;
+
static void alloc_qty PROTO((int, enum machine_mode, int, int));
static void alloc_qty_for_scratch PROTO((rtx, int, rtx, int, int));
*************** validate_equiv_mem_from_store (dest, set
*** 545,549 ****
&& reg_overlap_mentioned_p (dest, equiv_mem))
|| (GET_CODE (dest) == MEM
! && true_dependence (dest, equiv_mem)))
equiv_mem_modified = 1;
}
--- 549,553 ----
&& reg_overlap_mentioned_p (dest, equiv_mem))
|| (GET_CODE (dest) == MEM
! && true_dependence (dest, VOIDmode, equiv_mem, rtx_varies_p)))
equiv_mem_modified = 1;
}
*************** memref_referenced_p (memref, x)
*** 617,621 ****
switch (code)
{
- case REG:
case CONST_INT:
case CONST:
--- 621,624 ----
*************** memref_referenced_p (memref, x)
*** 629,634 ****
return 0;
case MEM:
! if (true_dependence (memref, x))
return 1;
break;
--- 632,642 ----
return 0;
+ case REG:
+ return (reg_equiv_replacement[REGNO (x)] == 0
+ || memref_referenced_p (memref,
+ reg_equiv_replacement[REGNO (x)]));
+
case MEM:
! if (true_dependence (memref, VOIDmode, x, rtx_varies_p))
return 1;
break;
*************** optimize_reg_copy_1 (insn, dest, src)
*** 818,827 ****
if (sregno >= FIRST_PSEUDO_REGISTER)
{
! reg_live_length[sregno] -= length;
! /* reg_live_length is only an approximation after combine
! if sched is not run, so make sure that we still have
! a reasonable value. */
! if (reg_live_length[sregno] < 2)
! reg_live_length[sregno] = 2;
reg_n_calls_crossed[sregno] -= n_calls;
}
--- 826,839 ----
if (sregno >= FIRST_PSEUDO_REGISTER)
{
! if (reg_live_length[sregno] >= 0)
! {
! reg_live_length[sregno] -= length;
! /* reg_live_length is only an approximation after
! combine if sched is not run, so make sure that we
! still have a reasonable value. */
! if (reg_live_length[sregno] < 2)
! reg_live_length[sregno] = 2;
! }
!
reg_n_calls_crossed[sregno] -= n_calls;
}
*************** optimize_reg_copy_1 (insn, dest, src)
*** 829,833 ****
if (dregno >= FIRST_PSEUDO_REGISTER)
{
! reg_live_length[dregno] += d_length;
reg_n_calls_crossed[dregno] += d_n_calls;
}
--- 841,847 ----
if (dregno >= FIRST_PSEUDO_REGISTER)
{
! if (reg_live_length[dregno] >= 0)
! reg_live_length[dregno] += d_length;
!
reg_n_calls_crossed[dregno] += d_n_calls;
}
*************** update_equiv_regs ()
*** 948,953 ****
{
rtx *reg_equiv_init_insn = (rtx *) alloca (max_regno * sizeof (rtx *));
- rtx *reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *));
rtx insn;
bzero ((char *) reg_equiv_init_insn, max_regno * sizeof (rtx *));
--- 962,968 ----
{
rtx *reg_equiv_init_insn = (rtx *) alloca (max_regno * sizeof (rtx *));
rtx insn;
+
+ reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *));
bzero ((char *) reg_equiv_init_insn, max_regno * sizeof (rtx *));
diff -rcp2N gcc-2.7.2.2/loop.c g77-new/loop.c
*** gcc-2.7.2.2/loop.c Thu Feb 20 19:24:20 1997
--- g77-new/loop.c Sun Aug 10 18:46:43 1997
*************** int *loop_number_exit_count;
*** 111,116 ****
unsigned HOST_WIDE_INT loop_n_iterations;
! /* Nonzero if there is a subroutine call in the current loop.
! (unknown_address_altered is also nonzero in this case.) */
static int loop_has_call;
--- 111,115 ----
unsigned HOST_WIDE_INT loop_n_iterations;
! /* Nonzero if there is a subroutine call in the current loop. */
static int loop_has_call;
*************** static char *moved_once;
*** 160,164 ****
here, we just turn on unknown_address_altered. */
! #define NUM_STORES 20
static rtx loop_store_mems[NUM_STORES];
--- 159,163 ----
here, we just turn on unknown_address_altered. */
! #define NUM_STORES 30
static rtx loop_store_mems[NUM_STORES];
*************** scan_loop (loop_start, end, nregs)
*** 669,673 ****
{
temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
! if (temp && CONSTANT_P (XEXP (temp, 0)))
src = XEXP (temp, 0), move_insn = 1;
if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX))
--- 668,673 ----
{
temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
! if (temp && CONSTANT_P (XEXP (temp, 0))
! && LEGITIMATE_CONSTANT_P (XEXP (temp, 0)))
src = XEXP (temp, 0), move_insn = 1;
if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX))
*************** move_movables (movables, threshold, insn
*** 1629,1632 ****
--- 1629,1633 ----
if (already_moved[regno]
+ || flag_move_all_movables
|| (threshold * savings * m->lifetime) >= insn_count
|| (m->forces && m->forces->done
*************** prescan_loop (start, end)
*** 2199,2203 ****
else if (GET_CODE (insn) == CALL_INSN)
{
! unknown_address_altered = 1;
loop_has_call = 1;
}
--- 2200,2205 ----
else if (GET_CODE (insn) == CALL_INSN)
{
! if (! CONST_CALL_P (insn))
! unknown_address_altered = 1;
loop_has_call = 1;
}
*************** invariant_p (x)
*** 2777,2781 ****
/* See if there is any dependence between a store and this load. */
for (i = loop_store_mems_idx - 1; i >= 0; i--)
! if (true_dependence (loop_store_mems[i], x))
return 0;
--- 2779,2783 ----
/* See if there is any dependence between a store and this load. */
for (i = loop_store_mems_idx - 1; i >= 0; i--)
! if (true_dependence (loop_store_mems[i], VOIDmode, x, rtx_varies_p))
return 0;
*************** strength_reduce (scan_start, end, loop_t
*** 3821,3826 ****
exit. */
! if (v->lifetime * threshold * benefit < insn_count
! && ! bl->reversed)
{
if (loop_dump_stream)
--- 3823,3828 ----
exit. */
! if ( ! flag_reduce_all_givs && v->lifetime * threshold * benefit < insn_count
! && ! bl->reversed )
{
if (loop_dump_stream)
*************** record_giv (v, insn, src_reg, dest_reg,
*** 4375,4378 ****
--- 4377,4382 ----
v->final_value = 0;
v->same_insn = 0;
+ v->unrolled = 0;
+ v->shared = 0;
/* The v->always_computable field is used in update_giv_derive, to
*************** check_final_value (v, loop_start, loop_e
*** 4652,4657 ****
if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
&& LABEL_NAME (JUMP_LABEL (p))
! && ((INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (v->insn)
! && INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (loop_start))
|| (INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (last_giv_use)
&& INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (loop_end))))
--- 4656,4664 ----
if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
&& LABEL_NAME (JUMP_LABEL (p))
! && ((INSN_UID (JUMP_LABEL (p)) >= max_uid_for_loop)
! || (INSN_UID (v->insn) >= max_uid_for_loop)
! || (INSN_UID (last_giv_use) >= max_uid_for_loop)
! || (INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (v->insn)
! && INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (loop_start))
|| (INSN_LUID (JUMP_LABEL (p)) > INSN_LUID (last_giv_use)
&& INSN_LUID (JUMP_LABEL (p)) < INSN_LUID (loop_end))))
*************** emit_iv_add_mult (b, m, a, reg, insert_b
*** 5560,5563 ****
--- 5567,5572 ----
emit_insn_before (seq, insert_before);
+
+ record_base_value (REGNO (reg), b);
}
diff -rcp2N gcc-2.7.2.2/loop.h g77-new/loop.h
*** gcc-2.7.2.2/loop.h Fri Jul 14 08:23:28 1995
--- g77-new/loop.h Thu Jul 10 20:09:03 1997
*************** struct induction
*** 89,92 ****
--- 89,95 ----
we won't use it to eliminate a biv, it
would probably lose. */
+ unsigned unrolled : 1; /* 1 if new register has been allocated in
+ unrolled loop. */
+ unsigned shared : 1;
int lifetime; /* Length of life of this giv */
int times_used; /* # times this giv is used. */
diff -rcp2N gcc-2.7.2.2/real.c g77-new/real.c
*** gcc-2.7.2.2/real.c Tue Aug 15 17:57:18 1995
--- g77-new/real.c Thu Jul 10 20:09:04 1997
*************** make_nan (nan, sign, mode)
*** 5625,5633 ****
}
! /* Convert an SFmode target `float' value to a REAL_VALUE_TYPE.
! This is the inverse of the function `etarsingle' invoked by
REAL_VALUE_TO_TARGET_SINGLE. */
REAL_VALUE_TYPE
ereal_from_float (f)
HOST_WIDE_INT f;
--- 5625,5699 ----
}
! /* This is the inverse of the function `etarsingle' invoked by
REAL_VALUE_TO_TARGET_SINGLE. */
REAL_VALUE_TYPE
+ ereal_unto_float (f)
+ long f;
+ {
+ REAL_VALUE_TYPE r;
+ unsigned EMUSHORT s[2];
+ unsigned EMUSHORT e[NE];
+
+ /* Convert 32 bit integer to array of 16 bit pieces in target machine order.
+ This is the inverse operation to what the function `endian' does. */
+ if (REAL_WORDS_BIG_ENDIAN)
+ {
+ s[0] = (unsigned EMUSHORT) (f >> 16);
+ s[1] = (unsigned EMUSHORT) f;
+ }
+ else
+ {
+ s[0] = (unsigned EMUSHORT) f;
+ s[1] = (unsigned EMUSHORT) (f >> 16);
+ }
+ /* Convert and promote the target float to E-type. */
+ e24toe (s, e);
+ /* Output E-type to REAL_VALUE_TYPE. */
+ PUT_REAL (e, &r);
+ return r;
+ }
+
+
+ /* This is the inverse of the function `etardouble' invoked by
+ REAL_VALUE_TO_TARGET_DOUBLE. */
+
+ REAL_VALUE_TYPE
+ ereal_unto_double (d)
+ long d[];
+ {
+ REAL_VALUE_TYPE r;
+ unsigned EMUSHORT s[4];
+ unsigned EMUSHORT e[NE];
+
+ /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */
+ if (REAL_WORDS_BIG_ENDIAN)
+ {
+ s[0] = (unsigned EMUSHORT) (d[0] >> 16);
+ s[1] = (unsigned EMUSHORT) d[0];
+ s[2] = (unsigned EMUSHORT) (d[1] >> 16);
+ s[3] = (unsigned EMUSHORT) d[1];
+ }
+ else
+ {
+ /* Target float words are little-endian. */
+ s[0] = (unsigned EMUSHORT) d[0];
+ s[1] = (unsigned EMUSHORT) (d[0] >> 16);
+ s[2] = (unsigned EMUSHORT) d[1];
+ s[3] = (unsigned EMUSHORT) (d[1] >> 16);
+ }
+ /* Convert target double to E-type. */
+ e53toe (s, e);
+ /* Output E-type to REAL_VALUE_TYPE. */
+ PUT_REAL (e, &r);
+ return r;
+ }
+
+
+ /* Convert an SFmode target `float' value to a REAL_VALUE_TYPE.
+ This is somewhat like ereal_unto_float, but the input types
+ for these are different. */
+
+ REAL_VALUE_TYPE
ereal_from_float (f)
HOST_WIDE_INT f;
*************** ereal_from_float (f)
*** 5658,5663 ****
/* Convert a DFmode target `double' value to a REAL_VALUE_TYPE.
! This is the inverse of the function `etardouble' invoked by
! REAL_VALUE_TO_TARGET_DOUBLE.
The DFmode is stored as an array of HOST_WIDE_INT in the target's
--- 5724,5729 ----
/* Convert a DFmode target `double' value to a REAL_VALUE_TYPE.
! This is somewhat like ereal_unto_double, but the input types
! for these are different.
The DFmode is stored as an array of HOST_WIDE_INT in the target's
diff -rcp2N gcc-2.7.2.2/real.h g77-new/real.h
*** gcc-2.7.2.2/real.h Thu Jun 15 07:57:56 1995
--- g77-new/real.h Thu Jul 10 20:09:05 1997
*************** extern void ereal_to_decimal PROTO((REAL
*** 152,155 ****
--- 152,157 ----
extern int ereal_cmp PROTO((REAL_VALUE_TYPE, REAL_VALUE_TYPE));
extern int ereal_isneg PROTO((REAL_VALUE_TYPE));
+ extern REAL_VALUE_TYPE ereal_unto_float PROTO((long));
+ extern REAL_VALUE_TYPE ereal_unto_double PROTO((long *));
extern REAL_VALUE_TYPE ereal_from_float PROTO((HOST_WIDE_INT));
extern REAL_VALUE_TYPE ereal_from_double PROTO((HOST_WIDE_INT *));
*************** extern REAL_VALUE_TYPE real_value_trunca
*** 197,200 ****
--- 199,208 ----
/* IN is a REAL_VALUE_TYPE. OUT is a long. */
#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) ((OUT) = etarsingle ((IN)))
+
+ /* Inverse of REAL_VALUE_TO_TARGET_DOUBLE. */
+ #define REAL_VALUE_UNTO_TARGET_DOUBLE(d) (ereal_unto_double (d))
+
+ /* Inverse of REAL_VALUE_TO_TARGET_SINGLE. */
+ #define REAL_VALUE_UNTO_TARGET_SINGLE(f) (ereal_unto_float (f))
/* d is an array of HOST_WIDE_INT that holds a double precision
diff -rcp2N gcc-2.7.2.2/recog.c g77-new/recog.c
*** gcc-2.7.2.2/recog.c Sat Jul 1 06:52:35 1995
--- g77-new/recog.c Sun Aug 10 18:46:55 1997
*************** register_operand (op, mode)
*** 872,876 ****
REGNO (SUBREG_REG (op)))
&& (GET_MODE_SIZE (mode)
! != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
return 0;
#endif
--- 872,878 ----
REGNO (SUBREG_REG (op)))
&& (GET_MODE_SIZE (mode)
! != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
! && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_INT
! && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_FLOAT)
return 0;
#endif
diff -rcp2N gcc-2.7.2.2/reload.c g77-new/reload.c
*** gcc-2.7.2.2/reload.c Sat Nov 11 08:23:54 1995
--- g77-new/reload.c Sun Aug 10 04:58:03 1997
***************
*** 1,4 ****
/* Search an insn for pseudo regs that must be in hard regs and are not.
! Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
This file is part of GNU CC.
--- 1,4 ----
/* Search an insn for pseudo regs that must be in hard regs and are not.
! Copyright (C) 1987, 88, 89, 92-5, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
*************** static int push_secondary_reload PROTO((
*** 292,295 ****
--- 292,296 ----
enum machine_mode, enum reload_type,
enum insn_code *));
+ static enum reg_class find_valid_class PROTO((enum machine_mode, int));
static int push_reload PROTO((rtx, rtx, rtx *, rtx *, enum reg_class,
enum machine_mode, enum machine_mode,
*************** static struct decomposition decompose PR
*** 305,312 ****
static int immune_p PROTO((rtx, rtx, struct decomposition));
static int alternative_allows_memconst PROTO((char *, int));
! static rtx find_reloads_toplev PROTO((rtx, int, enum reload_type, int, int));
static rtx make_memloc PROTO((rtx, int));
static int find_reloads_address PROTO((enum machine_mode, rtx *, rtx, rtx *,
! int, enum reload_type, int));
static rtx subst_reg_equivs PROTO((rtx));
static rtx subst_indexed_address PROTO((rtx));
--- 306,313 ----
static int immune_p PROTO((rtx, rtx, struct decomposition));
static int alternative_allows_memconst PROTO((char *, int));
! static rtx find_reloads_toplev PROTO((rtx, int, enum reload_type, int, int, short *));
static rtx make_memloc PROTO((rtx, int));
static int find_reloads_address PROTO((enum machine_mode, rtx *, rtx, rtx *,
! int, enum reload_type, int, short *));
static rtx subst_reg_equivs PROTO((rtx));
static rtx subst_indexed_address PROTO((rtx));
*************** push_secondary_reload (in_p, x, opnum, o
*** 590,599 ****
if (in_p && icode == CODE_FOR_nothing
! && SECONDARY_MEMORY_NEEDED (class, reload_class, reload_mode))
! get_secondary_mem (x, reload_mode, opnum, type);
if (! in_p && icode == CODE_FOR_nothing
! && SECONDARY_MEMORY_NEEDED (reload_class, class, reload_mode))
! get_secondary_mem (x, reload_mode, opnum, type);
#endif
}
--- 591,600 ----
if (in_p && icode == CODE_FOR_nothing
! && SECONDARY_MEMORY_NEEDED (class, reload_class, mode))
! get_secondary_mem (x, mode, opnum, type);
if (! in_p && icode == CODE_FOR_nothing
! && SECONDARY_MEMORY_NEEDED (reload_class, class, mode))
! get_secondary_mem (x, mode, opnum, type);
#endif
}
*************** get_secondary_mem (x, mode, opnum, type)
*** 673,677 ****
find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0),
! opnum, type, 0);
}
--- 674,678 ----
find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0),
! opnum, type, 0, NULL);
}
*************** clear_secondary_mem ()
*** 689,692 ****
--- 690,725 ----
#endif /* SECONDARY_MEMORY_NEEDED */
+ /* Find the largest class for which every register number plus N is valid in
+ M1 (if in range). Abort if no such class exists. */
+
+ static enum reg_class
+ find_valid_class (m1, n)
+ enum machine_mode m1;
+ int n;
+ {
+ int class;
+ int regno;
+ enum reg_class best_class;
+ int best_size = 0;
+
+ for (class = 1; class < N_REG_CLASSES; class++)
+ {
+ int bad = 0;
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER && ! bad; regno++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+ && TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
+ && ! HARD_REGNO_MODE_OK (regno + n, m1))
+ bad = 1;
+
+ if (! bad && reg_class_size[class] > best_size)
+ best_class = class, best_size = reg_class_size[class];
+ }
+
+ if (best_size == 0)
+ abort ();
+
+ return best_class;
+ }
+
/* Record one reload that needs to be performed.
IN is an rtx saying where the data are to be found before this instruction.
*************** push_reload (in, out, inloc, outloc, cla
*** 894,898 ****
&& GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
! && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in)), inmode)
|| (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
--- 927,932 ----
&& GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
! && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in)) + SUBREG_WORD (in),
! inmode)
|| (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
*************** push_reload (in, out, inloc, outloc, cla
*** 909,913 ****
output before the outer reload. */
push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
! GENERAL_REGS, VOIDmode, VOIDmode, 0, 0, opnum, type);
dont_remove_subreg = 1;
}
--- 943,948 ----
output before the outer reload. */
push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
! find_valid_class (inmode, SUBREG_WORD (in)),
! VOIDmode, VOIDmode, 0, 0, opnum, type);
dont_remove_subreg = 1;
}
*************** push_reload (in, out, inloc, outloc, cla
*** 982,986 ****
&& GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
! && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (out)), outmode)
|| (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
--- 1017,1022 ----
&& GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
! && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (out)) + SUBREG_WORD (out),
! outmode)
|| (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
*************** push_reload (in, out, inloc, outloc, cla
*** 998,1002 ****
dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
! &SUBREG_REG (out), ALL_REGS, VOIDmode, VOIDmode, 0, 0,
opnum, RELOAD_OTHER);
}
--- 1034,1040 ----
dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
! &SUBREG_REG (out),
! find_valid_class (outmode, SUBREG_WORD (out)),
! VOIDmode, VOIDmode, 0, 0,
opnum, RELOAD_OTHER);
}
*************** find_reloads (insn, replace, ind_levels,
*** 2241,2244 ****
--- 2279,2283 ----
int goal_earlyclobber, this_earlyclobber;
enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+ short force_update[MAX_RECOG_OPERANDS];
this_insn = insn;
*************** find_reloads (insn, replace, ind_levels,
*** 2272,2275 ****
--- 2311,2316 ----
#endif
+ bzero ((char *) force_update, sizeof force_update);
+
/* Find what kind of insn this is. NOPERANDS gets number of operands.
Make OPERANDS point to a vector of operand values.
*************** find_reloads (insn, replace, ind_levels,
*** 2469,2473 ****
find_reloads_address (VOIDmode, NULL_PTR,
recog_operand[i], recog_operand_loc[i],
! i, operand_type[i], ind_levels);
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
}
--- 2510,2515 ----
find_reloads_address (VOIDmode, NULL_PTR,
recog_operand[i], recog_operand_loc[i],
! i, operand_type[i], ind_levels,
! &force_update[i]);
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
}
*************** find_reloads (insn, replace, ind_levels,
*** 2478,2482 ****
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
! i, address_type[i], ind_levels))
address_reloaded[i] = 1;
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
--- 2520,2525 ----
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
! i, address_type[i], ind_levels,
! &force_update[i]))
address_reloaded[i] = 1;
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
*************** find_reloads (insn, replace, ind_levels,
*** 2487,2491 ****
ind_levels,
set != 0
! && &SET_DEST (set) == recog_operand_loc[i]);
else if (code == PLUS)
/* We can get a PLUS as an "operand" as a result of
--- 2530,2535 ----
ind_levels,
set != 0
! && &SET_DEST (set) == recog_operand_loc[i],
! &force_update[i]);
else if (code == PLUS)
/* We can get a PLUS as an "operand" as a result of
*************** find_reloads (insn, replace, ind_levels,
*** 2493,2497 ****
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]
= find_reloads_toplev (recog_operand[i], i, address_type[i],
! ind_levels, 0);
else if (code == REG)
{
--- 2537,2541 ----
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i]
= find_reloads_toplev (recog_operand[i], i, address_type[i],
! ind_levels, 0, &force_update[i]);
else if (code == REG)
{
*************** find_reloads (insn, replace, ind_levels,
*** 2505,2510 ****
if (reg_equiv_constant[regno] != 0
&& (set == 0 || &SET_DEST (set) != recog_operand_loc[i]))
! substed_operand[i] = recog_operand[i]
! = reg_equiv_constant[regno];
#if 0 /* This might screw code in reload1.c to delete prior output-reload
that feeds this insn. */
--- 2549,2557 ----
if (reg_equiv_constant[regno] != 0
&& (set == 0 || &SET_DEST (set) != recog_operand_loc[i]))
! {
! substed_operand[i] = recog_operand[i]
! = reg_equiv_constant[regno];
! force_update[i] = 1;
! }
#if 0 /* This might screw code in reload1.c to delete prior output-reload
that feeds this insn. */
*************** find_reloads (insn, replace, ind_levels,
*** 2545,2549 ****
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
! i, address_type[i], ind_levels);
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
}
--- 2592,2597 ----
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
! i, address_type[i], ind_levels,
! &force_update[i]);
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
}
*************** find_reloads (insn, replace, ind_levels,
*** 3415,3419 ****
= find_reloads_toplev (force_const_mem (operand_mode[i],
recog_operand[i]),
! i, address_type[i], ind_levels, 0);
if (alternative_allows_memconst (constraints1[i],
goal_alternative_number))
--- 3463,3467 ----
= find_reloads_toplev (force_const_mem (operand_mode[i],
recog_operand[i]),
! i, address_type[i], ind_levels, 0, NULL);
if (alternative_allows_memconst (constraints1[i],
goal_alternative_number))
*************** find_reloads (insn, replace, ind_levels,
*** 3595,3609 ****
Don't do this if we aren't making replacements because we might be
propagating things allocated by frame pointer elimination into places
! it doesn't expect. */
! if (insn_code_number >= 0 && replace)
! for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
! {
! int opno = recog_dup_num[i];
! *recog_dup_loc[i] = *recog_operand_loc[opno];
! if (operand_reloadnum[opno] >= 0)
! push_replacement (recog_dup_loc[i], operand_reloadnum[opno],
! insn_operand_mode[insn_code_number][opno]);
! }
#if 0
--- 3643,3664 ----
Don't do this if we aren't making replacements because we might be
propagating things allocated by frame pointer elimination into places
! it doesn't expect. However, always do it for replaces of pseudos
! by constants. */
! for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
! {
! int opno = recog_dup_num[i];
!
! if (! (insn_code_number >= 0 && replace))
! {
! if (! force_update[opno])
! continue;
! }
!
! *recog_dup_loc[i] = *recog_operand_loc[opno];
! if (operand_reloadnum[opno] >= 0)
! push_replacement (recog_dup_loc[i], operand_reloadnum[opno],
! insn_operand_mode[insn_code_number][opno]);
! }
#if 0
*************** find_reloads (insn, replace, ind_levels,
*** 3829,3832 ****
--- 3884,3888 ----
register RTX_CODE code = GET_CODE (recog_operand[i]);
int is_set_dest = GET_CODE (body) == SET && (i == 0);
+ short ign;
if (insn_code_number >= 0)
*************** find_reloads (insn, replace, ind_levels,
*** 3834,3838 ****
find_reloads_address (VOIDmode, NULL_PTR,
recog_operand[i], recog_operand_loc[i],
! i, RELOAD_FOR_INPUT, ind_levels);
/* In these cases, we can't tell if the operand is an input
--- 3890,3894 ----
find_reloads_address (VOIDmode, NULL_PTR,
recog_operand[i], recog_operand_loc[i],
! i, RELOAD_FOR_INPUT, ind_levels, &ign);
/* In these cases, we can't tell if the operand is an input
*************** find_reloads (insn, replace, ind_levels,
*** 3845,3853 ****
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
! i, RELOAD_OTHER, ind_levels);
if (code == SUBREG)
recog_operand[i] = *recog_operand_loc[i]
= find_reloads_toplev (recog_operand[i], i, RELOAD_OTHER,
! ind_levels, is_set_dest);
if (code == REG)
{
--- 3901,3909 ----
XEXP (recog_operand[i], 0),
&XEXP (recog_operand[i], 0),
! i, RELOAD_OTHER, ind_levels, &ign);
if (code == SUBREG)
recog_operand[i] = *recog_operand_loc[i]
= find_reloads_toplev (recog_operand[i], i, RELOAD_OTHER,
! ind_levels, is_set_dest, &ign);
if (code == REG)
{
*************** alternative_allows_memconst (constraint,
*** 3908,3915 ****
IS_SET_DEST is true if X is the destination of a SET, which is not
! appropriate to be replaced by a constant. */
static rtx
! find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest)
rtx x;
int opnum;
--- 3964,3974 ----
IS_SET_DEST is true if X is the destination of a SET, which is not
! appropriate to be replaced by a constant.
!
! FORCE_UPDATE, if non-NULL, is the address of a SHORT that is set to
! 1 if X is replaced with something based on reg_equiv_constant. */
static rtx
! find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, force_update)
rtx x;
int opnum;
*************** find_reloads_toplev (x, opnum, type, ind
*** 3917,3920 ****
--- 3976,3980 ----
int ind_levels;
int is_set_dest;
+ short *force_update;
{
register RTX_CODE code = GET_CODE (x);
*************** find_reloads_toplev (x, opnum, type, ind
*** 3928,3932 ****
register int regno = REGNO (x);
if (reg_equiv_constant[regno] != 0 && !is_set_dest)
! x = reg_equiv_constant[regno];
#if 0
/* This creates (subreg (mem...)) which would cause an unnecessary
--- 3988,3998 ----
register int regno = REGNO (x);
if (reg_equiv_constant[regno] != 0 && !is_set_dest)
! {
! x = reg_equiv_constant[regno];
! if (force_update)
! *force_update = 1;
! else
! abort (); /* Learn why this happens. */
! }
#if 0
/* This creates (subreg (mem...)) which would cause an unnecessary
*************** find_reloads_toplev (x, opnum, type, ind
*** 3951,3955 ****
find_reloads_address (GET_MODE (x), NULL_PTR,
XEXP (x, 0),
! &XEXP (x, 0), opnum, type, ind_levels);
}
return x;
--- 4017,4022 ----
find_reloads_address (GET_MODE (x), NULL_PTR,
XEXP (x, 0),
! &XEXP (x, 0), opnum, type, ind_levels,
! force_update);
}
return x;
*************** find_reloads_toplev (x, opnum, type, ind
*** 3959,3963 ****
rtx tem = x;
find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
! opnum, type, ind_levels);
return tem;
}
--- 4026,4030 ----
rtx tem = x;
find_reloads_address (GET_MODE (x), &tem, XEXP (x, 0), &XEXP (x, 0),
! opnum, type, ind_levels, force_update);
return tem;
}
*************** find_reloads_toplev (x, opnum, type, ind
*** 3982,3986 ****
&& (tem = gen_lowpart_common (GET_MODE (x),
reg_equiv_constant[regno])) != 0)
! return tem;
if (GET_MODE_BITSIZE (GET_MODE (x)) == BITS_PER_WORD
--- 4049,4059 ----
&& (tem = gen_lowpart_common (GET_MODE (x),
reg_equiv_constant[regno])) != 0)
! {
! if (force_update)
! *force_update = 1;
! else
! abort (); /* Learn why this happens. */
! return tem;
! }
if (GET_MODE_BITSIZE (GET_MODE (x)) == BITS_PER_WORD
*************** find_reloads_toplev (x, opnum, type, ind
*** 3990,3994 ****
SUBREG_WORD (x), 0,
GET_MODE (SUBREG_REG (x)))) != 0)
! return tem;
if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
--- 4063,4073 ----
SUBREG_WORD (x), 0,
GET_MODE (SUBREG_REG (x)))) != 0)
! {
! if (force_update)
! *force_update = 1;
! else
! abort (); /* Learn why this happens. */
! return tem;
! }
if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
*************** find_reloads_toplev (x, opnum, type, ind
*** 4040,4044 ****
find_reloads_address (GET_MODE (x), NULL_PTR,
XEXP (x, 0),
! &XEXP (x, 0), opnum, type, ind_levels);
}
--- 4119,4124 ----
find_reloads_address (GET_MODE (x), NULL_PTR,
XEXP (x, 0),
! &XEXP (x, 0), opnum, type, ind_levels,
! force_update);
}
*************** find_reloads_toplev (x, opnum, type, ind
*** 4049,4053 ****
if (fmt[i] == 'e')
XEXP (x, i) = find_reloads_toplev (XEXP (x, i), opnum, type,
! ind_levels, is_set_dest);
}
return x;
--- 4129,4133 ----
if (fmt[i] == 'e')
XEXP (x, i) = find_reloads_toplev (XEXP (x, i), opnum, type,
! ind_levels, is_set_dest, NULL);
}
return x;
*************** make_memloc (ad, regno)
*** 4110,4114 ****
static int
! find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels)
enum machine_mode mode;
rtx *memrefloc;
--- 4190,4195 ----
static int
! find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels,
! force_update)
enum machine_mode mode;
rtx *memrefloc;
*************** find_reloads_address (mode, memrefloc, a
*** 4118,4121 ****
--- 4199,4203 ----
enum reload_type type;
int ind_levels;
+ short *force_update;
{
register int regno;
*************** find_reloads_address (mode, memrefloc, a
*** 4134,4137 ****
--- 4216,4223 ----
{
*loc = ad = reg_equiv_constant[regno];
+ if (force_update)
+ *force_update = 1;
+ else
+ abort (); /* Learn why this happens. */
return 1;
}
*************** find_reloads_address (mode, memrefloc, a
*** 4141,4145 ****
tem = make_memloc (ad, regno);
find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
! &XEXP (tem, 0), opnum, type, ind_levels);
push_reload (tem, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
GET_MODE (ad), VOIDmode, 0, 0,
--- 4227,4231 ----
tem = make_memloc (ad, regno);
find_reloads_address (GET_MODE (tem), NULL_PTR, XEXP (tem, 0),
! &XEXP (tem, 0), opnum, type, ind_levels, NULL);
push_reload (tem, NULL_RTX, loc, NULL_PTR, BASE_REG_CLASS,
GET_MODE (ad), VOIDmode, 0, 0,
*************** find_reloads_address (mode, memrefloc, a
*** 4214,4218 ****
tem = ad;
find_reloads_address (GET_MODE (ad), &tem, XEXP (ad, 0), &XEXP (ad, 0),
! opnum, type, ind_levels == 0 ? 0 : ind_levels - 1);
/* If tem was changed, then we must create a new memory reference to
--- 4300,4305 ----
tem = ad;
find_reloads_address (GET_MODE (ad), &tem, XEXP (ad, 0), &XEXP (ad, 0),
! opnum, type, ind_levels == 0 ? 0 : ind_levels - 1,
! NULL);
/* If tem was changed, then we must create a new memory reference to
*************** find_reloads_address_1 (x, context, loc,
*** 4722,4726 ****
/* First reload the memory location's address. */
find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
! &XEXP (tem, 0), opnum, type, ind_levels);
/* Put this inside a new increment-expression. */
x = gen_rtx (GET_CODE (x), GET_MODE (x), tem);
--- 4809,4814 ----
/* First reload the memory location's address. */
find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
! &XEXP (tem, 0), opnum, type, ind_levels,
! NULL);
/* Put this inside a new increment-expression. */
x = gen_rtx (GET_CODE (x), GET_MODE (x), tem);
*************** find_reloads_address_1 (x, context, loc,
*** 4788,4792 ****
find_reloads_address (GET_MODE (x), &XEXP (x, 0),
XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
! opnum, type, ind_levels);
reloadnum = push_reload (x, NULL_RTX, loc, NULL_PTR,
--- 4876,4880 ----
find_reloads_address (GET_MODE (x), &XEXP (x, 0),
XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
! opnum, type, ind_levels, NULL);
reloadnum = push_reload (x, NULL_RTX, loc, NULL_PTR,
*************** find_reloads_address_1 (x, context, loc,
*** 4818,4822 ****
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
! opnum, type, ind_levels);
push_reload (*loc, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
--- 4906,4910 ----
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
! opnum, type, ind_levels, NULL);
push_reload (*loc, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
*************** find_reloads_address_1 (x, context, loc,
*** 4852,4856 ****
x = make_memloc (x, regno);
find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
! opnum, type, ind_levels);
}
--- 4940,4944 ----
x = make_memloc (x, regno);
find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
! opnum, type, ind_levels, NULL);
}
*************** find_reloads_address_part (x, loc, class
*** 4965,4969 ****
rtx tem = x = force_const_mem (mode, x);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
! opnum, type, ind_levels);
}
--- 5053,5057 ----
rtx tem = x = force_const_mem (mode, x);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
! opnum, type, ind_levels, NULL);
}
*************** find_reloads_address_part (x, loc, class
*** 4977,4981 ****
x = gen_rtx (PLUS, GET_MODE (x), XEXP (x, 0), tem);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
! opnum, type, ind_levels);
}
--- 5065,5069 ----
x = gen_rtx (PLUS, GET_MODE (x), XEXP (x, 0), tem);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
! opnum, type, ind_levels, NULL);
}
*************** find_equiv_reg (goal, insn, class, other
*** 5518,5522 ****
and is also a register that appears in the address of GOAL. */
! if (goal_mem && value == SET_DEST (PATTERN (where))
&& refers_to_regno_for_reload_p (valueno,
(valueno
--- 5606,5610 ----
and is also a register that appears in the address of GOAL. */
! if (goal_mem && value == SET_DEST (single_set (where))
&& refers_to_regno_for_reload_p (valueno,
(valueno
*************** debug_reload()
*** 5900,5904 ****
if (reload_nocombine[r])
! fprintf (stderr, ", can combine", reload_nocombine[r]);
if (reload_secondary_p[r])
--- 5988,5992 ----
if (reload_nocombine[r])
! fprintf (stderr, ", can't combine %d", reload_nocombine[r]);
if (reload_secondary_p[r])
diff -rcp2N gcc-2.7.2.2/reload1.c g77-new/reload1.c
*** gcc-2.7.2.2/reload1.c Sun Nov 5 11:22:22 1995
--- g77-new/reload1.c Sun Aug 10 18:47:00 1997
*************** reload (first, global, dumpfile)
*** 542,546 ****
Also find all paradoxical subregs and find largest such for each pseudo.
On machines with small register classes, record hard registers that
! are used for user variables. These can never be used for spills. */
for (insn = first; insn; insn = NEXT_INSN (insn))
--- 542,548 ----
Also find all paradoxical subregs and find largest such for each pseudo.
On machines with small register classes, record hard registers that
! are used for user variables. These can never be used for spills.
! Also look for a "constant" NOTE_INSN_SETJMP. This means that all
! caller-saved registers must be marked live. */
for (insn = first; insn; insn = NEXT_INSN (insn))
*************** reload (first, global, dumpfile)
*** 548,551 ****
--- 550,559 ----
rtx set = single_set (insn);
+ if (GET_CODE (insn) == NOTE && CONST_CALL_P (insn)
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (! call_used_regs[i])
+ regs_ever_live[i] = 1;
+
if (set != 0 && GET_CODE (SET_DEST (set)) == REG)
{
*************** reload (first, global, dumpfile)
*** 564,568 ****
if (GET_CODE (x) == MEM)
reg_equiv_memory_loc[i] = x;
! else if (CONSTANT_P (x))
{
if (LEGITIMATE_CONSTANT_P (x))
--- 572,578 ----
if (GET_CODE (x) == MEM)
reg_equiv_memory_loc[i] = x;
! else if (CONSTANT_P (x)
! && ! (GET_CODE (x) == CONST
! && GET_CODE (XEXP (x, 0)) == MINUS))
{
if (LEGITIMATE_CONSTANT_P (x))
*************** eliminate_regs (x, mem_mode, insn)
*** 2886,2890 ****
/* Fall through to generic unary operation case. */
- case USE:
case STRICT_LOW_PART:
case NEG: case NOT:
--- 2896,2899 ----
*************** eliminate_regs (x, mem_mode, insn)
*** 2975,2978 ****
--- 2984,3000 ----
return x;
+ case USE:
+ /* If using a register that is the source of an eliminate we still
+ think can be performed, note it cannot be performed since we don't
+ know how this register is used. */
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if (ep->from_rtx == XEXP (x, 0))
+ ep->can_eliminate = 0;
+
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ if (new != XEXP (x, 0))
+ return gen_rtx (code, GET_MODE (x), new);
+ return x;
+
case CLOBBER:
/* If clobbering a register that is the replacement register for an
*************** gen_reload (out, in, opnum, type)
*** 6736,6741 ****
--- 6758,6765 ----
if (GET_CODE (in) == PLUS
&& (GET_CODE (XEXP (in, 0)) == REG
+ || GET_CODE (XEXP (in, 0)) == SUBREG
|| GET_CODE (XEXP (in, 0)) == MEM)
&& (GET_CODE (XEXP (in, 1)) == REG
+ || GET_CODE (XEXP (in, 1)) == SUBREG
|| CONSTANT_P (XEXP (in, 1))
|| GET_CODE (XEXP (in, 1)) == MEM))
*************** gen_reload (out, in, opnum, type)
*** 6798,6807 ****
we emit below. */
! if (CONSTANT_P (op1) || GET_CODE (op1) == MEM
|| (GET_CODE (op1) == REG
&& REGNO (op1) >= FIRST_PSEUDO_REGISTER))
tem = op0, op0 = op1, op1 = tem;
! emit_insn (gen_move_insn (out, op0));
/* If OP0 and OP1 are the same, we can use OUT for OP1.
--- 6822,6831 ----
we emit below. */
! if (CONSTANT_P (op1) || GET_CODE (op1) == MEM || GET_CODE (op1) == SUBREG
|| (GET_CODE (op1) == REG
&& REGNO (op1) >= FIRST_PSEUDO_REGISTER))
tem = op0, op0 = op1, op1 = tem;
! gen_reload (out, op0, opnum, type);
/* If OP0 and OP1 are the same, we can use OUT for OP1.
*************** gen_reload (out, in, opnum, type)
*** 6831,6835 ****
delete_insns_since (last);
! emit_insn (gen_move_insn (out, op1));
emit_insn (gen_add2_insn (out, op0));
}
--- 6855,6859 ----
delete_insns_since (last);
! gen_reload (out, op1, opnum, type);
emit_insn (gen_add2_insn (out, op0));
}
*************** gen_reload (out, in, opnum, type)
*** 6852,6857 ****
in = gen_rtx (REG, GET_MODE (loc), REGNO (in));
! emit_insn (gen_move_insn (loc, in));
! emit_insn (gen_move_insn (out, loc));
}
#endif
--- 6876,6881 ----
in = gen_rtx (REG, GET_MODE (loc), REGNO (in));
! gen_reload (loc, in, opnum, type);
! gen_reload (out, loc, opnum, type);
}
#endif
diff -rcp2N gcc-2.7.2.2/rtl.c g77-new/rtl.c
*** gcc-2.7.2.2/rtl.c Thu Jun 15 08:02:59 1995
--- g77-new/rtl.c Thu Jul 10 20:09:06 1997
*************** char *reg_note_name[] = { "", "REG_DEAD"
*** 179,183 ****
"REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
"REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
! "REG_DEP_ANTI", "REG_DEP_OUTPUT" };
/* Allocate an rtx vector of N elements.
--- 179,183 ----
"REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
"REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
! "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_NOALIAS" };
/* Allocate an rtx vector of N elements.
diff -rcp2N gcc-2.7.2.2/rtl.h g77-new/rtl.h
*** gcc-2.7.2.2/rtl.h Thu Jun 15 08:03:16 1995
--- g77-new/rtl.h Thu Jul 10 20:09:07 1997
*************** enum reg_note { REG_DEAD = 1, REG_INC =
*** 349,353 ****
REG_NONNEG = 8, REG_NO_CONFLICT = 9, REG_UNUSED = 10,
REG_CC_SETTER = 11, REG_CC_USER = 12, REG_LABEL = 13,
! REG_DEP_ANTI = 14, REG_DEP_OUTPUT = 15 };
/* Define macros to extract and insert the reg-note kind in an EXPR_LIST. */
--- 349,353 ----
REG_NONNEG = 8, REG_NO_CONFLICT = 9, REG_UNUSED = 10,
REG_CC_SETTER = 11, REG_CC_USER = 12, REG_LABEL = 13,
! REG_DEP_ANTI = 14, REG_DEP_OUTPUT = 15, REG_NOALIAS = 16 };
/* Define macros to extract and insert the reg-note kind in an EXPR_LIST. */
*************** extern char *reg_note_name[];
*** 432,436 ****
#define NOTE_INSN_FUNCTION_BEG -13
-
#if 0 /* These are not used, and I don't know what they were for. --rms. */
#define NOTE_DECL_NAME(INSN) ((INSN)->fld[3].rtstr)
--- 432,435 ----
*************** extern char *note_insn_name[];
*** 576,579 ****
--- 575,579 ----
/* For a TRAP_IF rtx, TRAP_CONDITION is an expression. */
#define TRAP_CONDITION(RTX) ((RTX)->fld[0].rtx)
+ #define TRAP_CODE(RTX) ((RTX)->fld[1].rtint)
/* 1 in a SYMBOL_REF if it addresses this function's constants pool. */
*************** extern rtx eliminate_constant_term PROTO
*** 817,820 ****
--- 817,830 ----
extern rtx expand_complex_abs PROTO((enum machine_mode, rtx, rtx, int));
extern enum machine_mode choose_hard_reg_mode PROTO((int, int));
+ extern int rtx_varies_p PROTO((rtx));
+ extern int may_trap_p PROTO((rtx));
+ extern int side_effects_p PROTO((rtx));
+ extern int volatile_refs_p PROTO((rtx));
+ extern int volatile_insn_p PROTO((rtx));
+ extern void remove_note PROTO((rtx, rtx));
+ extern void note_stores PROTO((rtx, void (*)()));
+ extern int refers_to_regno_p PROTO((int, int, rtx, rtx *));
+ extern int reg_overlap_mentioned_p PROTO((rtx, rtx));
+
/* Maximum number of parallel sets and clobbers in any insn in this fn.
*************** extern rtx *regno_reg_rtx;
*** 967,968 ****
--- 977,987 ----
extern int rtx_to_tree_code PROTO((enum rtx_code));
+
+ extern int true_dependence PROTO((rtx, enum machine_mode, rtx, int (*)()));
+ extern int read_dependence PROTO((rtx, rtx));
+ extern int anti_dependence PROTO((rtx, rtx));
+ extern int output_dependence PROTO((rtx, rtx));
+ extern void init_alias_analysis PROTO((void));
+ extern void end_alias_analysis PROTO((void));
+ extern void mark_user_reg PROTO((rtx));
+ extern void mark_reg_pointer PROTO((rtx));
diff -rcp2N gcc-2.7.2.2/sched.c g77-new/sched.c
*** gcc-2.7.2.2/sched.c Thu Jun 15 08:06:39 1995
--- g77-new/sched.c Sun Aug 10 18:46:13 1997
*************** Boston, MA 02111-1307, USA. */
*** 126,129 ****
--- 126,132 ----
#include "insn-attr.h"
+ extern char *reg_known_equiv_p;
+ extern rtx *reg_known_value;
+
#ifdef INSN_SCHEDULING
/* Arrays set up by scheduling for the same respective purposes as
*************** static int *sched_reg_live_length;
*** 143,146 ****
--- 146,150 ----
by splitting insns. */
static rtx *reg_last_uses;
+ static int reg_last_uses_size;
static rtx *reg_last_sets;
static regset reg_pending_sets;
*************** struct sometimes
*** 294,302 ****
/* Forward declarations. */
- static rtx canon_rtx PROTO((rtx));
- static int rtx_equal_for_memref_p PROTO((rtx, rtx));
- static rtx find_symbolic_term PROTO((rtx));
- static int memrefs_conflict_p PROTO((int, rtx, int, rtx,
- HOST_WIDE_INT));
static void add_dependence PROTO((rtx, rtx, enum reg_note));
static void remove_dependence PROTO((rtx, rtx));
--- 298,301 ----
*************** static int priority PROTO((rtx));
*** 314,318 ****
static void free_pending_lists PROTO((void));
static void add_insn_mem_dependence PROTO((rtx *, rtx *, rtx, rtx));
! static void flush_pending_lists PROTO((rtx));
static void sched_analyze_1 PROTO((rtx, rtx));
static void sched_analyze_2 PROTO((rtx, rtx));
--- 313,317 ----
static void free_pending_lists PROTO((void));
static void add_insn_mem_dependence PROTO((rtx *, rtx *, rtx, rtx));
! static void flush_pending_lists PROTO((rtx, int));
static void sched_analyze_1 PROTO((rtx, rtx));
static void sched_analyze_2 PROTO((rtx, rtx));
*************** void schedule_insns PROTO((FILE *));
*** 346,885 ****
#endif /* INSN_SCHEDULING */
- #define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
-
- /* Vector indexed by N giving the initial (unchanging) value known
- for pseudo-register N. */
- static rtx *reg_known_value;
-
- /* Vector recording for each reg_known_value whether it is due to a
- REG_EQUIV note. Future passes (viz., reload) may replace the
- pseudo with the equivalent expression and so we account for the
- dependences that would be introduced if that happens. */
- /* ??? This is a problem only on the Convex. The REG_EQUIV notes created in
- assign_parms mention the arg pointer, and there are explicit insns in the
- RTL that modify the arg pointer. Thus we must ensure that such insns don't
- get scheduled across each other because that would invalidate the REG_EQUIV
- notes. One could argue that the REG_EQUIV notes are wrong, but solving
- the problem in the scheduler will likely give better code, so we do it
- here. */
- static char *reg_known_equiv_p;
-
- /* Indicates number of valid entries in reg_known_value. */
- static int reg_known_value_size;
-
- static rtx
- canon_rtx (x)
- rtx x;
- {
- if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
- && REGNO (x) <= reg_known_value_size)
- return reg_known_value[REGNO (x)];
- else if (GET_CODE (x) == PLUS)
- {
- rtx x0 = canon_rtx (XEXP (x, 0));
- rtx x1 = canon_rtx (XEXP (x, 1));
-
- if (x0 != XEXP (x, 0) || x1 != XEXP (x, 1))
- {
- /* We can tolerate LO_SUMs being offset here; these
- rtl are used for nothing other than comparisons. */
- if (GET_CODE (x0) == CONST_INT)
- return plus_constant_for_output (x1, INTVAL (x0));
- else if (GET_CODE (x1) == CONST_INT)
- return plus_constant_for_output (x0, INTVAL (x1));
- return gen_rtx (PLUS, GET_MODE (x), x0, x1);
- }
- }
- return x;
- }
-
- /* Set up all info needed to perform alias analysis on memory references. */
-
- void
- init_alias_analysis ()
- {
- int maxreg = max_reg_num ();
- rtx insn;
- rtx note;
- rtx set;
-
- reg_known_value_size = maxreg;
-
- reg_known_value
- = (rtx *) oballoc ((maxreg-FIRST_PSEUDO_REGISTER) * sizeof (rtx))
- - FIRST_PSEUDO_REGISTER;
- bzero ((char *) (reg_known_value + FIRST_PSEUDO_REGISTER),
- (maxreg-FIRST_PSEUDO_REGISTER) * sizeof (rtx));
-
- reg_known_equiv_p
- = (char *) oballoc ((maxreg -FIRST_PSEUDO_REGISTER) * sizeof (char))
- - FIRST_PSEUDO_REGISTER;
- bzero (reg_known_equiv_p + FIRST_PSEUDO_REGISTER,
- (maxreg - FIRST_PSEUDO_REGISTER) * sizeof (char));
-
- /* Fill in the entries with known constant values. */
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if ((set = single_set (insn)) != 0
- && GET_CODE (SET_DEST (set)) == REG
- && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
- && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
- && reg_n_sets[REGNO (SET_DEST (set))] == 1)
- || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
- && GET_CODE (XEXP (note, 0)) != EXPR_LIST)
- {
- int regno = REGNO (SET_DEST (set));
- reg_known_value[regno] = XEXP (note, 0);
- reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV;
- }
-
- /* Fill in the remaining entries. */
- while (--maxreg >= FIRST_PSEUDO_REGISTER)
- if (reg_known_value[maxreg] == 0)
- reg_known_value[maxreg] = regno_reg_rtx[maxreg];
- }
-
- /* Return 1 if X and Y are identical-looking rtx's.
-
- We use the data in reg_known_value above to see if two registers with
- different numbers are, in fact, equivalent. */
-
- static int
- rtx_equal_for_memref_p (x, y)
- rtx x, y;
- {
- register int i;
- register int j;
- register enum rtx_code code;
- register char *fmt;
-
- if (x == 0 && y == 0)
- return 1;
- if (x == 0 || y == 0)
- return 0;
- x = canon_rtx (x);
- y = canon_rtx (y);
-
- if (x == y)
- return 1;
-
- code = GET_CODE (x);
- /* Rtx's of different codes cannot be equal. */
- if (code != GET_CODE (y))
- return 0;
-
- /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
- (REG:SI x) and (REG:HI x) are NOT equivalent. */
-
- if (GET_MODE (x) != GET_MODE (y))
- return 0;
-
- /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively. */
-
- if (code == REG)
- return REGNO (x) == REGNO (y);
- if (code == LABEL_REF)
- return XEXP (x, 0) == XEXP (y, 0);
- if (code == SYMBOL_REF)
- return XSTR (x, 0) == XSTR (y, 0);
-
- /* For commutative operations, the RTX match if the operand match in any
- order. Also handle the simple binary and unary cases without a loop. */
- if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
- return ((rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))
- && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1)))
- || (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 1))
- && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 0))));
- else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2')
- return (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))
- && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1)));
- else if (GET_RTX_CLASS (code) == '1')
- return rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0));
-
- /* Compare the elements. If any pair of corresponding elements
- fail to match, return 0 for the whole things. */
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- switch (fmt[i])
- {
- case 'w':
- if (XWINT (x, i) != XWINT (y, i))
- return 0;
- break;
-
- case 'n':
- case 'i':
- if (XINT (x, i) != XINT (y, i))
- return 0;
- break;
-
- case 'V':
- case 'E':
- /* Two vectors must have the same length. */
- if (XVECLEN (x, i) != XVECLEN (y, i))
- return 0;
-
- /* And the corresponding elements must match. */
- for (j = 0; j < XVECLEN (x, i); j++)
- if (rtx_equal_for_memref_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0)
- return 0;
- break;
-
- case 'e':
- if (rtx_equal_for_memref_p (XEXP (x, i), XEXP (y, i)) == 0)
- return 0;
- break;
-
- case 'S':
- case 's':
- if (strcmp (XSTR (x, i), XSTR (y, i)))
- return 0;
- break;
-
- case 'u':
- /* These are just backpointers, so they don't matter. */
- break;
-
- case '0':
- break;
-
- /* It is believed that rtx's at this level will never
- contain anything but integers and other rtx's,
- except for within LABEL_REFs and SYMBOL_REFs. */
- default:
- abort ();
- }
- }
- return 1;
- }
-
- /* Given an rtx X, find a SYMBOL_REF or LABEL_REF within
- X and return it, or return 0 if none found. */
-
- static rtx
- find_symbolic_term (x)
- rtx x;
- {
- register int i;
- register enum rtx_code code;
- register char *fmt;
-
- code = GET_CODE (x);
- if (code == SYMBOL_REF || code == LABEL_REF)
- return x;
- if (GET_RTX_CLASS (code) == 'o')
- return 0;
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- rtx t;
-
- if (fmt[i] == 'e')
- {
- t = find_symbolic_term (XEXP (x, i));
- if (t != 0)
- return t;
- }
- else if (fmt[i] == 'E')
- break;
- }
- return 0;
- }
-
- /* Return nonzero if X and Y (memory addresses) could reference the
- same location in memory. C is an offset accumulator. When
- C is nonzero, we are testing aliases between X and Y + C.
- XSIZE is the size in bytes of the X reference,
- similarly YSIZE is the size in bytes for Y.
-
- If XSIZE or YSIZE is zero, we do not know the amount of memory being
- referenced (the reference was BLKmode), so make the most pessimistic
- assumptions.
-
- We recognize the following cases of non-conflicting memory:
-
- (1) addresses involving the frame pointer cannot conflict
- with addresses involving static variables.
- (2) static variables with different addresses cannot conflict.
-
- Nice to notice that varying addresses cannot conflict with fp if no
- local variables had their addresses taken, but that's too hard now. */
-
- /* ??? In Fortran, references to a array parameter can never conflict with
- another array parameter. */
-
- static int
- memrefs_conflict_p (xsize, x, ysize, y, c)
- rtx x, y;
- int xsize, ysize;
- HOST_WIDE_INT c;
- {
- if (GET_CODE (x) == HIGH)
- x = XEXP (x, 0);
- else if (GET_CODE (x) == LO_SUM)
- x = XEXP (x, 1);
- else
- x = canon_rtx (x);
- if (GET_CODE (y) == HIGH)
- y = XEXP (y, 0);
- else if (GET_CODE (y) == LO_SUM)
- y = XEXP (y, 1);
- else
- y = canon_rtx (y);
-
- if (rtx_equal_for_memref_p (x, y))
- return (xsize == 0 || ysize == 0 ||
- (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
-
- if (y == frame_pointer_rtx || y == hard_frame_pointer_rtx
- || y == stack_pointer_rtx)
- {
- rtx t = y;
- int tsize = ysize;
- y = x; ysize = xsize;
- x = t; xsize = tsize;
- }
-
- if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
- || x == stack_pointer_rtx)
- {
- rtx y1;
-
- if (CONSTANT_P (y))
- return 0;
-
- if (GET_CODE (y) == PLUS
- && canon_rtx (XEXP (y, 0)) == x
- && (y1 = canon_rtx (XEXP (y, 1)))
- && GET_CODE (y1) == CONST_INT)
- {
- c += INTVAL (y1);
- return (xsize == 0 || ysize == 0
- || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
- }
-
- if (GET_CODE (y) == PLUS
- && (y1 = canon_rtx (XEXP (y, 0)))
- && CONSTANT_P (y1))
- return 0;
-
- return 1;
- }
-
- if (GET_CODE (x) == PLUS)
- {
- /* The fact that X is canonicalized means that this
- PLUS rtx is canonicalized. */
- rtx x0 = XEXP (x, 0);
- rtx x1 = XEXP (x, 1);
-
- if (GET_CODE (y) == PLUS)
- {
- /* The fact that Y is canonicalized means that this
- PLUS rtx is canonicalized. */
- rtx y0 = XEXP (y, 0);
- rtx y1 = XEXP (y, 1);
-
- if (rtx_equal_for_memref_p (x1, y1))
- return memrefs_conflict_p (xsize, x0, ysize, y0, c);
- if (rtx_equal_for_memref_p (x0, y0))
- return memrefs_conflict_p (xsize, x1, ysize, y1, c);
- if (GET_CODE (x1) == CONST_INT)
- if (GET_CODE (y1) == CONST_INT)
- return memrefs_conflict_p (xsize, x0, ysize, y0,
- c - INTVAL (x1) + INTVAL (y1));
- else
- return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
- else if (GET_CODE (y1) == CONST_INT)
- return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
-
- /* Handle case where we cannot understand iteration operators,
- but we notice that the base addresses are distinct objects. */
- x = find_symbolic_term (x);
- if (x == 0)
- return 1;
- y = find_symbolic_term (y);
- if (y == 0)
- return 1;
- return rtx_equal_for_memref_p (x, y);
- }
- else if (GET_CODE (x1) == CONST_INT)
- return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
- }
- else if (GET_CODE (y) == PLUS)
- {
- /* The fact that Y is canonicalized means that this
- PLUS rtx is canonicalized. */
- rtx y0 = XEXP (y, 0);
- rtx y1 = XEXP (y, 1);
-
- if (GET_CODE (y1) == CONST_INT)
- return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
- else
- return 1;
- }
-
- if (GET_CODE (x) == GET_CODE (y))
- switch (GET_CODE (x))
- {
- case MULT:
- {
- /* Handle cases where we expect the second operands to be the
- same, and check only whether the first operand would conflict
- or not. */
- rtx x0, y0;
- rtx x1 = canon_rtx (XEXP (x, 1));
- rtx y1 = canon_rtx (XEXP (y, 1));
- if (! rtx_equal_for_memref_p (x1, y1))
- return 1;
- x0 = canon_rtx (XEXP (x, 0));
- y0 = canon_rtx (XEXP (y, 0));
- if (rtx_equal_for_memref_p (x0, y0))
- return (xsize == 0 || ysize == 0
- || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
-
- /* Can't properly adjust our sizes. */
- if (GET_CODE (x1) != CONST_INT)
- return 1;
- xsize /= INTVAL (x1);
- ysize /= INTVAL (x1);
- c /= INTVAL (x1);
- return memrefs_conflict_p (xsize, x0, ysize, y0, c);
- }
- }
-
- if (CONSTANT_P (x))
- {
- if (GET_CODE (x) == CONST_INT && GET_CODE (y) == CONST_INT)
- {
- c += (INTVAL (y) - INTVAL (x));
- return (xsize == 0 || ysize == 0
- || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
- }
-
- if (GET_CODE (x) == CONST)
- {
- if (GET_CODE (y) == CONST)
- return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),
- ysize, canon_rtx (XEXP (y, 0)), c);
- else
- return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),
- ysize, y, c);
- }
- if (GET_CODE (y) == CONST)
- return memrefs_conflict_p (xsize, x, ysize,
- canon_rtx (XEXP (y, 0)), c);
-
- if (CONSTANT_P (y))
- return (rtx_equal_for_memref_p (x, y)
- && (xsize == 0 || ysize == 0
- || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)));
-
- return 1;
- }
- return 1;
- }
-
- /* Functions to compute memory dependencies.
-
- Since we process the insns in execution order, we can build tables
- to keep track of what registers are fixed (and not aliased), what registers
- are varying in known ways, and what registers are varying in unknown
- ways.
-
- If both memory references are volatile, then there must always be a
- dependence between the two references, since their order can not be
- changed. A volatile and non-volatile reference can be interchanged
- though.
-
- A MEM_IN_STRUCT reference at a non-QImode varying address can never
- conflict with a non-MEM_IN_STRUCT reference at a fixed address. We must
- allow QImode aliasing because the ANSI C standard allows character
- pointers to alias anything. We are assuming that characters are
- always QImode here. */
-
- /* Read dependence: X is read after read in MEM takes place. There can
- only be a dependence here if both reads are volatile. */
-
- int
- read_dependence (mem, x)
- rtx mem;
- rtx x;
- {
- return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem);
- }
-
- /* True dependence: X is read after store in MEM takes place. */
-
- int
- true_dependence (mem, x)
- rtx mem;
- rtx x;
- {
- /* If X is an unchanging read, then it can't possibly conflict with any
- non-unchanging store. It may conflict with an unchanging write though,
- because there may be a single store to this address to initialize it.
- Just fall through to the code below to resolve the case where we have
- both an unchanging read and an unchanging write. This won't handle all
- cases optimally, but the possible performance loss should be
- negligible. */
- if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
- return 0;
-
- return ((MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
- || (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
- SIZE_FOR_MODE (x), XEXP (x, 0), 0)
- && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
- && GET_MODE (mem) != QImode
- && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
- && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
- && GET_MODE (x) != QImode
- && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem))));
- }
-
- /* Anti dependence: X is written after read in MEM takes place. */
-
- int
- anti_dependence (mem, x)
- rtx mem;
- rtx x;
- {
- /* If MEM is an unchanging read, then it can't possibly conflict with
- the store to X, because there is at most one store to MEM, and it must
- have occurred somewhere before MEM. */
- if (RTX_UNCHANGING_P (mem))
- return 0;
-
- return ((MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
- || (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
- SIZE_FOR_MODE (x), XEXP (x, 0), 0)
- && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
- && GET_MODE (mem) != QImode
- && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
- && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
- && GET_MODE (x) != QImode
- && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem))));
- }
-
- /* Output dependence: X is written after store in MEM takes place. */
-
- int
- output_dependence (mem, x)
- rtx mem;
- rtx x;
- {
- return ((MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
- || (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
- SIZE_FOR_MODE (x), XEXP (x, 0), 0)
- && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
- && GET_MODE (mem) != QImode
- && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
- && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
- && GET_MODE (x) != QImode
- && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem))));
- }
-
/* Helper functions for instruction scheduling. */
--- 345,348 ----
*************** add_insn_mem_dependence (insn_list, mem_
*** 1609,1621 ****
/* Make a dependency between every memory reference on the pending lists
! and INSN, thus flushing the pending lists. */
static void
! flush_pending_lists (insn)
rtx insn;
{
rtx link;
! while (pending_read_insns)
{
add_dependence (insn, XEXP (pending_read_insns, 0), REG_DEP_ANTI);
--- 1072,1086 ----
/* Make a dependency between every memory reference on the pending lists
! and INSN, thus flushing the pending lists. If ONLY_WRITE, don't flush
! the read list. */
static void
! flush_pending_lists (insn, only_write)
rtx insn;
+ int only_write;
{
rtx link;
! while (pending_read_insns && ! only_write)
{
add_dependence (insn, XEXP (pending_read_insns, 0), REG_DEP_ANTI);
*************** sched_analyze_1 (x, insn)
*** 1746,1750 ****
this flush occurs 8 times for sparc, and 10 times for m88k using
the number 32. */
! flush_pending_lists (insn);
}
else
--- 1211,1215 ----
this flush occurs 8 times for sparc, and 10 times for m88k using
the number 32. */
! flush_pending_lists (insn, 0);
}
else
*************** sched_analyze_2 (x, insn)
*** 1922,1926 ****
/* If a dependency already exists, don't create a new one. */
if (! find_insn_list (XEXP (pending, 0), LOG_LINKS (insn)))
! if (true_dependence (XEXP (pending_mem, 0), x))
add_dependence (insn, XEXP (pending, 0), 0);
--- 1387,1392 ----
/* If a dependency already exists, don't create a new one. */
if (! find_insn_list (XEXP (pending, 0), LOG_LINKS (insn)))
! if (true_dependence (XEXP (pending_mem, 0), VOIDmode,
! x, rtx_varies_p))
add_dependence (insn, XEXP (pending, 0), 0);
*************** sched_analyze_2 (x, insn)
*** 1968,1972 ****
reg_pending_sets_all = 1;
! flush_pending_lists (insn);
}
--- 1434,1438 ----
reg_pending_sets_all = 1;
! flush_pending_lists (insn, 0);
}
*************** sched_analyze_insn (x, insn, loop_notes)
*** 2021,2025 ****
register RTX_CODE code = GET_CODE (x);
rtx link;
! int maxreg = max_reg_num ();
int i;
--- 1487,1491 ----
register RTX_CODE code = GET_CODE (x);
rtx link;
! int maxreg = reg_last_uses_size;
int i;
*************** sched_analyze_insn (x, insn, loop_notes)
*** 2058,2062 ****
if (loop_notes)
{
! int max_reg = max_reg_num ();
rtx link;
--- 1524,1528 ----
if (loop_notes)
{
! int max_reg = reg_last_uses_size;
rtx link;
*************** sched_analyze_insn (x, insn, loop_notes)
*** 2072,2076 ****
reg_pending_sets_all = 1;
! flush_pending_lists (insn);
link = loop_notes;
--- 1538,1542 ----
reg_pending_sets_all = 1;
! flush_pending_lists (insn, 0);
link = loop_notes;
*************** sched_analyze (head, tail)
*** 2202,2207 ****
&& NOTE_LINE_NUMBER (NEXT_INSN (insn)) == NOTE_INSN_SETJMP)
{
! int max_reg = max_reg_num ();
! for (i = 0; i < max_reg; i++)
{
for (u = reg_last_uses[i]; u; u = XEXP (u, 1))
--- 1668,1672 ----
&& NOTE_LINE_NUMBER (NEXT_INSN (insn)) == NOTE_INSN_SETJMP)
{
! for (i = 0; i < reg_last_uses_size; i++)
{
for (u = reg_last_uses[i]; u; u = XEXP (u, 1))
*************** sched_analyze (head, tail)
*** 2247,2259 ****
loop_notes = 0;
! /* We don't need to flush memory for a function call which does
! not involve memory. */
! if (! CONST_CALL_P (insn))
! {
! /* In the absence of interprocedural alias analysis,
! we must flush all pending reads and writes, and
! start new dependencies starting from here. */
! flush_pending_lists (insn);
! }
/* Depend this function call (actually, the user of this
--- 1712,1720 ----
loop_notes = 0;
! /* In the absence of interprocedural alias analysis, we must flush
! all pending reads and writes, and start new dependencies starting
! from here. But only flush writes for constant calls (which may
! be passed a pointer to something we haven't written yet). */
! flush_pending_lists (insn, CONST_CALL_P (insn));
/* Depend this function call (actually, the user of this
*************** sched_analyze (head, tail)
*** 2264,2270 ****
else if (GET_CODE (insn) == NOTE
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
! || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
! loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
! GEN_INT (NOTE_LINE_NUMBER (insn)), loop_notes);
if (insn == tail)
--- 1725,1736 ----
else if (GET_CODE (insn) == NOTE
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
! || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
! || (NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP
! && GET_CODE (PREV_INSN (insn)) != CALL_INSN)))
! {
! loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
! GEN_INT (NOTE_LINE_NUMBER (insn)), loop_notes);
! CONST_CALL_P (loop_notes) = CONST_CALL_P (insn);
! }
if (insn == tail)
*************** sched_note_set (b, x, death)
*** 2372,2380 ****
#define SCHED_SORT(READY, NEW_READY, OLD_READY) \
! do { if ((NEW_READY) - (OLD_READY) == 1) \
! swap_sort (READY, NEW_READY); \
! else if ((NEW_READY) - (OLD_READY) > 1) \
! qsort (READY, NEW_READY, sizeof (rtx), rank_for_schedule); } \
! while (0)
/* Returns a positive value if y is preferred; returns a negative value if
--- 1838,1845 ----
#define SCHED_SORT(READY, NEW_READY, OLD_READY) \
! if ((NEW_READY) - (OLD_READY) == 1) \
! swap_sort (READY, NEW_READY); \
! else if ((NEW_READY) - (OLD_READY) > 1) \
! qsort (READY, NEW_READY, sizeof (rtx), rank_for_schedule); else \
/* Returns a positive value if y is preferred; returns a negative value if
*************** reemit_notes (insn, last)
*** 3128,3132 ****
{
if (INTVAL (XEXP (note, 0)) == NOTE_INSN_SETJMP)
! emit_note_after (INTVAL (XEXP (note, 0)), insn);
else
last = emit_note_before (INTVAL (XEXP (note, 0)), last);
--- 2593,2598 ----
{
if (INTVAL (XEXP (note, 0)) == NOTE_INSN_SETJMP)
! CONST_CALL_P (emit_note_after (INTVAL (XEXP (note, 0)), insn))
! = CONST_CALL_P (note);
else
last = emit_note_before (INTVAL (XEXP (note, 0)), last);
*************** schedule_block (b, file)
*** 3174,3178 ****
b, INSN_UID (basic_block_head[b]), INSN_UID (basic_block_end[b]));
! i = max_reg_num ();
reg_last_uses = (rtx *) alloca (i * sizeof (rtx));
bzero ((char *) reg_last_uses, i * sizeof (rtx));
--- 2640,2644 ----
b, INSN_UID (basic_block_head[b]), INSN_UID (basic_block_end[b]));
! reg_last_uses_size = i = max_reg_num ();
reg_last_uses = (rtx *) alloca (i * sizeof (rtx));
bzero ((char *) reg_last_uses, i * sizeof (rtx));
*************** schedule_block (b, file)
*** 3800,3804 ****
made live again later. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! if (call_used_regs[i] || global_regs[i])
{
register int offset = i / REGSET_ELT_BITS;
--- 3266,3271 ----
made live again later. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
! if ((call_used_regs[i] && ! fixed_regs[i])
! || global_regs[i])
{
register int offset = i / REGSET_ELT_BITS;
*************** schedule_insns (dump_file)
*** 4717,4721 ****
bcopy ((char *) reg_n_deaths, (char *) sched_reg_n_deaths,
max_regno * sizeof (short));
- init_alias_analysis ();
}
else
--- 4184,4187 ----
*************** schedule_insns (dump_file)
*** 4726,4732 ****
bb_dead_regs = 0;
bb_live_regs = 0;
- if (! flag_schedule_insns)
- init_alias_analysis ();
}
if (write_symbols != NO_DEBUG)
--- 4192,4213 ----
bb_dead_regs = 0;
bb_live_regs = 0;
}
+ init_alias_analysis ();
+ #if 0
+ if (dump_file)
+ {
+ extern rtx *reg_base_value;
+ extern int reg_base_value_size;
+ int i;
+ for (i = 0; i < reg_base_value_size; i++)
+ if (reg_base_value[i])
+ {
+ fprintf (dump_file, ";; reg_base_value[%d] = ", i);
+ print_rtl (dump_file, reg_base_value[i]);
+ fputc ('\n', dump_file);
+ }
+ }
+ #endif
+
if (write_symbols != NO_DEBUG)
diff -rcp2N gcc-2.7.2.2/sdbout.c g77-new/sdbout.c
*** gcc-2.7.2.2/sdbout.c Thu Jun 15 08:07:11 1995
--- g77-new/sdbout.c Mon Aug 11 01:42:22 1997
*************** plain_type_1 (type, level)
*** 539,543 ****
sdb_dims[sdb_n_dims++]
= (TYPE_DOMAIN (type)
! ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1
: 0);
return PUSH_DERIVED_LEVEL (DT_ARY, m);
--- 539,546 ----
sdb_dims[sdb_n_dims++]
= (TYPE_DOMAIN (type)
! && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
! && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
! ? (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
! - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1)
: 0);
return PUSH_DERIVED_LEVEL (DT_ARY, m);
diff -rcp2N gcc-2.7.2.2/stmt.c g77-new/stmt.c
*** gcc-2.7.2.2/stmt.c Tue Sep 12 19:01:54 1995
--- g77-new/stmt.c Sun Aug 10 18:46:56 1997
*************** fixup_gotos (thisblock, stack_level, cle
*** 1244,1249 ****
poplevel (1, 0, 0);
end_sequence ();
! f->before_jump
! = emit_insns_after (cleanup_insns, f->before_jump);
f->cleanup_list_list = TREE_CHAIN (lists);
--- 1244,1250 ----
poplevel (1, 0, 0);
end_sequence ();
! if (cleanup_insns != 0)
! f->before_jump
! = emit_insns_after (cleanup_insns, f->before_jump);
f->cleanup_list_list = TREE_CHAIN (lists);
*************** expand_expr_stmt (exp)
*** 1721,1725 ****
last_expr_type = TREE_TYPE (exp);
! if (! flag_syntax_only)
last_expr_value = expand_expr (exp,
(expr_stmts_for_value
--- 1722,1726 ----
last_expr_type = TREE_TYPE (exp);
! if (! flag_syntax_only || expr_stmts_for_value)
last_expr_value = expand_expr (exp,
(expr_stmts_for_value
*************** expand_end_bindings (vars, mark_ends, do
*** 3160,3163 ****
--- 3161,3169 ----
#endif
+ #ifdef HAVE_nonlocal_goto_receiver
+ if (HAVE_nonlocal_goto_receiver)
+ emit_insn (gen_nonlocal_goto_receiver ());
+ #endif
+
/* The handler expects the desired label address in the static chain
register. It tests the address and does an appropriate jump
*************** expand_decl (decl)
*** 3369,3393 ****
= promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
! if (TREE_CODE (type) == COMPLEX_TYPE)
! {
! rtx realpart, imagpart;
! enum machine_mode partmode = TYPE_MODE (TREE_TYPE (type));
! /* For a complex type variable, make a CONCAT of two pseudos
! so that the real and imaginary parts
! can be allocated separately. */
! realpart = gen_reg_rtx (partmode);
! REG_USERVAR_P (realpart) = 1;
! imagpart = gen_reg_rtx (partmode);
! REG_USERVAR_P (imagpart) = 1;
! DECL_RTL (decl) = gen_rtx (CONCAT, reg_mode, realpart, imagpart);
! }
! else
! {
! DECL_RTL (decl) = gen_reg_rtx (reg_mode);
! if (TREE_CODE (type) == POINTER_TYPE)
! mark_reg_pointer (DECL_RTL (decl));
! REG_USERVAR_P (DECL_RTL (decl)) = 1;
! }
}
else if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
--- 3375,3383 ----
= promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
! DECL_RTL (decl) = gen_reg_rtx (reg_mode);
! mark_user_reg (DECL_RTL (decl));
! if (TREE_CODE (type) == POINTER_TYPE)
! mark_reg_pointer (DECL_RTL (decl));
}
else if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
*************** expand_decl (decl)
*** 3462,3468 ****
free_temp_slots ();
! /* Allocate space on the stack for the variable. */
address = allocate_dynamic_stack_space (size, NULL_RTX,
! DECL_ALIGN (decl));
/* Reference the variable indirect through that rtx. */
--- 3452,3461 ----
free_temp_slots ();
! /* Allocate space on the stack for the variable. Note that
! DECL_ALIGN says how the variable is to be aligned and we
! cannot use it to conclude anything about the alignment of
! the size. */
address = allocate_dynamic_stack_space (size, NULL_RTX,
! TYPE_ALIGN (TREE_TYPE (decl)));
/* Reference the variable indirect through that rtx. */
diff -rcp2N gcc-2.7.2.2/stor-layout.c g77-new/stor-layout.c
*** gcc-2.7.2.2/stor-layout.c Thu Feb 20 19:24:20 1997
--- g77-new/stor-layout.c Mon Aug 11 06:47:50 1997
*************** layout_decl (decl, known_align)
*** 255,259 ****
if (maximum_field_alignment != 0)
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
! else if (flag_pack_struct)
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
}
--- 255,259 ----
if (maximum_field_alignment != 0)
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
! else if (DECL_PACKED (decl))
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
}
*************** layout_decl (decl, known_align)
*** 261,265 ****
if (DECL_BIT_FIELD (decl)
&& TYPE_SIZE (type) != 0
! && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
register enum machine_mode xmode
--- 261,266 ----
if (DECL_BIT_FIELD (decl)
&& TYPE_SIZE (type) != 0
! && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
! && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
{
register enum machine_mode xmode
*************** layout_decl (decl, known_align)
*** 278,281 ****
--- 279,291 ----
}
+ /* Turn off DECL_BIT_FIELD if we won't need it set. */
+ if (DECL_BIT_FIELD (decl) && TYPE_MODE (type) == BLKmode
+ && known_align % TYPE_ALIGN (type) == 0
+ && DECL_SIZE (decl) != 0
+ && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST
+ || (TREE_INT_CST_LOW (DECL_SIZE (decl)) % BITS_PER_UNIT) == 0)
+ && DECL_ALIGN (decl) >= TYPE_ALIGN (type))
+ DECL_BIT_FIELD (decl) = 0;
+
/* Evaluate nonconstant size only once, either now or as soon as safe. */
if (DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
*************** layout_record (rec)
*** 380,384 ****
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
! else if (flag_pack_struct)
type_align = MIN (type_align, BITS_PER_UNIT);
--- 390,394 ----
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
! else if (TYPE_PACKED (rec))
type_align = MIN (type_align, BITS_PER_UNIT);
*************** layout_record (rec)
*** 422,428 ****
&& DECL_BIT_FIELD_TYPE (field)
&& !DECL_PACKED (field)
- /* If #pragma pack is in effect, turn off this feature. */
&& maximum_field_alignment == 0
- && !flag_pack_struct
&& !integer_zerop (DECL_SIZE (field)))
{
--- 432,436 ----
*************** layout_record (rec)
*** 459,463 ****
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
! else if (flag_pack_struct)
type_align = MIN (type_align, BITS_PER_UNIT);
--- 467,471 ----
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
! else if (TYPE_PACKED (rec))
type_align = MIN (type_align, BITS_PER_UNIT);
*************** layout_record (rec)
*** 500,505 ****
/* Do nothing. */;
else if (TREE_CODE (dsize) == INTEGER_CST
&& TREE_INT_CST_HIGH (dsize) == 0
! && TREE_INT_CST_LOW (dsize) + const_size > const_size)
/* Use const_size if there's no overflow. */
const_size += TREE_INT_CST_LOW (dsize);
--- 508,514 ----
/* Do nothing. */;
else if (TREE_CODE (dsize) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (dsize)
&& TREE_INT_CST_HIGH (dsize) == 0
! && TREE_INT_CST_LOW (dsize) + const_size >= const_size)
/* Use const_size if there's no overflow. */
const_size += TREE_INT_CST_LOW (dsize);
*************** get_best_mode (bitsize, bitpos, align, l
*** 1172,1175 ****
--- 1181,1192 ----
enum machine_mode mode;
int unit;
+
+ if (bitpos < 0)
+ {
+ /* For correct calculations and convenience, bias negative bitpos
+ to become a non-negative value that is [1,bitsize], such that
+ the relative bit offset to a multiple of bitsize is preserved. */
+ bitpos = bitsize - ((-bitpos) % bitsize);
+ }
/* Find the narrowest integer mode that contains the bit field. */
diff -rcp2N gcc-2.7.2.2/stupid.c g77-new/stupid.c
*** gcc-2.7.2.2/stupid.c Sun Oct 29 07:45:22 1995
--- g77-new/stupid.c Sun Aug 10 18:46:01 1997
*************** static int *uid_suid;
*** 66,69 ****
--- 66,74 ----
static int last_call_suid;
+ /* Record the suid of the last NOTE_INSN_SETJMP
+ so we can tell whether a pseudo reg crosses any setjmp. */
+
+ static int last_setjmp_suid;
+
/* Element N is suid of insn where life span of pseudo reg N ends.
Element is 0 if register N has not been seen yet on backward scan. */
*************** static char *regs_live;
*** 89,92 ****
--- 94,101 ----
static char *regs_change_size;
+ /* Indexed by reg number, nonzero if reg crosses a setjmp. */
+
+ static char *regs_crosses_setjmp;
+
/* Indexed by insn's suid, the set of hard regs live after that insn. */
*************** stupid_life_analysis (f, nregs, file)
*** 149,152 ****
--- 158,162 ----
last_call_suid = i + 1;
+ last_setjmp_suid = i + 1;
max_suid = i + 1;
*************** stupid_life_analysis (f, nregs, file)
*** 167,170 ****
--- 177,183 ----
bzero ((char *) regs_change_size, nregs * sizeof (char));
+ regs_crosses_setjmp = (char *) alloca (nregs * sizeof (char));
+ bzero ((char *) regs_crosses_setjmp, nregs * sizeof (char));
+
reg_renumber = (short *) oballoc (nregs * sizeof (short));
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
*************** stupid_life_analysis (f, nregs, file)
*** 216,219 ****
--- 229,236 ----
stupid_mark_refs (PATTERN (insn), insn);
+ if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
+ last_setjmp_suid = INSN_SUID (insn);
+
/* Mark all call-clobbered regs as live after each call insn
so that a pseudo whose life span includes this insn
*************** stupid_life_analysis (f, nregs, file)
*** 254,259 ****
register int r = reg_order[i];
! /* Some regnos disappear from the rtl. Ignore them to avoid crash. */
! if (regno_reg_rtx[r] == 0)
continue;
--- 271,277 ----
register int r = reg_order[i];
! /* Some regnos disappear from the rtl. Ignore them to avoid crash.
! Also don't allocate registers that cross a setjmp. */
! if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r])
continue;
*************** stupid_reg_compare (r1p, r2p)
*** 309,314 ****
that can hold a value of machine-mode MODE
(but actually we test only the first of the block for holding MODE)
! currently free from after insn whose suid is BIRTH
! through the insn whose suid is DEATH,
and return the number of the first of them.
Return -1 if such a block cannot be found.
--- 327,332 ----
that can hold a value of machine-mode MODE
(but actually we test only the first of the block for holding MODE)
! currently free from after insn whose suid is BORN_INSN
! through the insn whose suid is DEAD_INSN,
and return the number of the first of them.
Return -1 if such a block cannot be found.
*************** stupid_find_reg (call_preserved, class,
*** 338,341 ****
--- 356,366 ----
#endif
+ /* If this register's life is more than 5,000 insns, we probably
+ can't allocate it, so don't waste the time trying. This avoid
+ quadratic behavior on programs that have regularly-occurring
+ SAVE_EXPRs. */
+ if (dead_insn > born_insn + 5000)
+ return -1;
+
COPY_HARD_REG_SET (used,
call_preserved ? call_used_reg_set : fixed_reg_set);
*************** stupid_mark_refs (x, insn)
*** 488,491 ****
--- 513,519 ----
if (last_call_suid < reg_where_dead[regno])
reg_n_calls_crossed[regno] += 1;
+
+ if (last_setjmp_suid < reg_where_dead[regno])
+ regs_crosses_setjmp[regno] = 1;
}
}
diff -rcp2N gcc-2.7.2.2/toplev.c g77-new/toplev.c
*** gcc-2.7.2.2/toplev.c Fri Oct 20 17:56:35 1995
--- g77-new/toplev.c Sun Aug 10 18:43:36 1997
*************** int flag_unroll_loops;
*** 388,391 ****
--- 388,405 ----
int flag_unroll_all_loops;
+ /* Nonzero forces all invariant computations in loops to be moved
+ outside the loop. */
+
+ int flag_move_all_movables = 0;
+
+ /* Nonzero forces all general induction variables in loops to be
+ strength reduced. */
+
+ int flag_reduce_all_givs = 0;
+
+ /* Nonzero gets another run of loop_optimize performed. */
+
+ int flag_rerun_loop_opt = 0;
+
/* Nonzero for -fwritable-strings:
store string constants in data segment and don't uniquize them. */
*************** int flag_gnu_linker = 1;
*** 522,525 ****
--- 536,550 ----
int flag_pack_struct = 0;
+ /* 1 if alias checking is on (by default, when -O). */
+ int flag_alias_check = 0;
+
+ /* 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.
+ This defaults to 0 for C. */
+ int flag_argument_noalias = 0;
+
/* Table of language-independent -f options.
STRING is the option name. VARIABLE is the address of the variable.
*************** struct { char *string; int *variable; in
*** 542,545 ****
--- 567,573 ----
{"unroll-loops", &flag_unroll_loops, 1},
{"unroll-all-loops", &flag_unroll_all_loops, 1},
+ {"move-all-movables", &flag_move_all_movables, 1},
+ {"reduce-all-givs", &flag_reduce_all_givs, 1},
+ {"rerun-loop-opt", &flag_rerun_loop_opt, 1},
{"writable-strings", &flag_writable_strings, 1},
{"peephole", &flag_no_peephole, 0},
*************** struct { char *string; int *variable; in
*** 568,572 ****
{"gnu-linker", &flag_gnu_linker, 1},
{"pack-struct", &flag_pack_struct, 1},
! {"bytecode", &output_bytecode, 1}
};
--- 596,604 ----
{"gnu-linker", &flag_gnu_linker, 1},
{"pack-struct", &flag_pack_struct, 1},
! {"bytecode", &output_bytecode, 1},
! {"alias-check", &flag_alias_check, 1},
! {"argument-alias", &flag_argument_noalias, 0},
! {"argument-noalias", &flag_argument_noalias, 1},
! {"argument-noalias-global", &flag_argument_noalias, 2}
};
*************** rest_of_compilation (decl)
*** 2715,2725 ****
finish_compilation will call rest_of_compilation again
for those functions that need to be output. Also defer those
! functions that we are supposed to defer. */
!
! if (DECL_DEFER_OUTPUT (decl)
! || ((specd || DECL_INLINE (decl))
! && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
! && ! flag_keep_inline_functions)
! || DECL_EXTERNAL (decl))))
{
DECL_DEFER_OUTPUT (decl) = 1;
--- 2747,2760 ----
finish_compilation will call rest_of_compilation again
for those functions that need to be output. Also defer those
! functions that we are supposed to defer. We cannot defer
! functions containing nested functions since the nested function
! data is in our non-saved obstack. */
!
! if (! current_function_contains_functions
! && (DECL_DEFER_OUTPUT (decl)
! || ((specd || DECL_INLINE (decl))
! && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
! && ! flag_keep_inline_functions)
! || DECL_EXTERNAL (decl)))))
{
DECL_DEFER_OUTPUT (decl) = 1;
*************** rest_of_compilation (decl)
*** 2893,2897 ****
--- 2928,2951 ----
TIMEVAR (loop_time,
{
+ int save_unroll_flag;
+ int save_unroll_all_flag;
+
+ if (flag_rerun_loop_opt)
+ {
+ save_unroll_flag = flag_unroll_loops;
+ save_unroll_all_flag = flag_unroll_all_loops;
+ flag_unroll_loops = 0;
+ flag_unroll_all_loops = 0;
+ }
+
loop_optimize (insns, loop_dump_file);
+
+ if (flag_rerun_loop_opt)
+ {
+ flag_unroll_loops = save_unroll_flag;
+ flag_unroll_all_loops = save_unroll_all_flag;
+
+ loop_optimize (insns, loop_dump_file);
+ }
});
}
*************** rest_of_compilation (decl)
*** 3280,3283 ****
--- 3334,3341 ----
resume_temporary_allocation ();
+ /* Show no temporary slots allocated. */
+
+ init_temp_slots ();
+
/* The parsing time is all the time spent in yyparse
*except* what is spent in this function. */
*************** main (argc, argv, envp)
*** 3383,3386 ****
--- 3441,3445 ----
flag_omit_frame_pointer = 1;
#endif
+ flag_alias_check = 1;
}
diff -rcp2N gcc-2.7.2.2/tree.c g77-new/tree.c
*** gcc-2.7.2.2/tree.c Sun Oct 1 21:26:56 1995
--- g77-new/tree.c Sun Aug 10 18:47:23 1997
*************** build_string (len, str)
*** 1428,1436 ****
/* Return a newly constructed COMPLEX_CST node whose value is
specified by the real and imaginary parts REAL and IMAG.
! Both REAL and IMAG should be constant nodes.
! The TREE_TYPE is not initialized. */
tree
! build_complex (real, imag)
tree real, imag;
{
--- 1428,1437 ----
/* Return a newly constructed COMPLEX_CST node whose value is
specified by the real and imaginary parts REAL and IMAG.
! Both REAL and IMAG should be constant nodes. TYPE, if specified,
! will be the type of the COMPLEX_CST; otherwise a new type will be made. */
tree
! build_complex (type, real, imag)
! tree type;
tree real, imag;
{
*************** build_complex (real, imag)
*** 1439,1443 ****
TREE_REALPART (t) = real;
TREE_IMAGPART (t) = imag;
! TREE_TYPE (t) = build_complex_type (TREE_TYPE (real));
TREE_OVERFLOW (t) = TREE_OVERFLOW (real) | TREE_OVERFLOW (imag);
TREE_CONSTANT_OVERFLOW (t)
--- 1440,1444 ----
TREE_REALPART (t) = real;
TREE_IMAGPART (t) = imag;
! TREE_TYPE (t) = type ? type : build_complex_type (TREE_TYPE (real));
TREE_OVERFLOW (t) = TREE_OVERFLOW (real) | TREE_OVERFLOW (imag);
TREE_CONSTANT_OVERFLOW (t)
*************** integer_zerop (expr)
*** 1484,1487 ****
--- 1485,1489 ----
return ((TREE_CODE (expr) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (expr)
&& TREE_INT_CST_LOW (expr) == 0
&& TREE_INT_CST_HIGH (expr) == 0)
*************** integer_onep (expr)
*** 1501,1504 ****
--- 1503,1507 ----
return ((TREE_CODE (expr) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (expr)
&& TREE_INT_CST_LOW (expr) == 1
&& TREE_INT_CST_HIGH (expr) == 0)
*************** integer_all_onesp (expr)
*** 1525,1529 ****
return 1;
! else if (TREE_CODE (expr) != INTEGER_CST)
return 0;
--- 1528,1533 ----
return 1;
! else if (TREE_CODE (expr) != INTEGER_CST
! || TREE_CONSTANT_OVERFLOW (expr))
return 0;
*************** integer_pow2p (expr)
*** 1574,1578 ****
return 1;
! if (TREE_CODE (expr) != INTEGER_CST)
return 0;
--- 1578,1582 ----
return 1;
! if (TREE_CODE (expr) != INTEGER_CST || TREE_CONSTANT_OVERFLOW (expr))
return 0;
*************** real_zerop (expr)
*** 1596,1599 ****
--- 1600,1604 ----
return ((TREE_CODE (expr) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (expr)
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0))
|| (TREE_CODE (expr) == COMPLEX_CST
*************** real_onep (expr)
*** 1611,1614 ****
--- 1616,1620 ----
return ((TREE_CODE (expr) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (expr)
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1))
|| (TREE_CODE (expr) == COMPLEX_CST
*************** real_twop (expr)
*** 1626,1629 ****
--- 1632,1636 ----
return ((TREE_CODE (expr) == REAL_CST
+ && ! TREE_CONSTANT_OVERFLOW (expr)
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2))
|| (TREE_CODE (expr) == COMPLEX_CST
*************** staticp (arg)
*** 2055,2061 ****
return 1;
case COMPONENT_REF:
case BIT_FIELD_REF:
! return staticp (TREE_OPERAND (arg, 0));
#if 0
--- 2062,2073 ----
return 1;
+ /* If we are referencing a bitfield, we can't evaluate an
+ ADDR_EXPR at compile time and so it isn't a constant. */
case COMPONENT_REF:
+ return (! DECL_BIT_FIELD (TREE_OPERAND (arg, 1))
+ && staticp (TREE_OPERAND (arg, 0)));
+
case BIT_FIELD_REF:
! return 0;
#if 0
*************** contains_placeholder_p (exp)
*** 2157,2160 ****
--- 2169,2174 ----
if (code == WITH_RECORD_EXPR)
return 0;
+ else if (code == PLACEHOLDER_EXPR)
+ return 1;
switch (TREE_CODE_CLASS (code))
*************** substitute_in_expr (exp, f, r)
*** 2204,2207 ****
--- 2218,2222 ----
{
enum tree_code code = TREE_CODE (exp);
+ tree op0, op1, op2;
tree new = 0;
tree inner;
*************** substitute_in_expr (exp, f, r)
*** 2225,2231 ****
{
case 1:
! new = fold (build1 (code, TREE_TYPE (exp),
! substitute_in_expr (TREE_OPERAND (exp, 0),
! f, r)));
break;
--- 2240,2248 ----
{
case 1:
! op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
! if (op0 == TREE_OPERAND (exp, 0))
! return exp;
!
! new = fold (build1 (code, TREE_TYPE (exp), op0));
break;
*************** substitute_in_expr (exp, f, r)
*** 2238,2245 ****
abort ();
! new = fold (build (code, TREE_TYPE (exp),
! substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
! substitute_in_expr (TREE_OPERAND (exp, 1),
! f, r)));
break;
--- 2255,2264 ----
abort ();
! op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
! op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
! if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
! return exp;
!
! new = fold (build (code, TREE_TYPE (exp), op0, op1));
break;
*************** substitute_in_expr (exp, f, r)
*** 2253,2261 ****
abort ();
! new = fold (build (code, TREE_TYPE (exp),
! substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
! substitute_in_expr (TREE_OPERAND (exp, 1), f, r),
! substitute_in_expr (TREE_OPERAND (exp, 2),
! f, r)));
}
--- 2272,2283 ----
abort ();
! op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
! op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
! op2 = substitute_in_expr (TREE_OPERAND (exp, 2), f, r);
! if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
! && op2 == TREE_OPERAND (exp, 2))
! return exp;
!
! new = fold (build (code, TREE_TYPE (exp), op0, op1, op2));
}
*************** substitute_in_expr (exp, f, r)
*** 2276,2302 ****
return r;
! new = fold (build (code, TREE_TYPE (exp),
! substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
TREE_OPERAND (exp, 1)));
break;
case BIT_FIELD_REF:
! new = fold (build (code, TREE_TYPE (exp),
! substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
! substitute_in_expr (TREE_OPERAND (exp, 1), f, r),
! substitute_in_expr (TREE_OPERAND (exp, 2), f, r)));
break;
case INDIRECT_REF:
case BUFFER_REF:
! new = fold (build1 (code, TREE_TYPE (exp),
! substitute_in_expr (TREE_OPERAND (exp, 0),
! f, r)));
break;
case OFFSET_REF:
! new = fold (build (code, TREE_TYPE (exp),
! substitute_in_expr (TREE_OPERAND (exp, 0), f, r),
! substitute_in_expr (TREE_OPERAND (exp, 1), f, r)));
break;
}
--- 2298,2342 ----
return r;
! /* If this expression hasn't been completed let, leave it
! alone. */
! if (TREE_CODE (inner) == PLACEHOLDER_EXPR
! && TREE_TYPE (inner) == 0)
! return exp;
!
! op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
! if (op0 == TREE_OPERAND (exp, 0))
! return exp;
!
! new = fold (build (code, TREE_TYPE (exp), op0,
TREE_OPERAND (exp, 1)));
break;
case BIT_FIELD_REF:
! op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
! op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
! op2 = substitute_in_expr (TREE_OPERAND (exp, 2), f, r);
! if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
! && op2 == TREE_OPERAND (exp, 2))
! return exp;
!
! new = fold (build (code, TREE_TYPE (exp), op0, op1, op2));
break;
case INDIRECT_REF:
case BUFFER_REF:
! op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
! if (op0 == TREE_OPERAND (exp, 0))
! return exp;
!
! new = fold (build1 (code, TREE_TYPE (exp), op0));
break;
case OFFSET_REF:
! op0 = substitute_in_expr (TREE_OPERAND (exp, 0), f, r);
! op1 = substitute_in_expr (TREE_OPERAND (exp, 1), f, r);
! if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
! return exp;
!
! new = fold (build (code, TREE_TYPE (exp), op0, op1));
break;
}
*************** substitute_in_expr (exp, f, r)
*** 2311,2454 ****
}
- /* Given a type T, a FIELD_DECL F, and a replacement value R,
- return a new type with all size expressions that contain F
- updated by replacing F with R. */
-
- tree
- substitute_in_type (t, f, r)
- tree t, f, r;
- {
- switch (TREE_CODE (t))
- {
- case POINTER_TYPE:
- case VOID_TYPE:
- return t;
- case INTEGER_TYPE:
- case ENUMERAL_TYPE:
- case BOOLEAN_TYPE:
- case CHAR_TYPE:
- if ((TREE_CODE (TYPE_MIN_VALUE (t)) != INTEGER_CST
- && contains_placeholder_p (TYPE_MIN_VALUE (t)))
- || (TREE_CODE (TYPE_MAX_VALUE (t)) != INTEGER_CST
- && contains_placeholder_p (TYPE_MAX_VALUE (t))))
- return build_range_type (t,
- substitute_in_expr (TYPE_MIN_VALUE (t), f, r),
- substitute_in_expr (TYPE_MAX_VALUE (t), f, r));
- return t;
-
- case REAL_TYPE:
- if ((TYPE_MIN_VALUE (t) != 0
- && TREE_CODE (TYPE_MIN_VALUE (t)) != REAL_CST
- && contains_placeholder_p (TYPE_MIN_VALUE (t)))
- || (TYPE_MAX_VALUE (t) != 0
- && TREE_CODE (TYPE_MAX_VALUE (t)) != REAL_CST
- && contains_placeholder_p (TYPE_MAX_VALUE (t))))
- {
- t = build_type_copy (t);
-
- if (TYPE_MIN_VALUE (t))
- TYPE_MIN_VALUE (t) = substitute_in_expr (TYPE_MIN_VALUE (t), f, r);
- if (TYPE_MAX_VALUE (t))
- TYPE_MAX_VALUE (t) = substitute_in_expr (TYPE_MAX_VALUE (t), f, r);
- }
- return t;
-
- case COMPLEX_TYPE:
- return build_complex_type (substitute_in_type (TREE_TYPE (t), f, r));
-
- case OFFSET_TYPE:
- case METHOD_TYPE:
- case REFERENCE_TYPE:
- case FILE_TYPE:
- case SET_TYPE:
- case FUNCTION_TYPE:
- case LANG_TYPE:
- /* Don't know how to do these yet. */
- abort ();
-
- case ARRAY_TYPE:
- t = build_array_type (substitute_in_type (TREE_TYPE (t), f, r),
- substitute_in_type (TYPE_DOMAIN (t), f, r));
- TYPE_SIZE (t) = 0;
- layout_type (t);
- return t;
-
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- {
- tree new = copy_node (t);
- tree field;
- tree last_field = 0;
-
- /* Start out with no fields, make new fields, and chain them
- in. */
-
- TYPE_FIELDS (new) = 0;
- TYPE_SIZE (new) = 0;
-
- for (field = TYPE_FIELDS (t); field;
- field = TREE_CHAIN (field))
- {
- tree new_field = copy_node (field);
-
- TREE_TYPE (new_field)
- = substitute_in_type (TREE_TYPE (new_field), f, r);
-
- /* If this is an anonymous field and the type of this field is
- a UNION_TYPE or RECORD_TYPE with no elements, ignore it. If
- the type just has one element, treat that as the field.
- But don't do this if we are processing a QUAL_UNION_TYPE. */
- if (TREE_CODE (t) != QUAL_UNION_TYPE && DECL_NAME (new_field) == 0
- && (TREE_CODE (TREE_TYPE (new_field)) == UNION_TYPE
- || TREE_CODE (TREE_TYPE (new_field)) == RECORD_TYPE))
- {
- if (TYPE_FIELDS (TREE_TYPE (new_field)) == 0)
- continue;
-
- if (TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (new_field))) == 0)
- new_field = TYPE_FIELDS (TREE_TYPE (new_field));
- }
-
- DECL_CONTEXT (new_field) = new;
- DECL_SIZE (new_field) = 0;
-
- if (TREE_CODE (t) == QUAL_UNION_TYPE)
- {
- /* Do the substitution inside the qualifier and if we find
- that this field will not be present, omit it. */
- DECL_QUALIFIER (new_field)
- = substitute_in_expr (DECL_QUALIFIER (field), f, r);
- if (integer_zerop (DECL_QUALIFIER (new_field)))
- continue;
- }
-
- if (last_field == 0)
- TYPE_FIELDS (new) = new_field;
- else
- TREE_CHAIN (last_field) = new_field;
-
- last_field = new_field;
-
- /* If this is a qualified type and this field will always be
- present, we are done. */
- if (TREE_CODE (t) == QUAL_UNION_TYPE
- && integer_onep (DECL_QUALIFIER (new_field)))
- break;
- }
-
- /* If this used to be a qualified union type, but we now know what
- field will be present, make this a normal union. */
- if (TREE_CODE (new) == QUAL_UNION_TYPE
- && (TYPE_FIELDS (new) == 0
- || integer_onep (DECL_QUALIFIER (TYPE_FIELDS (new)))))
- TREE_SET_CODE (new, UNION_TYPE);
-
- layout_type (new);
- return new;
- }
- }
- }
-
/* Stabilize a reference so that we can use it any number of times
without causing its operands to be evaluated more than once.
--- 2351,2354 ----
*************** build_type_variant (type, constp, volati
*** 3141,3145 ****
preserve the TYPE_NAME, since there is code that depends on this. */
! for (t = TYPE_MAIN_VARIANT(type); t; t = TYPE_NEXT_VARIANT (t))
if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t)
&& TYPE_NAME (t) == TYPE_NAME (type))
--- 3041,3045 ----
preserve the TYPE_NAME, since there is code that depends on this. */
! for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (constp == TYPE_READONLY (t) && volatilep == TYPE_VOLATILE (t)
&& TYPE_NAME (t) == TYPE_NAME (type))
*************** get_unwidened (op, for_type)
*** 4051,4055 ****
if (TREE_CODE (op) == COMPONENT_REF
/* Since type_for_size always gives an integer type. */
! && TREE_CODE (type) != REAL_TYPE)
{
unsigned innerprec = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
--- 3951,3957 ----
if (TREE_CODE (op) == COMPONENT_REF
/* Since type_for_size always gives an integer type. */
! && TREE_CODE (type) != REAL_TYPE
! /* Don't crash if field not layed out yet. */
! && DECL_SIZE (TREE_OPERAND (op, 1)) != 0)
{
unsigned innerprec = TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (op, 1)));
diff -rcp2N gcc-2.7.2.2/tree.h g77-new/tree.h
*** gcc-2.7.2.2/tree.h Mon Sep 25 17:49:40 1995
--- g77-new/tree.h Sun Aug 10 18:47:08 1997
*************** enum built_in_function
*** 98,101 ****
--- 98,103 ----
BUILT_IN_APPLY,
BUILT_IN_RETURN,
+ BUILT_IN_SETJMP,
+ BUILT_IN_LONGJMP,
/* C++ extensions */
*************** struct tree_int_cst
*** 408,411 ****
--- 410,415 ----
{
char common[sizeof (struct tree_common)];
+ struct rtx_def *rtl; /* acts as link to register transfer language
+ (rtl) info */
HOST_WIDE_INT int_cst_low;
HOST_WIDE_INT int_cst_high;
*************** struct tree_type
*** 957,960 ****
--- 961,967 ----
#define DECL_STATIC_DESTRUCTOR(NODE) ((NODE)->decl.static_dtor_flag)
+ /* In a PARM_DECL, nonzero if this is a restricted pointer. */
+ #define DECL_RESTRICT(NODE) (NODE)->decl.static_ctor_flag
+
/* Used to indicate that this DECL represents a compiler-generated entity. */
#define DECL_ARTIFICIAL(NODE) ((NODE)->decl.artificial_flag)
*************** extern tree build_int_2_wide PROTO((HOS
*** 1176,1180 ****
extern tree build_real PROTO((tree, REAL_VALUE_TYPE));
extern tree build_real_from_int_cst PROTO((tree, tree));
! extern tree build_complex PROTO((tree, tree));
extern tree build_string PROTO((int, char *));
extern tree build1 PROTO((enum tree_code, tree, tree));
--- 1183,1187 ----
extern tree build_real PROTO((tree, REAL_VALUE_TYPE));
extern tree build_real_from_int_cst PROTO((tree, tree));
! extern tree build_complex PROTO((tree, tree, tree));
extern tree build_string PROTO((int, char *));
extern tree build1 PROTO((enum tree_code, tree, tree));
*************** extern int contains_placeholder_p PROTO(
*** 1378,1387 ****
extern tree substitute_in_expr PROTO((tree, tree, tree));
- /* Given a type T, a FIELD_DECL F, and a replacement value R,
- return a new type with all size expressions that contain F
- updated by replacing the reference to F with R. */
-
- extern tree substitute_in_type PROTO((tree, tree, tree));
-
/* variable_size (EXP) is like save_expr (EXP) except that it
is for the special case of something that is part of a
--- 1385,1388 ----
*************** extern tree maybe_build_cleanup PROTO((
*** 1456,1460 ****
and find the ultimate containing object, which is returned. */
! extern tree get_inner_reference PROTO((tree, int *, int *, tree *, enum machine_mode *, int *, int *));
/* Return the FUNCTION_DECL which provides this _DECL with its context,
--- 1457,1463 ----
and find the ultimate containing object, which is returned. */
! extern tree get_inner_reference PROTO((tree, int *, int *, tree *,
! enum machine_mode *, int *,
! int *, int *));
/* Return the FUNCTION_DECL which provides this _DECL with its context,
diff -rcp2N gcc-2.7.2.2/unroll.c g77-new/unroll.c
*** gcc-2.7.2.2/unroll.c Sat Aug 19 17:33:26 1995
--- g77-new/unroll.c Thu Jul 10 20:09:10 1997
*************** unroll_loop (loop_end, insn_count, loop_
*** 268,273 ****
structure of the function. This can happen as a result of the
"if (foo) bar; else break;" optimization in jump.c. */
! if (write_symbols != NO_DEBUG)
{
int block_begins = 0;
--- 268,277 ----
structure of the function. This can happen as a result of the
"if (foo) bar; else break;" optimization in jump.c. */
+ /* ??? Gcc has a general policy that -g is never supposed to change the code
+ that the compiler emits, so we must disable this optimization always,
+ even if debug info is not being output. This is rare, so this should
+ not be a significant performance problem. */
! if (1 /* write_symbols != NO_DEBUG */)
{
int block_begins = 0;
*************** unroll_loop (loop_end, insn_count, loop_
*** 633,636 ****
--- 637,657 ----
}
+ if (unroll_type == UNROLL_NAIVE
+ && GET_CODE (last_loop_insn) == JUMP_INSN
+ && start_label != JUMP_LABEL (last_loop_insn))
+ {
+ /* ??? The loop ends with a conditional branch that does not branch back
+ to the loop start label. In this case, we must emit an unconditional
+ branch to the loop exit after emitting the final branch.
+ copy_loop_body does not have support for this currently, so we
+ give up. It doesn't seem worthwhile to unroll anyways since
+ unrolling would increase the number of branch instructions
+ executed. */
+ if (loop_dump_stream)
+ fprintf (loop_dump_stream,
+ "Unrolling failure: final conditional branch not to loop start\n");
+ return;
+ }
+
/* Allocate a translation table for the labels and insn numbers.
They will be filled in as we copy the insns in the loop. */
*************** unroll_loop (loop_end, insn_count, loop_
*** 995,999 ****
for (j = FIRST_PSEUDO_REGISTER; j < max_reg_before_loop; j++)
if (local_regno[j])
! map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
/* The last copy needs the compare/branch insns at the end,
--- 1016,1024 ----
for (j = FIRST_PSEUDO_REGISTER; j < max_reg_before_loop; j++)
if (local_regno[j])
! {
! map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
! record_base_value (REGNO (map->reg_map[j]),
! regno_reg_rtx[j]);
! }
/* The last copy needs the compare/branch insns at the end,
*************** unroll_loop (loop_end, insn_count, loop_
*** 1136,1140 ****
for (j = FIRST_PSEUDO_REGISTER; j < max_reg_before_loop; j++)
if (local_regno[j])
! map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
/* If loop starts with a branch to the test, then fix it so that
--- 1161,1169 ----
for (j = FIRST_PSEUDO_REGISTER; j < max_reg_before_loop; j++)
if (local_regno[j])
! {
! map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
! record_base_value (REGNO (map->reg_map[j]),
! regno_reg_rtx[j]);
! }
/* If loop starts with a branch to the test, then fix it so that
*************** copy_loop_body (copy_start, copy_end, ma
*** 1605,1608 ****
--- 1634,1641 ----
int this_giv_inc = INTVAL (giv_inc);
+ /* If this DEST_ADDR giv was not split, then ignore it. */
+ if (*tv->location != tv->dest_reg)
+ continue;
+
/* Scale this_giv_inc if the multiplicative factors of
the two givs are different. */
*************** copy_loop_body (copy_start, copy_end, ma
*** 1631,1635 ****
incrementing the shared pseudo reg more than
once. */
! if (! tv->same_insn)
{
/* tv->dest_reg may actually be a (PLUS (REG)
--- 1664,1668 ----
incrementing the shared pseudo reg more than
once. */
! if (! tv->same_insn && ! tv->shared)
{
/* tv->dest_reg may actually be a (PLUS (REG)
*************** copy_loop_body (copy_start, copy_end, ma
*** 1757,1760 ****
--- 1790,1794 ----
giv_dest_reg = tem;
map->reg_map[regno] = tem;
+ record_base_value (REGNO (tem), giv_src_reg);
}
else
*************** iteration_info (iteration_var, initial_v
*** 2220,2231 ****
return;
}
! /* Reject iteration variables larger than the host long size, since they
could result in a number of iterations greater than the range of our
! `unsigned long' variable loop_n_iterations. */
! else if (GET_MODE_BITSIZE (GET_MODE (iteration_var)) > HOST_BITS_PER_LONG)
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
! "Loop unrolling: Iteration var rejected because mode larger than host long.\n");
return;
}
--- 2254,2266 ----
return;
}
! /* Reject iteration variables larger than the host wide int size, since they
could result in a number of iterations greater than the range of our
! `unsigned HOST_WIDE_INT' variable loop_n_iterations. */
! else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var))
! > HOST_BITS_PER_WIDE_INT))
{
if (loop_dump_stream)
fprintf (loop_dump_stream,
! "Loop unrolling: Iteration var rejected because mode too large.\n");
return;
}
*************** find_splittable_regs (unroll_type, loop_
*** 2443,2447 ****
{
rtx tem = gen_reg_rtx (bl->biv->mode);
!
emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
loop_start);
--- 2478,2483 ----
{
rtx tem = gen_reg_rtx (bl->biv->mode);
!
! record_base_value (REGNO (tem), bl->biv->add_val);
emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
loop_start);
*************** find_splittable_regs (unroll_type, loop_
*** 2500,2503 ****
--- 2536,2541 ----
exits. */
rtx tem = gen_reg_rtx (bl->biv->mode);
+ record_base_value (REGNO (tem), bl->biv->add_val);
+
emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
loop_start);
*************** find_splittable_givs (bl, unroll_type, l
*** 2675,2678 ****
--- 2713,2717 ----
rtx tem = gen_reg_rtx (bl->biv->mode);
+ record_base_value (REGNO (tem), bl->biv->add_val);
emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
loop_start);
*************** find_splittable_givs (bl, unroll_type, l
*** 2716,2719 ****
--- 2755,2759 ----
{
rtx tem = gen_reg_rtx (v->mode);
+ record_base_value (REGNO (tem), v->add_val);
emit_iv_add_mult (bl->initial_value, v->mult_val,
v->add_val, tem, loop_start);
*************** find_splittable_givs (bl, unroll_type, l
*** 2734,2747 ****
register for the split addr giv, just to be safe. */
! /* ??? If there are multiple address givs which have been
! combined with the same dest_reg giv, then we may only need
! one new register for them. Pulling out constants below will
! catch some of the common cases of this. Currently, I leave
! the work of simplifying multiple address givs to the
! following cse pass. */
!
! /* As a special case, if we have multiple identical address givs
! within a single instruction, then we do use a single pseudo
! reg for both. This is necessary in case one is a match_dup
of the other. */
--- 2774,2780 ----
register for the split addr giv, just to be safe. */
! /* If we have multiple identical address givs within a
! single instruction, then use a single pseudo reg for
! both. This is necessary in case one is a match_dup
of the other. */
*************** find_splittable_givs (bl, unroll_type, l
*** 2756,2759 ****
--- 2789,2812 ----
INSN_UID (v->insn));
}
+ /* If multiple address GIVs have been combined with the
+ same dest_reg GIV, do not create a new register for
+ each. */
+ else if (unroll_type != UNROLL_COMPLETELY
+ && v->giv_type == DEST_ADDR
+ && v->same && v->same->giv_type == DEST_ADDR
+ && v->same->unrolled
+ #ifdef ADDRESS_COST
+ /* combine_givs_p may return true when ADDRESS_COST is
+ defined even if the multiply and add values are
+ not equal. To share a register here, the values
+ must be equal, as well as related. */
+ && rtx_equal_p (v->mult_val, v->same->mult_val)
+ && rtx_equal_p (v->add_val, v->same->add_val)
+ #endif
+ )
+ {
+ v->dest_reg = v->same->dest_reg;
+ v->shared = 1;
+ }
else if (unroll_type != UNROLL_COMPLETELY)
{
*************** find_splittable_givs (bl, unroll_type, l
*** 2761,2765 ****
register to hold the split value of the DEST_ADDR giv.
Emit insn to initialize its value before loop start. */
! tem = gen_reg_rtx (v->mode);
/* If the address giv has a constant in its new_reg value,
--- 2814,2821 ----
register to hold the split value of the DEST_ADDR giv.
Emit insn to initialize its value before loop start. */
!
! rtx tem = gen_reg_rtx (v->mode);
! record_base_value (REGNO (tem), v->add_val);
! v->unrolled = 1;
/* If the address giv has a constant in its new_reg value,
*************** find_splittable_givs (bl, unroll_type, l
*** 2772,2781 ****
v->dest_reg
= plus_constant (tem, INTVAL (XEXP (v->new_reg,1)));
!
/* Only succeed if this will give valid addresses.
Try to validate both the first and the last
address resulting from loop unrolling, if
one fails, then can't do const elim here. */
! if (! verify_addresses (v, giv_inc, unroll_number))
{
/* Save the negative of the eliminated const, so
--- 2828,2837 ----
v->dest_reg
= plus_constant (tem, INTVAL (XEXP (v->new_reg,1)));
!
/* Only succeed if this will give valid addresses.
Try to validate both the first and the last
address resulting from loop unrolling, if
one fails, then can't do const elim here. */
! if (verify_addresses (v, giv_inc, unroll_number))
{
/* Save the negative of the eliminated const, so
*************** final_biv_value (bl, loop_start, loop_en
*** 3061,3064 ****
--- 3117,3121 ----
tem = gen_reg_rtx (bl->biv->mode);
+ record_base_value (REGNO (tem), bl->biv->add_val);
/* Make sure loop_end is not the last insn. */
if (NEXT_INSN (loop_end) == 0)
*************** final_giv_value (v, loop_start, loop_end
*** 3154,3157 ****
--- 3211,3215 ----
/* Put the final biv value in tem. */
tem = gen_reg_rtx (bl->biv->mode);
+ record_base_value (REGNO (tem), bl->biv->add_val);
emit_iv_add_mult (increment, GEN_INT (loop_n_iterations),
bl->initial_value, tem, insert_before);
diff -rcp2N gcc-2.7.2.2/varasm.c g77-new/varasm.c
*** gcc-2.7.2.2/varasm.c Thu Aug 31 19:02:53 1995
--- g77-new/varasm.c Sun Aug 10 22:26:32 1997
*************** assemble_variable (decl, top_level, at_e
*** 1067,1070 ****
--- 1067,1072 ----
if (! dont_output_data)
{
+ int size;
+
if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
goto finish;
*************** assemble_variable (decl, top_level, at_e
*** 1072,1078 ****
/* This is better than explicit arithmetic, since it avoids overflow. */
size_tree = size_binop (CEIL_DIV_EXPR,
! DECL_SIZE (decl), size_int (BITS_PER_UNIT));
! if (TREE_INT_CST_HIGH (size_tree) != 0)
{
error_with_decl (decl, "size of variable `%s' is too large");
--- 1074,1082 ----
/* This is better than explicit arithmetic, since it avoids overflow. */
size_tree = size_binop (CEIL_DIV_EXPR,
! DECL_SIZE (decl), size_int (BITS_PER_UNIT));
! size = TREE_INT_CST_LOW (size_tree);
! if (TREE_INT_CST_HIGH (size_tree) != 0
! || size != TREE_INT_CST_LOW (size_tree))
{
error_with_decl (decl, "size of variable `%s' is too large");
*************** decode_addr_const (exp, value)
*** 2132,2135 ****
--- 2136,2140 ----
case COMPLEX_CST:
case CONSTRUCTOR:
+ case INTEGER_CST:
x = TREE_CST_RTL (target);
break;
*************** const_hash (exp)
*** 2247,2251 ****
return const_hash (TREE_OPERAND (exp, 0)) * 9
+ const_hash (TREE_OPERAND (exp, 1));
! else if (code == NOP_EXPR || code == CONVERT_EXPR)
return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
--- 2252,2256 ----
return const_hash (TREE_OPERAND (exp, 0)) * 9
+ const_hash (TREE_OPERAND (exp, 1));
! else if (code == NOP_EXPR || code == CONVERT_EXPR || code == NON_LVALUE_EXPR)
return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
*************** compare_constant_1 (exp, p)
*** 2401,2405 ****
return p;
}
! else if (code == NOP_EXPR || code == CONVERT_EXPR)
{
p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
--- 2406,2410 ----
return p;
}
! else if (code == NOP_EXPR || code == CONVERT_EXPR || code == NON_LVALUE_EXPR)
{
p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
*************** copy_constant (exp)
*** 2633,2637 ****
case COMPLEX_CST:
! return build_complex (copy_constant (TREE_REALPART (exp)),
copy_constant (TREE_IMAGPART (exp)));
--- 2638,2643 ----
case COMPLEX_CST:
! return build_complex (TREE_TYPE (exp),
! copy_constant (TREE_REALPART (exp)),
copy_constant (TREE_IMAGPART (exp)));
*************** copy_constant (exp)
*** 2644,2647 ****
--- 2650,2654 ----
case NOP_EXPR:
case CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
return build1 (TREE_CODE (exp), TREE_TYPE (exp),
copy_constant (TREE_OPERAND (exp, 0)));
*************** output_constant_def (exp)
*** 2690,2696 ****
register rtx def;
- if (TREE_CODE (exp) == INTEGER_CST)
- abort (); /* No TREE_CST_RTL slot in these. */
-
if (TREE_CST_RTL (exp))
return TREE_CST_RTL (exp);
--- 2697,2700 ----
*************** bc_assemble_integer (exp, size)
*** 3620,3624 ****
exp = fold (exp);
! while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR)
exp = TREE_OPERAND (exp, 0);
if (TREE_CODE (exp) == INTEGER_CST)
--- 3624,3629 ----
exp = fold (exp);
! while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
! || TREE_CODE (exp) == NON_LVALUE_EXPR)
exp = TREE_OPERAND (exp, 0);
if (TREE_CODE (exp) == INTEGER_CST)
*************** bc_assemble_integer (exp, size)
*** 3631,3639 ****
const_part = TREE_OPERAND (exp, 0);
while (TREE_CODE (const_part) == NOP_EXPR
! || TREE_CODE (const_part) == CONVERT_EXPR)
const_part = TREE_OPERAND (const_part, 0);
addr_part = TREE_OPERAND (exp, 1);
while (TREE_CODE (addr_part) == NOP_EXPR
! || TREE_CODE (addr_part) == CONVERT_EXPR)
addr_part = TREE_OPERAND (addr_part, 0);
if (TREE_CODE (const_part) != INTEGER_CST)
--- 3636,3646 ----
const_part = TREE_OPERAND (exp, 0);
while (TREE_CODE (const_part) == NOP_EXPR
! || TREE_CODE (const_part) == CONVERT_EXPR
! || TREE_CODE (const_part) == NON_LVALUE_EXPR)
const_part = TREE_OPERAND (const_part, 0);
addr_part = TREE_OPERAND (exp, 1);
while (TREE_CODE (addr_part) == NOP_EXPR
! || TREE_CODE (addr_part) == CONVERT_EXPR
! || TREE_CODE (addr_part) == NON_LVALUE_EXPR)
addr_part = TREE_OPERAND (addr_part, 0);
if (TREE_CODE (const_part) != INTEGER_CST)
diff -rcp2N gcc-2.7.2.2/version.c g77-new/version.c
*** gcc-2.7.2.2/version.c Thu Feb 20 19:24:33 1997
--- g77-new/version.c Sun Aug 10 19:28:55 1997
***************
*** 1 ****
! char *version_string = "2.7.2.2";
--- 1 ----
! char *version_string = "2.7.2.2.f.3b";