| 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 < ®_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"; |