diff --git a/contrib/gcc/ChangeLog b/contrib/gcc/ChangeLog index 61272bd79e77..3d40878c4fa4 100644 --- a/contrib/gcc/ChangeLog +++ b/contrib/gcc/ChangeLog @@ -1,3 +1,357 @@ +2001-01-01 Bernd Schmidt + + * version.c: Bump. + + * loop.c (instrument_loop_bct): Set JUMP_LABEL on new jump. + + 2000-12-27 Geoffrey Keating + * config/rs6000/rs6000.md (define_attr "length"): Correct + calculation. + +2001-01-01 Philipp Thomas + + * configure.in: Make the help for --enable-nls make it + clear that this is an experimental feature. + * configure: Regenerate. + * ABOUT-GCC-NLS: Explain why NLS support is buggy. + +2000-12-29 Bernd Schmidt + + * version.c: Bump. + + * combine.c (cant_combine_insn_p): Only restrict hard register + combinations for SMALL_REGISTER_CLASSES machines. + + * config/sparc/sparc.c (pic_address_needs_scratch): LABEL_REFs are + not valid pic operands. + + 2000-12-26 Kazu Hirata + * config/h8300/h8300.c (get_shift_alg): Fix a typo in the + assembly code for 12-bit ASHIFTRT in HImode. + + 2000-07-17 Kazu Hirata + * h8300.md: Fix the format of mac. + (movsi_h8300hs): Output a tab after stmac instead of a space. + + 2000-10-07 Will Cohen , Kazu Hirata + * config/h8300/h8300.md: Remove the memory alternative and correct + the insn lengths in the templates for sign extention and zero + extention. + + 2000-12-23 Philip Blundell + * config/arm/linux-elf.h (CPP_PREDEFINES): Don't define `arm' or + `arm_elf'; do define `__arm__'. + + 2000-08-22 Richard Henderson + * alias.c (init_alias_analysis): Do not register + struct_value_incoming_rtx or static_chain_rtx as pointing + to stack memory. + + Tue Dec 5 20:09:14 2000 Jeffrey A Law (law@cygnus.com) + * builtins.c (expand_builtin_setjmp_setup): Set + current_function_has_nonlocal_label. + + 2000-12-03 Richard Henderson + * builtins.c (expand_builtin_setjmp_setup): New. + (expand_builtin_setjmp_receiver): New. + (expand_builtin_setjmp): Split out _setup and _receiver functions. + Move argument parsing in from ... + (expand_builtin): ... here. + * except.c (receive_exception_label): Branch around receiver + unless new-style exceptions. Call expand_builtin_setjmp_receiver. + (start_dynamic_handler): Call expand_builtin_setjmp_setup. + * expr.h: Update builtin setjmp decls. + +2000-12-22 Bernd Schmidt + + * calls.c (emit_call_1): Fall back to call_pop/call_value_pop if no + non-popping calls are available. + + * flow.c (propagate_block): Use flow_delete_insn instead of + NOTEifying a dead ADDR_VEC. + + Fri Sep 10 11:43:07 1999 Philip Blundell + * configure.in, config/arm/linux-oldld.h, + config/arm/linux-elf26.h, config/arm/linux-elf.h: Backport latest + ARM GNU/Linux config from mainline. + * configure: Regenerate. + + 2000-02-08 Geoff Keating + * dwarf2.h (DW_CFA_GNU_negative_offset_extended): New constant. + * dwarf2out.c (dwarf_cfi_name): Print name of new constant. + (reg_save): Use DW_CFA_GNU_negative_offset_extended when needed. + (output_cfi): Handle output of DW_CFA_GNU_negative_offset_extended. + * frame.c (execute_cfa_insn): Handle + DW_CFA_GNU_negative_offset_extended. + + 2000-03-06 Mark Mitchell + * function.c (free_temps_for_rtl_expr): Don't free slots + that have been pushed into a higher level. + + 1999-12-16 David S. Miller + * expr.c (emit_move_insn_1): Only emit clobbers if one of + the outputs is a SUBREG. + + Wed Sep 22 17:35:55 1999 Michael Meissner + * expr.c (emit_move_insn_1): If we are copying a complex that fits + in one word or less (complex char, complex short, or on 64 bit + systems complex float) to/from a hard register, copy it through + memory instead of dying in gen_{real,imag}part. If we have a + short complex type, prevent inlining since it allocates stack + memory. + + Fri Dec 15 15:32:16 MET 2000 Jan Hubicka + * combine.c (cant_combine_insn_p): Get around SUBREGs when determining + hardreg<->reg moves. + + 2000-12-01 Bernd Schmidt + * combine.c (cant_combine_insn_p): Only disallow insns involving + hard regs if they are reg-reg moves. + + 2000-11-24 Bernd Schmidt + * combine.c (cant_combine_insn_p): New function. + (try_combine): Use it. + +2000-12-20 Bernd Schmidt + + * version.c: Bump. + + * reload1.c (free_for_value_p): Fix error in last change. + + 2000-03-22 Richard Henderson + * stmt.c (expand_asm_operands): Don't promote the temporary. + + Sun Sep 19 09:03:40 1999 Mark Mitchell + * rtl.h (insns_safe_to_move_p): New function. + * loop.c (find_and_verify_loops): Use it. + * rtlanal.c (insns_safe_to_move_p): Define it. + + Thu Nov 2 19:20:12 2000 J"orn Rennecke + * reload.c (find_equiv_reg): Test all hard registers for membership + in the requested class. + + Sun Apr 23 16:24:35 2000 Denis Chertykov + * reload.c (find_equiv_reg): Checks all valueno regs + as a reload_reg_p regs. + + Fri Apr 21 14:58:29 2000 Denis Chertykov + * reload.c (find_equiv_reg): Checks all valueno and regno regs + as a call-clobbered regs. + +2000-12-18 Bernd Schmidt + + 2000-09-15 Bernd Schmidt + * optabs.c (emit_libcall_block): If target is a user variable, + copy to a temporary first. + + 2000-04-28 Kazu Hirata + * h8300.c (function_epilogue): Clean up flags when the last insn + in a function is a barrier. + + Mon Aug 30 01:02:09 1999 Jeffrey A Law (law@cygnus.com) + * emit-rtl.c (copy_rtx_if_shared): A MEM which references + virtual_stack_vars_rtx or virtual_incoming_args_rtx can not + be shared. + + 2000-03-24 Geoff Keating + * flow.c (propagate_block): When we delete an ADDR_VEC, + also delete the BARRIER following it if there is one. + + Wed Oct 27 14:10:27 1999 Geoffrey Keating + * flow.c (propagate_block): When the last reference to a label + before an ADDR_VEC is deleted because the reference is a dead + store, delete the ADDR_VEC. + + 2000-03-19 Richard Henderson + * flow.c (delete_block): Delete the addr_vec along with the block. + (flow_delete_insn): Decrement LABEL_NUSES when deleting insns that + reference labels. + + 2000-12-02 Bernd Schmidt + * reload1.c (free_for_value_p): New function, frontend to + reload_reg_free_for_value_p. All callers of the latter now call + this function with an additional mode argument. + + 2000-11-10 Bernd Schmidt + (regno_clobbered_p): New arg SETS. Examine SETs if it's nonzero. All + callers changed. + * reload1.c (choose_reload_regs): Registers set in the insn can't be + used for RELOAD_OTHER reloads. + + 2000-10-28 Bernd Schmidt + * reload1.c (choose_reload_regs): Never set reload_override_in for an + optional reload. + + 2000-09-07 Bernd Schmidt + * reload.c (regno_clobbered_p): Accept new arg, MODE, and use it + to handle multiword modes correctly. All callers and the declaration + changed. + +2000-12-18 David Edelsohn + + * rs6000.c (and64_operand): Use logical_u_operand. + (first_reg_to_save): Don't save fixed or call-used registers + except PIC_OFFSET_TABLE_REGNUM when -fpic even though it is fixed. + * rs6000.md (anddi3): Prefer rldic? over andis instruction. + +2000-12-18 Zack Weinberg : + + * Makefile.in: Rename cpp to cpp0, tradcpp to tradcpp0, and + xcpp to cpp throughout. + (native): Remove unnecessary dependency on cpp. + * gcc.c (C specs): Call cpp0 to do preprocessing, not cpp. + * ch/lang-specs.h, cp/lang-specs.h, f/lang-specs.h, + objc/lang-specs.h: Call cpp0 to do preprocessing, not cpp. + +2000-12-18 Christian Groessler + + * toplev.c (check_lang_option): Use NUM_ELEM only on arrays, not on + pointers. + +2000-12-18 Franz Sirl + + * linux.h (DEFAULT_VTABLE_THUNKS): Switch back to version 1. + * alpha/linux-elf.h (DEFAULT_VTABLE_THUNKS): Likewise. + * arm/linux-elf (DEFAULT_VTABLE_THUNKS): Likewise. + * i386/freebsd-elf.h (DEFAULT_VTABLE_THUNKS): Likewise. + * rs6000/linux.h (DEFAULT_VTABLE_THUNKS): Likewise. + * sparc/linux.h (DEFAULT_VTABLE_THUNKS): Likewise. + +2000-12-05 Bernd Schmidt + + * version.c: Bump. + + 2000-07-03 Nick Clifton + * config/arm/arm.md: Fix post increment and pre increment + peepholes so that they do not generate UNPREDICATBLE opcodes. + (ie ones where the increment clobbers the source/destination). + + Mon Oct 25 00:42:35 1999 Jeffrey A Law (law@cygnus.com) + * arm.c (arm_override_options): Correct initialization of + arm_fast_multiply, arm_arch4, arm_arch5, arm_ld_sched, + arm_is_strong, and arm_is_6_or_7. + + Thu Jul 29 19:01:58 1999 Bernd Schmidt + * arm.h (Hint): Delete macro. + Substitute HOST_WIDE_INT for Hint in some prototypes. + * arm.c: Substitute HOST_WIDE_INT for Hint in one prototype. + +2000-11-30 Bernd Schmidt + + * version.c: Bump. + + Based on a patch from Geoff Keating : + * loop.c (basic_induction_var): If a REG is set from something + that is not a biv, then the REG is not a biv. Even if it is + earlier set from something that is a biv. + + 2000-09-01 Jim Wilson + * loop.c (check_final_value): Check for biv use before checking for + giv use. Check for both biv and giv uses. Always set last_giv_use + if there is a giv use. + + 2000-09-29 Franz Sirl + * loop.c (check_final_value): A GIV is not replaceable if used + before set. + + Sun Oct 10 13:28:48 1999 Bernd Schmidt + * loop.c (find_and_verify_loops): When looking for a BARRIER, don't + use one before a jump table. + + Fri Jul 9 10:48:28 1999 Bernd Schmidt + * loop.c (check_dbra_loop): When reversing a loop, delete all + REG_EQUAL notes referencing the reversed biv except those which are + for a giv based on it. + + 2000-11-24 Bernd Schmidt + * reload1.c (conflicts_with_override): New function. + (emit_input_reload_insns): Use it to tighten test for validity + of substituting into output of previous insn. + + Wed Oct 27 03:09:23 1999 J"orn Rennecke + * reload.h (earlyclobber_operand_p): Declare. + * reload.c (earlyclobber_operand_p): Don't declare. No longer static. + * reload1.c (reload_reg_free_for_value_p): RELOAD_OTHER reloads with + an earlyclobbered output conflict with RELOAD_INPUT reloads - handle + case where the RELOAD_OTHER reload is new. Use + earlyclobber_operand_p. + + 2000-01-12 Bernd Schmidt + * reload1.c (reload_reg_unavailable): New static variable. + (reload_reg_free_p): Test it. + (reload_reg_free_for_value_p): Test it instead of reload_reg_used. + (choose_reload_regs_init): Compute it. + + Thu Jul 6 18:30:36 2000 Richard Kenner + * reload.c (push_reload): When seeing if can reuse a register, + check extra registers against widest of INMODE and OUTMODE. + + 1999-11-29 Bernd Schmidt + * reload.c (push_reload): When looking for a register to put into + reg_rtx, make sure all hard regs in a multi-reg register are in the + right class and nonfixed. + + 1999-11-29 Joern Rennecke + * reload1.c (reloads_conflict): Reverse test comparing operand + numbers when testing for conflict between output/outaddr reloads. + + 2000-07-12 Richard Henderson + * reload.c (push_secondary_reload): Make sure to add the new + reload at the end, after acquiring secondary memory. + + 2000-09-14 Alexandre Oliva , Bernd Schmidt + * reload.c (find_reloads_address_1): Generate reloads for auto_inc + pseudos that refer to the original pseudos, not only to their + equivalent memory locations. + + 2000-09-18 Bernd Schmidt + * reload1.c (forget_old_reloads_1): If a hard reg is stored, clear + its entry in spill_reg_store. + + Tue Oct 26 00:41:54 1999 Bernd Schmidt + * reload1.c (reload_reg_free_for_value_p): Show + RELOAD_FOR_OTHER_ADDRESS reloads can conflict with RELOAD_OTHER + reloads. + + 2000-02-26 Geoff Keating + * reload1.c (do_output_reload): Check reg_reloaded_valid before + looking at reg_reloaded_contents. + + Thu Apr 13 19:39:56 2000 Clinton Popetz + * emit-rtl.c (try_split): Avoid infinite loop if the split + results in a sequence that contains the original insn. + + 1999-12-14 Bernd Schmidt + * combine.c (combine_simplify_rtx): Don't make shared rtl. + (simplify_logical): Likewise. + + Sat May 20 07:27:35 2000 Alexandre Oliva + * fold-const.c (make_range): Handle degenerated intervals. + Fixes c-torture/execute/991221-1.c + + 2000-07-15 Michael Meissner + * fold-const.c (fold): When optimizing FOO++ == CONST into ++FOO + == CONST + INCREMENT, don't overwrite the tree node for FOO++, + create a new node instead. + + 2000-01-01 Bernd Schmidt + * expmed.c (emit_store_flag): Prevent losing a pending stack + adjust the same way we prevent losing queued increments. + +2000-10-27 Bernd Schmidt + + * expr.c (expand_expr, case INDIRECT_REF): If the address is a + PLUS, that does not prove the object is in a structure. + +2000-08-25 David Edelsohn + + * collect2.c (use_import_list): Always return 0 (disable). + +2000-07-07 Manfred Hollstein + + * i386.md (exception_receiver): Add missing parameter in + call to load_pic_register. + Fri May 26 10:30:02 2000 Richard Earnshaw (rearnsha@arm.com) * arm.md (negdi2): Add clobber of condition code register. diff --git a/contrib/gcc/alias.c b/contrib/gcc/alias.c index 9d8aac7832a4..0cf893cf9da6 100644 --- a/contrib/gcc/alias.c +++ b/contrib/gcc/alias.c @@ -1455,15 +1455,6 @@ init_alias_analysis () new_reg_base_value[HARD_FRAME_POINTER_REGNUM] = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx); #endif - if (struct_value_incoming_rtx - && GET_CODE (struct_value_incoming_rtx) == REG) - new_reg_base_value[REGNO (struct_value_incoming_rtx)] - = gen_rtx_ADDRESS (Pmode, struct_value_incoming_rtx); - - if (static_chain_rtx - && GET_CODE (static_chain_rtx) == REG) - new_reg_base_value[REGNO (static_chain_rtx)] - = gen_rtx_ADDRESS (Pmode, static_chain_rtx); /* Walk the insns adding values to the new_reg_base_value array. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) diff --git a/contrib/gcc/calls.c b/contrib/gcc/calls.c index d0153a3d1249..36a5d154138b 100644 --- a/contrib/gcc/calls.c +++ b/contrib/gcc/calls.c @@ -405,7 +405,15 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, #ifndef ACCUMULATE_OUTGOING_ARGS #if defined (HAVE_call_pop) && defined (HAVE_call_value_pop) - if (HAVE_call_pop && HAVE_call_value_pop && n_popped > 0) +/* If the target has "call" or "call_value" insns, then prefer them + if no arguments are actually popped. If the target does not have + "call" or "call_value" insns, then we must use the popping versions + even if the call has no arguments to pop. */ + if (HAVE_call_pop && HAVE_call_value_pop +#if defined (HAVE_call) && defined (HAVE_call_value) + && (n_popped > 0 || ! HAVE_call || ! HAVE_call_value) +#endif + ) { rtx n_pop = GEN_INT (n_popped); rtx pat; diff --git a/contrib/gcc/collect2.c b/contrib/gcc/collect2.c index e5d6452e19cb..c1f9b1c2aec8 100644 --- a/contrib/gcc/collect2.c +++ b/contrib/gcc/collect2.c @@ -3045,21 +3045,11 @@ scan_prog_file (prog_name, which_pass) #ifdef COLLECT_EXPORT_LIST -/* This new function is used to decide whether we should - generate import list for an object or to use it directly. */ +/* Never generate import list (gcc-2.95 branch). */ static int use_import_list (prog_name) char *prog_name; { - char *p; - - /* If we do not build a shared object then import list should not be used. */ - if (! shared_obj) return 0; - - /* Currently we check only for libgcc, but this can be changed in future. */ - p = strstr (prog_name, "libgcc.a"); - if (p != 0 && (strlen (p) == sizeof ("libgcc.a") - 1)) - return 1; return 0; } diff --git a/contrib/gcc/combine.c b/contrib/gcc/combine.c index 57b2e8619bc6..2b7af1e1cd26 100644 --- a/contrib/gcc/combine.c +++ b/contrib/gcc/combine.c @@ -392,6 +392,7 @@ static int n_occurrences; static void init_reg_last_arrays PROTO((void)); static void setup_incoming_promotions PROTO((void)); static void set_nonzero_bits_and_sign_copies PROTO((rtx, rtx)); +static int cant_combine_insn_p PROTO((rtx)); static int can_combine_p PROTO((rtx, rtx, rtx, rtx, rtx *, rtx *)); static int sets_function_arg_p PROTO((rtx)); static int combinable_i3pat PROTO((rtx, rtx *, rtx, rtx, int, rtx *)); @@ -1312,6 +1313,54 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed) return 1; } +/* Determine whether INSN can be used in a combination. Return nonzero if + not. This is used in try_combine to detect early some cases where we + can't perform combinations. */ + +static int +cant_combine_insn_p (insn) + rtx insn; +{ + rtx set; + rtx src, dest; + + /* If this isn't really an insn, we can't do anything. + This can occur when flow deletes an insn that it has merged into an + auto-increment address. */ + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') + return 1; + + /* For the 2.95.3 release, restrict this code to only handle the machines + where it's strictly needed. */ + if (! SMALL_REGISTER_CLASSES) + return 0; + + /* Never combine loads and stores involving hard regs. The register + allocator can usually handle such reg-reg moves by tying. If we allow + the combiner to make substitutions of hard regs, we risk aborting in + reload on machines that have SMALL_REGISTER_CLASSES. + As an exception, we allow combinations involving fixed regs; these are + not available to the register allocator so there's no risk involved. */ + + set = single_set (insn); + if (! set) + return 0; + src = SET_SRC (set); + dest = SET_DEST (set); + if (GET_CODE (src) == SUBREG) + src = SUBREG_REG (src); + if (GET_CODE (dest) == SUBREG) + dest = SUBREG_REG (dest); + if (REG_P (src) && REG_P (dest) + && ((REGNO (src) < FIRST_PSEUDO_REGISTER + && ! fixed_regs[REGNO (src)]) + || (REGNO (dest) < FIRST_PSEUDO_REGISTER + && ! fixed_regs[REGNO (dest)]))) + return 1; + + return 0; +} + /* Try to combine the insns I1 and I2 into I3. Here I1 and I2 appear earlier than I3. I1 can be zero; then we combine just I2 into I3. @@ -1362,21 +1411,20 @@ try_combine (i3, i2, i1) register rtx link; int i; - /* If any of I1, I2, and I3 isn't really an insn, we can't do anything. - This can occur when flow deletes an insn that it has merged into an - auto-increment address. We also can't do anything if I3 has a - REG_LIBCALL note since we don't want to disrupt the contiguity of a - libcall. */ - - if (GET_RTX_CLASS (GET_CODE (i3)) != 'i' - || GET_RTX_CLASS (GET_CODE (i2)) != 'i' - || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i') + /* Exit early if one of the insns involved can't be used for + combinations. */ + if (cant_combine_insn_p (i3) + || cant_combine_insn_p (i2) + || (i1 && cant_combine_insn_p (i1)) + /* We also can't do anything if I3 has a + REG_LIBCALL note since we don't want to disrupt the contiguity of a + libcall. */ #if 0 /* ??? This gives worse code, and appears to be unnecessary, since no pass after flow uses REG_LIBCALL/REG_RETVAL notes. */ || find_reg_note (i3, REG_LIBCALL, NULL_RTX) #endif -) + ) return 0; combine_attempts++; @@ -4015,7 +4063,8 @@ simplify_rtx (x, op0_mode, last, in_dest) gen_binary (MULT, mode, XEXP (XEXP (x, 0), 0), XEXP (x, 1)), gen_binary (MULT, mode, - XEXP (XEXP (x, 0), 1), XEXP (x, 1)))); + XEXP (XEXP (x, 0), 1), + copy_rtx (XEXP (x, 1))))); if (GET_CODE (x) != MULT) return x; @@ -4954,7 +5003,8 @@ simplify_logical (x, last) x = apply_distributive_law (gen_binary (GET_CODE (op0), mode, gen_binary (AND, mode, XEXP (op0, 0), op1), - gen_binary (AND, mode, XEXP (op0, 1), op1))); + gen_binary (AND, mode, XEXP (op0, 1), + copy_rtx (op1)))); if (GET_CODE (x) != AND) return x; } @@ -4963,7 +5013,8 @@ simplify_logical (x, last) return apply_distributive_law (gen_binary (GET_CODE (op1), mode, gen_binary (AND, mode, XEXP (op1, 0), op0), - gen_binary (AND, mode, XEXP (op1, 1), op0))); + gen_binary (AND, mode, XEXP (op1, 1), + copy_rtx (op0)))); /* Similarly, taking advantage of the fact that (and (not A) (xor B C)) == (xor (ior A B) (ior A C)) */ @@ -4972,13 +5023,14 @@ simplify_logical (x, last) return apply_distributive_law (gen_binary (XOR, mode, gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)), - gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 1)))); + gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)), + XEXP (op1, 1)))); else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR) return apply_distributive_law (gen_binary (XOR, mode, gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 0)), - gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 1)))); + gen_binary (IOR, mode, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1)))); break; case IOR: @@ -5004,7 +5056,8 @@ simplify_logical (x, last) x = apply_distributive_law (gen_binary (AND, mode, gen_binary (IOR, mode, XEXP (op0, 0), op1), - gen_binary (IOR, mode, XEXP (op0, 1), op1))); + gen_binary (IOR, mode, XEXP (op0, 1), + copy_rtx (op1)))); if (GET_CODE (x) != IOR) return x; @@ -5015,7 +5068,8 @@ simplify_logical (x, last) x = apply_distributive_law (gen_binary (AND, mode, gen_binary (IOR, mode, XEXP (op1, 0), op0), - gen_binary (IOR, mode, XEXP (op1, 1), op0))); + gen_binary (IOR, mode, XEXP (op1, 1), + copy_rtx (op0)))); if (GET_CODE (x) != IOR) return x; diff --git a/contrib/gcc/config/alpha/linux-elf.h b/contrib/gcc/config/alpha/linux-elf.h index 50bf2307d5b1..fc07127d757e 100644 --- a/contrib/gcc/config/alpha/linux-elf.h +++ b/contrib/gcc/config/alpha/linux-elf.h @@ -38,7 +38,7 @@ Boston, MA 02111-1307, USA. */ #ifndef USE_GNULIBC_1 #undef DEFAULT_VTABLE_THUNKS -#define DEFAULT_VTABLE_THUNKS 2 +#define DEFAULT_VTABLE_THUNKS 1 #endif #ifndef USE_GNULIBC_1 diff --git a/contrib/gcc/config/linux.h b/contrib/gcc/config/linux.h index 46ce8988223e..b619d01cdf5e 100644 --- a/contrib/gcc/config/linux.h +++ b/contrib/gcc/config/linux.h @@ -89,7 +89,7 @@ Boston, MA 02111-1307, USA. */ #ifndef USE_GNULIBC_1 #undef DEFAULT_VTABLE_THUNKS -#define DEFAULT_VTABLE_THUNKS 2 +#define DEFAULT_VTABLE_THUNKS 1 #endif #undef LIB_SPEC diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h index 40694908b68d..d967b01ebe33 100644 --- a/contrib/gcc/config/sparc/linux.h +++ b/contrib/gcc/config/sparc/linux.h @@ -37,7 +37,7 @@ Boston, MA 02111-1307, USA. */ #ifndef USE_GNULIBC_1 #undef DEFAULT_VTABLE_THUNKS -#define DEFAULT_VTABLE_THUNKS 2 +#define DEFAULT_VTABLE_THUNKS 1 #endif /* Use stabs instead of DWARF debug format. */ diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c index 45862a77bc73..6d2d44ff8298 100644 --- a/contrib/gcc/config/sparc/sparc.c +++ b/contrib/gcc/config/sparc/sparc.c @@ -2429,6 +2429,9 @@ int pic_address_needs_scratch (x) rtx x; { + if (GET_CODE (x) == LABEL_REF) + return 1; + /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF diff --git a/contrib/gcc/configure.in b/contrib/gcc/configure.in index c9e2bbf20571..2d054fd2a593 100644 --- a/contrib/gcc/configure.in +++ b/contrib/gcc/configure.in @@ -756,15 +756,31 @@ changequote([,])dnl tmake_file=arm/t-linux gnu_ld=yes ;; + arm*-*-linux-gnuoldld*) # ARM GNU/Linux with old ELF linker + xm_file=arm/xm-linux.h + xmake_file=x-linux + tm_file="arm/linux-oldld.h arm/linux-elf.h" + case $machine in + armv2*-*-*) + tm_file="arm/linux-elf26.h $tm_file" + ;; + esac + tmake_file="t-linux arm/t-linux" + extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o" + gnu_ld=yes + case x${enable_threads} in + x | xyes | xpthreads | xposix) + thread_file='posix' + ;; + esac + ;; arm*-*-linux-gnu*) # ARM GNU/Linux with ELF xm_file=arm/xm-linux.h xmake_file=x-linux + tm_file="arm/linux-elf.h" case $machine in armv2*-*-*) - tm_file=arm/linux-elf26.h - ;; - *) - tm_file=arm/linux-elf.h + tm_file="arm/linux-elf26.h $tm_file" ;; esac tmake_file="t-linux arm/t-linux" @@ -3731,7 +3747,8 @@ ALL_LINGUAS="en_UK" # NLS support is still experimental, so disable it by default for now. AC_ARG_ENABLE(nls, - [ --enable-nls use Native Language Support (disabled by default)], +[ --enable-nls use Native Language Support (disabled by default). + EXPERIMENTAL, see ABOUT-GCC-NLS.], , enable_nls=no) AM_GNU_GETTEXT diff --git a/contrib/gcc/cp/ChangeLog b/contrib/gcc/cp/ChangeLog index 3f005333b881..59383dc9a95f 100644 --- a/contrib/gcc/cp/ChangeLog +++ b/contrib/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +Fri Jun 9 17:55:08 2000 Jeffrey A Law (law@cygnus.com) + + 2000-02-07 + * decl2.c (import_export_decl): vlist ctor wrappers follow virtual + methods in their interface. + (vlist_ctor_wrapper_p): new function. + (finish_vlist_ctor_wrapper): likewise. + + 2000-02-06 + * decl2.c (maybe_retrofit_in_chrg): Move call to + make_vlist_ctor_wrapper from here ... + * decl.c (grok_ctor_properties): ... to here. + * decl.c (grokfndecl): ... and here. + * init.c (no_vlist_base_init): Declare unseen Vlist ctor weak. + * decl2.c (maybe_retrofit_in_chrg): Be sorry about varargs ctors. + 2000-03-08 Nathan Sidwell * exception.cc (__cp_pop_exception): Cleanup the original object. diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c index 069aaaf3fdf3..d7f58bfbfd25 100644 --- a/contrib/gcc/cp/decl2.c +++ b/contrib/gcc/cp/decl2.c @@ -980,7 +980,11 @@ maybe_retrofit_in_chrg (fn) if (DECL_CONSTRUCTOR_P (fn)) { if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn))) - DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_PVBASE; + { + DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_PVBASE; + if (flag_vtable_thunks_compat && varargs_function_p (fn)) + sorry ("-fvtable-thunks=2 for vararg constructor", fn); + } else DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_VBASE; } @@ -1028,10 +1032,6 @@ maybe_retrofit_in_chrg (fn) fntype = build_exception_variant (fntype, TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))); TREE_TYPE (fn) = fntype; - - if (flag_vtable_thunks_compat - && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) - make_vlist_ctor_wrapper (fn); } /* Classes overload their constituent function names automatically. @@ -2854,6 +2854,30 @@ import_export_decl (decl) else DECL_NOT_REALLY_EXTERN (decl) = 0; } + else if (DECL_VLIST_CTOR_WRAPPER_P (decl)) + { + int implement; + tree ctype = DECL_CLASS_CONTEXT (decl); + import_export_class (ctype); + if (!DECL_THIS_INLINE (DECL_VLIST_CTOR_WRAPPED (decl))) + { + /* No change. */ + } + else if (CLASSTYPE_INTERFACE_KNOWN (ctype)) + { + implement = !CLASSTYPE_INTERFACE_ONLY (ctype) + && flag_implement_inlines; + DECL_NOT_REALLY_EXTERN (decl) = implement; + DECL_EXTERNAL (decl) = !implement; + } + else + { + DECL_NOT_REALLY_EXTERN (decl) = 1; + DECL_EXTERNAL (decl) = 1; + } + if (flag_weak) + comdat_linkage (decl); + } else if (DECL_FUNCTION_MEMBER_P (decl)) { tree ctype = DECL_CLASS_CONTEXT (decl); @@ -3606,6 +3630,33 @@ generate_ctor_and_dtor_functions_for_priority (n, data) return 0; } +/* Returns non-zero if T is a vlist ctor wrapper. */ + +static int +vlist_ctor_wrapper_p (t, data) + tree t; + void *data ATTRIBUTE_UNUSED; +{ + return (TREE_CODE (t) == FUNCTION_DECL) && DECL_VLIST_CTOR_WRAPPER_P (t); +} + +/* Emits a vlist ctor wrapper if necessary. */ + +static int +finish_vlist_ctor_wrapper (t, data) + tree *t; + void *data ATTRIBUTE_UNUSED; +{ + import_export_decl (*t); + if (!DECL_EXTERNAL (*t) && !TREE_USED (*t)) + { + mark_used (*t); + synthesize_method (*t); + return 1; + } + return 0; +} + /* This routine is called from the last rule in yyparse (). Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -3682,6 +3733,12 @@ finish_file () /*data=*/0)) reconsider = 1; + if (walk_globals (vlist_ctor_wrapper_p, + finish_vlist_ctor_wrapper, + /*data=*/0)) + reconsider = 1; + + /* The list of objects with static storage duration is built up in reverse order, so we reverse it here. We also clear STATIC_AGGREGATES so that any new aggregates added during the diff --git a/contrib/gcc/cp/init.c b/contrib/gcc/cp/init.c index aed1fde65519..d70fc3298b9a 100644 --- a/contrib/gcc/cp/init.c +++ b/contrib/gcc/cp/init.c @@ -1262,6 +1262,14 @@ no_vlist_base_init (rval, exp, init, binfo, flags) my_friendly_assert (TREE_CODE (func) == CALL_EXPR, 20000131); func = TREE_OPERAND (func, 0); my_friendly_assert (TREE_CODE (func) == ADDR_EXPR, 20000132); + func = TREE_OPERAND (func, 0); + my_friendly_assert (TREE_CODE (func) == FUNCTION_DECL, 20000133); + + /* If we have already seen a definition for the wrapped function, + we don't need to declare it weak. Also, declare_weak will complain + if we do. */ + if (!TREE_ASM_WRITTEN (func)) + declare_weak (func); if (init == NULL_TREE || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init))) diff --git a/contrib/gcc/cp/lang-specs.h b/contrib/gcc/cp/lang-specs.h index 648bc1f09536..baa2fcd8f4b2 100644 --- a/contrib/gcc/cp/lang-specs.h +++ b/contrib/gcc/cp/lang-specs.h @@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */ {"@c++", #if USE_CPPLIB { - "%{E|M|MM:cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ + "%{E|M|MM:cpp0 -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C++ does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\ @@ -62,7 +62,7 @@ Boston, MA 02111-1307, USA. */ %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ %{!pipe:%g.s} %A\n }}}}"}}, #else /* ! USE_CPPLIB */ - {"cpp -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ + {"cpp0 -lang-c++ %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C++ does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ %{!no-gcc:-D__GNUC__=%v1 -D__GNUG__=%v1 -D__GNUC_MINOR__=%v2}\ diff --git a/contrib/gcc/cp/method.c b/contrib/gcc/cp/method.c index d60bfda52422..79a9692fc7a8 100644 --- a/contrib/gcc/cp/method.c +++ b/contrib/gcc/cp/method.c @@ -2241,13 +2241,18 @@ emit_thunk (thunk_fndecl) } void -make_vlist_ctor_wrapper (fn) +maybe_vlist_ctor_wrapper (fn, definep) tree fn; + int definep; { tree fntype, decl; tree arg_types, parms, parm, basetype, pbasetype; tree t, ctors; + if (!flag_vtable_thunks_compat + || !DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) + return; + arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); pbasetype = TREE_VALUE (arg_types); basetype = TREE_TYPE (pbasetype); @@ -2324,15 +2329,23 @@ make_vlist_ctor_wrapper (fn) /* Remember the original function. */ DECL_VLIST_CTOR_WRAPPED (decl) = fn; - /* When fn is declared, DECL_INITIAL is null. When it is defined, - DECL_INITIAL will be error_mark_node. */ - if (DECL_INITIAL (fn) == error_mark_node) + /* If this is called from start_method, definep is -1. Then we + are inside the class, and fn is inline by default. */ + if (definep) { /* Record that the ctor is being defined, so we also emit the - wrapper later. */ - TREE_USED (decl) = 1; - DECL_NOT_REALLY_EXTERN (decl) = 1; - DECL_INITIAL (decl) = NULL_TREE; + wrapper later. */ + if (DECL_THIS_INLINE (fn) || (definep == -1)) + { + DECL_THIS_INLINE (decl) = 1; + DECL_INLINE (decl) = 1; + pushdecl_top_level (decl); + } + else + { + TREE_USED (decl) = 1; + TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1; + } mark_inline_for_output (decl); } } @@ -2651,6 +2664,3 @@ synthesize_method (fndecl) else if (nested) pop_cp_function_context (context); } - - - diff --git a/contrib/gcc/dwarf2.h b/contrib/gcc/dwarf2.h index ddbe1b823bba..d0ca2451b769 100644 --- a/contrib/gcc/dwarf2.h +++ b/contrib/gcc/dwarf2.h @@ -1,6 +1,7 @@ /* Declarations and definitions of codes relating to the DWARF2 symbolic debugging information format. - Copyright (C) 1992, 1993, 1995, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 1992, 1993, 1995, 1996, 1997, 2000 + Free Software Foundation, Inc. Contributed by Gary Funck (gary@intrepid.com). Derived from the DWARF 1 implementation written by Ron Guilmette (rfg@monkeys.com). @@ -501,7 +502,8 @@ enum dwarf_call_frame_info /* GNU extensions */ DW_CFA_GNU_window_save = 0x2d, - DW_CFA_GNU_args_size = 0x2e + DW_CFA_GNU_args_size = 0x2e, + DW_CFA_GNU_negative_offset_extended = 0x2f }; #define DW_CIE_ID 0xffffffff diff --git a/contrib/gcc/dwarf2out.c b/contrib/gcc/dwarf2out.c index de3d26fcb347..30df09d7c28e 100644 --- a/contrib/gcc/dwarf2out.c +++ b/contrib/gcc/dwarf2out.c @@ -719,6 +719,8 @@ dwarf_cfi_name (cfi_opc) return "DW_CFA_GNU_window_save"; case DW_CFA_GNU_args_size: return "DW_CFA_GNU_args_size"; + case DW_CFA_GNU_negative_offset_extended: + return "DW_CFA_GNU_negative_offset_extended"; default: return "DW_CFA_"; @@ -948,7 +950,10 @@ reg_save (label, reg, sreg, offset) offset /= DWARF_CIE_DATA_ALIGNMENT; if (offset < 0) - abort (); + { + cfi->dw_cfi_opc = DW_CFA_GNU_negative_offset_extended; + offset = -offset; + } cfi->dw_cfi_oprnd2.dw_cfi_offset = offset; } else @@ -1635,6 +1640,7 @@ output_cfi (cfi, fde) break; #endif case DW_CFA_offset_extended: + case DW_CFA_GNU_negative_offset_extended: case DW_CFA_def_cfa: output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num); fputc ('\n', asm_out_file); diff --git a/contrib/gcc/emit-rtl.c b/contrib/gcc/emit-rtl.c index 36b030ae7b6b..54cee163738a 100644 --- a/contrib/gcc/emit-rtl.c +++ b/contrib/gcc/emit-rtl.c @@ -1847,25 +1847,17 @@ copy_rtx_if_shared (orig) return x; case MEM: - /* A MEM is allowed to be shared if its address is constant - or is a constant plus one of the special registers. */ - if (CONSTANT_ADDRESS_P (XEXP (x, 0)) - || XEXP (x, 0) == virtual_stack_vars_rtx - || XEXP (x, 0) == virtual_incoming_args_rtx) + /* A MEM is allowed to be shared if its address is constant. + + We used to allow sharing of MEMs which referenced + virtual_stack_vars_rtx or virtual_incoming_args_rtx, but + that can lose. instantiate_virtual_regs will not unshare + the MEMs, and combine may change the structure of the address + because it looks safe and profitable in one context, but + in some other context it creates unrecognizable RTL. */ + if (CONSTANT_ADDRESS_P (XEXP (x, 0))) return x; - if (GET_CODE (XEXP (x, 0)) == PLUS - && (XEXP (XEXP (x, 0), 0) == virtual_stack_vars_rtx - || XEXP (XEXP (x, 0), 0) == virtual_incoming_args_rtx) - && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1))) - { - /* This MEM can appear in more than one place, - but its address better not be shared with anything else. */ - if (! x->used) - XEXP (x, 0) = copy_rtx_if_shared (XEXP (x, 0)); - x->used = 1; - return x; - } break; default: @@ -2359,10 +2351,18 @@ try_split (pat, trial, last) it, in turn, will be split (SFmode on the 29k is an example). */ if (GET_CODE (seq) == SEQUENCE) { + int i; + + /* Avoid infinite loop if any insn of the result matches + the original pattern. */ + for (i = 0; i < XVECLEN (seq, 0); i++) + if (GET_CODE (XVECEXP (seq, 0, i)) == INSN + && rtx_equal_p (PATTERN (XVECEXP (seq, 0, i)), pat)) + return trial; + /* If we are splitting a JUMP_INSN, look for the JUMP_INSN in SEQ and copy our JUMP_LABEL to it. If JUMP_LABEL is non-zero, increment the usage count so we don't delete the label. */ - int i; if (GET_CODE (trial) == JUMP_INSN) for (i = XVECLEN (seq, 0) - 1; i >= 0; i--) diff --git a/contrib/gcc/except.c b/contrib/gcc/except.c index f7d78d687eff..cc6fc2913450 100644 --- a/contrib/gcc/except.c +++ b/contrib/gcc/except.c @@ -723,21 +723,41 @@ static void receive_exception_label (handler_label) rtx handler_label; { + rtx around_label = NULL_RTX; + + if (! flag_new_exceptions || exceptions_via_longjmp) + { + around_label = gen_label_rtx (); + emit_jump (around_label); + emit_barrier (); + } + emit_label (handler_label); + if (! exceptions_via_longjmp) + { #ifdef HAVE_exception_receiver - if (! exceptions_via_longjmp) - if (HAVE_exception_receiver) - emit_insn (gen_exception_receiver ()); + if (HAVE_exception_receiver) + emit_insn (gen_exception_receiver ()); + else #endif - #ifdef HAVE_nonlocal_goto_receiver - if (! exceptions_via_longjmp) - if (HAVE_nonlocal_goto_receiver) - emit_insn (gen_nonlocal_goto_receiver ()); + if (HAVE_nonlocal_goto_receiver) + emit_insn (gen_nonlocal_goto_receiver ()); + else #endif -} + { /* Nothing */ } + } + else + { +#ifndef DONT_USE_BUILTIN_SETJMP + expand_builtin_setjmp_receiver (handler_label); +#endif + } + if (around_label) + emit_label (around_label); +} struct func_eh_entry { @@ -1320,7 +1340,7 @@ static void start_dynamic_handler () { rtx dhc, dcc; - rtx x, arg, buf; + rtx arg, buf; int size; #ifndef DONT_USE_BUILTIN_SETJMP @@ -1362,18 +1382,17 @@ start_dynamic_handler () buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2); #ifdef DONT_USE_BUILTIN_SETJMP - x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1, SImode, 1, - buf, Pmode); - /* If we come back here for a catch, transfer control to the handler. */ - jumpif_rtx (x, ehstack.top->entry->exception_handler_label); -#else { - /* A label to continue execution for the no exception case. */ - rtx noex = gen_label_rtx(); - x = expand_builtin_setjmp (buf, NULL_RTX, noex, - ehstack.top->entry->exception_handler_label); - emit_label (noex); + rtx x; + x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_CONST, + TYPE_MODE (integer_type_node), 1, + buf, Pmode); + /* If we come back here for a catch, transfer control to the handler. */ + jumpif_rtx (x, ehstack.top->entry->exception_handler_label); } +#else + expand_builtin_setjmp_setup (buf, + ehstack.top->entry->exception_handler_label); #endif /* We are committed to this, so update the handler chain. */ diff --git a/contrib/gcc/expmed.c b/contrib/gcc/expmed.c index ffe16fedaf47..dd5973dae4bb 100644 --- a/contrib/gcc/expmed.c +++ b/contrib/gcc/expmed.c @@ -4194,9 +4194,11 @@ emit_store_flag (target, code, op0, op1, mode, unsignedp, normalizep) comparison and then the scc insn. compare_from_rtx may call emit_queue, which would be deleted below - if the scc insn fails. So call it ourselves before setting LAST. */ + if the scc insn fails. So call it ourselves before setting LAST. + Likewise for do_pending_stack_adjust. */ emit_queue (); + do_pending_stack_adjust (); last = get_last_insn (); comparison diff --git a/contrib/gcc/expr.c b/contrib/gcc/expr.c index 812e1fb661ce..3624f77b2337 100644 --- a/contrib/gcc/expr.c +++ b/contrib/gcc/expr.c @@ -191,6 +191,7 @@ static rtx expand_builtin PROTO((tree, rtx, rtx, static int apply_args_size PROTO((void)); static int apply_result_size PROTO((void)); static rtx result_vector PROTO((int, rtx)); +static rtx expand_builtin_setjmp PROTO((tree, rtx)); static rtx expand_builtin_apply_args PROTO((void)); static rtx expand_builtin_apply PROTO((rtx, rtx, rtx)); static void expand_builtin_return PROTO((rtx)); @@ -2679,19 +2680,79 @@ emit_move_insn_1 (x, y) } else { - /* Show the output dies here. This is necessary for pseudos; + rtx realpart_x, realpart_y; + rtx imagpart_x, imagpart_y; + + /* If this is a complex value with each part being smaller than a + word, the usual calling sequence will likely pack the pieces into + a single register. Unfortunately, SUBREG of hard registers only + deals in terms of words, so we have a problem converting input + arguments to the CONCAT of two registers that is used elsewhere + for complex values. If this is before reload, we can copy it into + memory and reload. FIXME, we should see about using extract and + insert on integer registers, but complex short and complex char + variables should be rarely used. */ + if (GET_MODE_BITSIZE (mode) < 2*BITS_PER_WORD + && (reload_in_progress | reload_completed) == 0) + { + int packed_dest_p = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER); + int packed_src_p = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER); + + if (packed_dest_p || packed_src_p) + { + enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT) + ? MODE_FLOAT : MODE_INT); + + enum machine_mode reg_mode = + mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1); + + if (reg_mode != BLKmode) + { + rtx mem = assign_stack_temp (reg_mode, + GET_MODE_SIZE (mode), 0); + + rtx cmem = change_address (mem, mode, NULL_RTX); + + current_function_cannot_inline + = "function using short complex types cannot be inline"; + + if (packed_dest_p) + { + rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0); + emit_move_insn_1 (cmem, y); + return emit_move_insn_1 (sreg, mem); + } + else + { + rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0); + emit_move_insn_1 (mem, sreg); + return emit_move_insn_1 (x, cmem); + } + } + } + } + + realpart_x = gen_realpart (submode, x); + realpart_y = gen_realpart (submode, y); + imagpart_x = gen_imagpart (submode, x); + imagpart_y = gen_imagpart (submode, y); + + /* Show the output dies here. This is necessary for SUBREGs + of pseudos since we cannot track their lifetimes correctly; hard regs shouldn't appear here except as return values. We never want to emit such a clobber after reload. */ if (x != y - && ! (reload_in_progress || reload_completed)) + && ! (reload_in_progress || reload_completed) + && (GET_CODE (realpart_x) == SUBREG + || GET_CODE (imagpart_x) == SUBREG)) { emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); } emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) - (gen_realpart (submode, x), gen_realpart (submode, y))); + (realpart_x, realpart_y)); emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) - (gen_imagpart (submode, x), gen_imagpart (submode, y))); + (imagpart_x, imagpart_y)); } return get_last_insn (); @@ -2703,6 +2764,8 @@ emit_move_insn_1 (x, y) else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) { rtx last_insn = 0; + rtx seq; + int need_clobber; #ifdef PUSH_ROUNDING @@ -2715,15 +2778,9 @@ emit_move_insn_1 (x, y) } #endif - /* Show the output dies here. This is necessary for pseudos; - hard regs shouldn't appear here except as return values. - We never want to emit such a clobber after reload. */ - if (x != y - && ! (reload_in_progress || reload_completed)) - { - emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); - } + start_sequence (); + need_clobber = 0; for (i = 0; i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; i++) @@ -2745,9 +2802,27 @@ emit_move_insn_1 (x, y) if (xpart == 0 || ypart == 0) abort (); + need_clobber |= (GET_CODE (xpart) == SUBREG); + last_insn = emit_move_insn (xpart, ypart); } + seq = gen_sequence (); + end_sequence (); + + /* Show the output dies here. This is necessary for SUBREGs + of pseudos since we cannot track their lifetimes correctly; + hard regs shouldn't appear here except as return values. + We never want to emit such a clobber after reload. */ + if (x != y + && ! (reload_in_progress || reload_completed) + && need_clobber != 0) + { + emit_insn (gen_rtx_CLOBBER (VOIDmode, x)); + } + + emit_insn (seq); + return last_insn; } else @@ -6262,12 +6337,8 @@ expand_expr (exp, target, tmode, modifier) } temp = gen_rtx_MEM (mode, op0); - /* If address was computed by addition, - mark this as an element of an aggregate. */ - if (TREE_CODE (exp1) == PLUS_EXPR - || (TREE_CODE (exp1) == SAVE_EXPR - && TREE_CODE (TREE_OPERAND (exp1, 0)) == PLUS_EXPR) - || AGGREGATE_TYPE_P (TREE_TYPE (exp)) + + if (AGGREGATE_TYPE_P (TREE_TYPE (exp)) || (TREE_CODE (exp1) == ADDR_EXPR && (exp2 = TREE_OPERAND (exp1, 0)) && AGGREGATE_TYPE_P (TREE_TYPE (exp2)))) @@ -8473,44 +8544,29 @@ expand_builtin_return_addr (fndecl_code, count, tem) return tem; } -/* __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. +/* Construct the leading half of a __builtin_setjmp call. Control will + return to RECEIVER_LABEL. This is used directly by sjlj exception + handling code. */ - NOTE: This is intended for use by GNAT and the exception handling - scheme in the compiler and will only work in the method used by - them. */ - -rtx -expand_builtin_setjmp (buf_addr, target, first_label, next_label) +void +expand_builtin_setjmp_setup (buf_addr, receiver_label) rtx buf_addr; - rtx target; - rtx first_label, next_label; + rtx receiver_label; { - rtx lab1 = gen_label_rtx (); enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); - enum machine_mode value_mode; rtx stack_save; - value_mode = TYPE_MODE (integer_type_node); - #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 (); - /* 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. */ + /* We store the frame pointer and the address of receiver_label in + the buffer and use the rest of it for the stack save area, which + is machine-dependent. */ #ifndef BUILTIN_SETJMP_FRAME_VALUE #define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx @@ -8522,7 +8578,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) (gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode)))), - force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1))); + force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label))); stack_save = gen_rtx_MEM (sa_mode, plus_constant (buf_addr, @@ -8535,20 +8591,22 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) emit_insn (gen_builtin_setjmp_setup (buf_addr)); #endif - /* Set TARGET to zero and branch to the first-time-through label. */ - emit_move_insn (target, const0_rtx); - emit_jump_insn (gen_jump (first_label)); - emit_barrier (); - emit_label (lab1); - - /* Tell flow about the strange goings on. Putting `lab1' on - `nonlocal_goto_handler_labels' to indicates that function - calls may traverse the arc back to this label. */ + /* Tell optimize_save_area_alloca that extra work is going to + need to go on during alloca. */ + current_function_calls_setjmp = 1; + /* Set this so all the registers get saved in our frame; we need to be + able to copy the saved values for any registers from frames we unwind. */ current_function_has_nonlocal_label = 1; - nonlocal_goto_handler_labels = - gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels); +} +/* Construct the trailing part of a __builtin_setjmp call. + This is used directly by sjlj exception handling code. */ + +void +expand_builtin_setjmp_receiver (receiver_label) + rtx receiver_label ATTRIBUTE_UNUSED; +{ /* Clobber the 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)); @@ -8595,7 +8653,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) #ifdef HAVE_builtin_setjmp_receiver if (HAVE_builtin_setjmp_receiver) - emit_insn (gen_builtin_setjmp_receiver (lab1)); + emit_insn (gen_builtin_setjmp_receiver (receiver_label)); else #endif #ifdef HAVE_nonlocal_goto_receiver @@ -8606,12 +8664,61 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) { ; /* Nothing */ } +} - /* Set TARGET, and branch to the next-time-through label. */ - emit_move_insn (target, const1_rtx); - emit_jump_insn (gen_jump (next_label)); + +/* __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 the exception handling + scheme in the compiler and will only work in the method used by + them. */ + +static rtx +expand_builtin_setjmp (arglist, target) + tree arglist; + rtx target; +{ + rtx buf_addr, next_lab, cont_lab; + + if (arglist == 0 + || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) + return NULL_RTX; + + if (target == 0 || GET_CODE (target) != REG + || REGNO (target) < FIRST_PSEUDO_REGISTER) + target = gen_reg_rtx (TYPE_MODE (integer_type_node)); + + buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); + + next_lab = gen_label_rtx (); + cont_lab = gen_label_rtx (); + + expand_builtin_setjmp_setup (buf_addr, next_lab); + + /* Set TARGET to zero and branch to the continue label. */ + emit_move_insn (target, const0_rtx); + emit_jump_insn (gen_jump (cont_lab)); emit_barrier (); + emit_label (next_lab); + expand_builtin_setjmp_receiver (next_lab); + + /* Set TARGET to one. */ + emit_move_insn (target, const1_rtx); + emit_label (cont_lab); + + /* Tell flow about the strange goings on. Putting `next_lab' on + `nonlocal_goto_handler_labels' to indicates that function + calls may traverse the arc back to this label. */ + + current_function_has_nonlocal_label = 1; + nonlocal_goto_handler_labels + = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels); + return target; } @@ -9632,18 +9739,10 @@ expand_builtin (exp, target, subtarget, mode, ignore) #endif case BUILT_IN_SETJMP: - if (arglist == 0 - || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) - break; - else - { - rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, - VOIDmode, 0); - rtx lab = gen_label_rtx (); - rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab); - emit_label (lab); - return ret; - } + target = expand_builtin_setjmp (arglist, target); + if (target) + return target; + break; /* __builtin_longjmp is passed a pointer to an array of five words. It's similar to the C library longjmp function but works with diff --git a/contrib/gcc/expr.h b/contrib/gcc/expr.h index 55e82e6622d4..c279774afe5d 100644 --- a/contrib/gcc/expr.h +++ b/contrib/gcc/expr.h @@ -831,7 +831,8 @@ extern rtx store_expr PROTO((tree, rtx, int)); Useful after calling expand_expr with 1 as sum_ok. */ extern rtx force_operand PROTO((rtx, rtx)); -extern rtx expand_builtin_setjmp PROTO((rtx, rtx, rtx, rtx)); +extern void expand_builtin_setjmp_setup PARAMS ((rtx, rtx)); +extern void expand_builtin_setjmp_receiver PARAMS ((rtx)); #ifdef TREE_CODE /* Generate code for computing expression EXP. diff --git a/contrib/gcc/f/lang-specs.h b/contrib/gcc/f/lang-specs.h index b4492a6327d2..39afae0c6dba 100644 --- a/contrib/gcc/f/lang-specs.h +++ b/contrib/gcc/f/lang-specs.h @@ -35,7 +35,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA Sun f77, at least) so you test `__unix' rather than `unix'. -D_LANGUAGE_FORTRAN is used by some compilers like SGI and might as well be in there. */ - {"cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ + {"cpp0 -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\ @@ -85,7 +85,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ %{!pipe:%g.s} %A\n }}}}"}}, {"@f77-version", - {"cpp -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I \ + {"cpp0 -lang-c %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I \ %{C:%{!E:%eGNU C does not support -C without using -E}} \ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG} \ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2} \ diff --git a/contrib/gcc/f/version.c b/contrib/gcc/f/version.c index 5e8381f0fc4f..1b1cfd2bf968 100644 --- a/contrib/gcc/f/version.c +++ b/contrib/gcc/f/version.c @@ -1 +1 @@ -const char *ffe_version_string = "0.5.25 19991024 (release)"; +const char *ffe_version_string = "0.5.25 19991030 (prerelease)"; diff --git a/contrib/gcc/flow.c b/contrib/gcc/flow.c index ac8fd6337ff2..b9c9d07c5b97 100644 --- a/contrib/gcc/flow.c +++ b/contrib/gcc/flow.c @@ -1681,7 +1681,7 @@ delete_block (b) basic_block b; { int deleted_handler = 0; - rtx insn, end; + rtx insn, end, tmp; /* If the head of this block is a CODE_LABEL, then it might be the label for an exception handler which can't be reached. @@ -1728,11 +1728,21 @@ delete_block (b) } } - /* Selectively unlink the insn chain. Include any BARRIER that may - follow the basic block. */ - end = next_nonnote_insn (b->end); - if (!end || GET_CODE (end) != BARRIER) - end = b->end; + /* Include any jump table following the basic block. */ + end = b->end; + if (GET_CODE (end) == JUMP_INSN + && (tmp = JUMP_LABEL (end)) != NULL_RTX + && (tmp = NEXT_INSN (tmp)) != NULL_RTX + && GET_CODE (tmp) == JUMP_INSN + && (GET_CODE (PATTERN (tmp)) == ADDR_VEC + || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC)) + end = tmp; + + /* Include any barrier that may follow the basic block. */ + tmp = next_nonnote_insn (b->end); + if (tmp && GET_CODE (tmp) == BARRIER) + end = tmp; + delete_insn_chain (insn, end); no_delete_insns: @@ -1796,6 +1806,7 @@ flow_delete_insn (insn) { rtx prev = PREV_INSN (insn); rtx next = NEXT_INSN (insn); + rtx note; PREV_INSN (insn) = NULL_RTX; NEXT_INSN (insn) = NULL_RTX; @@ -1815,6 +1826,10 @@ flow_delete_insn (insn) if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn)) LABEL_NUSES (JUMP_LABEL (insn))--; + /* Also if deleting an insn that references a label. */ + else if ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX) + LABEL_NUSES (XEXP (note, 0))--; + return next; } @@ -2721,6 +2736,39 @@ propagate_block (old, first, last, final, significant, bnum, remove_dead_code) can cause trouble for first or last insn in a basic block. */ if (final && insn_is_dead) { + rtx inote; + /* If the insn referred to a label, note that the label is + now less used. */ + for (inote = REG_NOTES (insn); inote; inote = XEXP (inote, 1)) + { + if (REG_NOTE_KIND (inote) == REG_LABEL) + { + rtx label = XEXP (inote, 0); + rtx next; + LABEL_NUSES (label)--; + + /* If this label was attached to an ADDR_VEC, it's + safe to delete the ADDR_VEC. In fact, it's pretty much + mandatory to delete it, because the ADDR_VEC may + be referencing labels that no longer exist. */ + if (LABEL_NUSES (label) == 0 + && (next = next_nonnote_insn (label)) != NULL + && GET_CODE (next) == JUMP_INSN + && (GET_CODE (PATTERN (next)) == ADDR_VEC + || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC)) + { + rtx pat = PATTERN (next); + int diff_vec_p = GET_CODE (pat) == ADDR_DIFF_VEC; + int len = XVECLEN (pat, diff_vec_p); + int i; + for (i = 0; i < len; i++) + LABEL_NUSES (XEXP (XVECEXP (pat, diff_vec_p, i), 0))--; + + flow_delete_insn (next); + } + } + } + PUT_CODE (insn, NOTE); NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; NOTE_SOURCE_FILE (insn) = 0; diff --git a/contrib/gcc/fold-const.c b/contrib/gcc/fold-const.c index cbd004e40843..f260ab4b5004 100644 --- a/contrib/gcc/fold-const.c +++ b/contrib/gcc/fold-const.c @@ -3259,8 +3259,17 @@ make_range (exp, pin_p, plow, phigh) low = range_binop (PLUS_EXPR, type, n_high, 0, integer_one_node, 0); high = range_binop (MINUS_EXPR, type, n_low, 0, - integer_one_node, 0); - in_p = ! in_p; + integer_one_node, 0); + + /* If the range is of the form +/- [ x+1, x ], we won't + be able to normalize it. But then, it represents the + whole range or the empty set, so make it +/- [ -, - ]. + */ + if (tree_int_cst_equal (n_low, low) + && tree_int_cst_equal (n_high, high)) + low = high = 0; + else + in_p = ! in_p; } else low = n_low, high = n_high; @@ -5625,7 +5634,15 @@ fold (expr) tree newconst = fold (build (PLUS_EXPR, TREE_TYPE (varop), constop, TREE_OPERAND (varop, 1))); - TREE_SET_CODE (varop, PREINCREMENT_EXPR); + + /* Do not overwrite the current varop to be a preincrement, + create a new node so that we won't confuse our caller who + might create trees and throw them away, reusing the + arguments that they passed to build. This shows up in + the THEN or ELSE parts of ?: being postincrements. */ + varop = build (PREINCREMENT_EXPR, TREE_TYPE (varop), + TREE_OPERAND (varop, 0), + TREE_OPERAND (varop, 1)); /* If VAROP is a reference to a bitfield, we must mask the constant by the width of the field. */ @@ -5669,9 +5686,9 @@ fold (expr) } - t = build (code, type, TREE_OPERAND (t, 0), - TREE_OPERAND (t, 1)); - TREE_OPERAND (t, constopnum) = newconst; + t = build (code, type, + (constopnum == 0) ? newconst : varop, + (constopnum == 1) ? newconst : varop); return t; } } @@ -5684,7 +5701,15 @@ fold (expr) tree newconst = fold (build (MINUS_EXPR, TREE_TYPE (varop), constop, TREE_OPERAND (varop, 1))); - TREE_SET_CODE (varop, PREDECREMENT_EXPR); + + /* Do not overwrite the current varop to be a predecrement, + create a new node so that we won't confuse our caller who + might create trees and throw them away, reusing the + arguments that they passed to build. This shows up in + the THEN or ELSE parts of ?: being postdecrements. */ + varop = build (PREDECREMENT_EXPR, TREE_TYPE (varop), + TREE_OPERAND (varop, 0), + TREE_OPERAND (varop, 1)); if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF && DECL_BIT_FIELD(TREE_OPERAND @@ -5723,9 +5748,9 @@ fold (expr) } - t = build (code, type, TREE_OPERAND (t, 0), - TREE_OPERAND (t, 1)); - TREE_OPERAND (t, constopnum) = newconst; + t = build (code, type, + (constopnum == 0) ? newconst : varop, + (constopnum == 1) ? newconst : varop); return t; } } diff --git a/contrib/gcc/frame.c b/contrib/gcc/frame.c index b5f643e70437..4dabf119b825 100644 --- a/contrib/gcc/frame.c +++ b/contrib/gcc/frame.c @@ -714,6 +714,14 @@ execute_cfa_insn (void *p, struct frame_state_internal *state, state->s.args_size = offset; break; + case DW_CFA_GNU_negative_offset_extended: + p = decode_uleb128 (p, ®); + p = decode_uleb128 (p, &offset); + offset *= info->data_align; + state->s.saved[reg] = REG_SAVED_OFFSET; + state->s.reg_or_offset[reg] = -offset; + break; + default: abort (); } diff --git a/contrib/gcc/loop.c b/contrib/gcc/loop.c index 497ac369c2b3..d7242ed04eb2 100644 --- a/contrib/gcc/loop.c +++ b/contrib/gcc/loop.c @@ -2773,6 +2773,7 @@ find_and_verify_loops (f) { rtx p; rtx our_next = next_real_insn (insn); + rtx last_insn_to_move = NEXT_INSN (insn); int dest_loop; int outer_loop = -1; @@ -2824,21 +2825,39 @@ find_and_verify_loops (f) && INSN_UID (JUMP_LABEL (p)) != 0 && condjump_p (p) && ! simplejump_p (p) - && next_real_insn (JUMP_LABEL (p)) == our_next) + && next_real_insn (JUMP_LABEL (p)) == our_next + /* If it's not safe to move the sequence, then we + mustn't try. */ + && insns_safe_to_move_p (p, NEXT_INSN (insn), + &last_insn_to_move)) { rtx target = JUMP_LABEL (insn) ? JUMP_LABEL (insn) : get_last_insn (); int target_loop_num = uid_loop_num[INSN_UID (target)]; - rtx loc; + rtx loc, loc2; for (loc = target; loc; loc = PREV_INSN (loc)) if (GET_CODE (loc) == BARRIER + /* Don't move things inside a tablejump. */ + && ((loc2 = next_nonnote_insn (loc)) == 0 + || GET_CODE (loc2) != CODE_LABEL + || (loc2 = next_nonnote_insn (loc2)) == 0 + || GET_CODE (loc2) != JUMP_INSN + || (GET_CODE (PATTERN (loc2)) != ADDR_VEC + && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC)) && uid_loop_num[INSN_UID (loc)] == target_loop_num) break; if (loc == 0) for (loc = target; loc; loc = NEXT_INSN (loc)) if (GET_CODE (loc) == BARRIER + /* Don't move things inside a tablejump. */ + && ((loc2 = next_nonnote_insn (loc)) == 0 + || GET_CODE (loc2) != CODE_LABEL + || (loc2 = next_nonnote_insn (loc2)) == 0 + || GET_CODE (loc2) != JUMP_INSN + || (GET_CODE (PATTERN (loc2)) != ADDR_VEC + && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC)) && uid_loop_num[INSN_UID (loc)] == target_loop_num) break; @@ -2879,11 +2898,13 @@ find_and_verify_loops (f) /* Include the BARRIER after INSN and copy the block after LOC. */ - new_label = squeeze_notes (new_label, NEXT_INSN (insn)); - reorder_insns (new_label, NEXT_INSN (insn), loc); + new_label = squeeze_notes (new_label, + last_insn_to_move); + reorder_insns (new_label, last_insn_to_move, loc); /* All those insns are now in TARGET_LOOP_NUM. */ - for (q = new_label; q != NEXT_INSN (NEXT_INSN (insn)); + for (q = new_label; + q != NEXT_INSN (last_insn_to_move); q = NEXT_INSN (q)) uid_loop_num[INSN_UID (q)] = target_loop_num; @@ -5678,6 +5699,7 @@ check_final_value (v, loop_start, loop_end, n_iterations) or all uses follow that insn in the same basic block), - its final value can be calculated (this condition is different than the one above in record_giv) + - it's not used before it's set - no assignments to the biv occur during the giv's lifetime. */ #if 0 @@ -5689,7 +5711,7 @@ check_final_value (v, loop_start, loop_end, n_iterations) if ((final_value = final_giv_value (v, loop_start, loop_end, n_iterations)) && (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn))) { - int biv_increment_seen = 0; + int biv_increment_seen = 0, before_giv_insn = 0; rtx p = v->insn; rtx last_giv_use; @@ -5719,26 +5741,35 @@ check_final_value (v, loop_start, loop_end, n_iterations) { p = NEXT_INSN (p); if (p == loop_end) - p = NEXT_INSN (loop_start); + { + before_giv_insn = 1; + p = NEXT_INSN (loop_start); + } if (p == v->insn) break; if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN || GET_CODE (p) == CALL_INSN) { - if (biv_increment_seen) + /* It is possible for the BIV increment to use the GIV if we + have a cycle. Thus we must be sure to check each insn for + both BIV and GIV uses, and we must check for BIV uses + first. */ + + if (! biv_increment_seen + && reg_set_p (v->src_reg, PATTERN (p))) + biv_increment_seen = 1; + + if (reg_mentioned_p (v->dest_reg, PATTERN (p))) { - if (reg_mentioned_p (v->dest_reg, PATTERN (p))) + if (biv_increment_seen || before_giv_insn) { v->replaceable = 0; v->not_replaceable = 1; break; } + last_giv_use = p; } - else if (reg_set_p (v->src_reg, PATTERN (p))) - biv_increment_seen = 1; - else if (reg_mentioned_p (v->dest_reg, PATTERN (p))) - last_giv_use = p; } } @@ -5983,6 +6014,7 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location) insn = p; while (1) { + rtx dest; do { insn = PREV_INSN (insn); } while (insn && GET_CODE (insn) == NOTE @@ -5994,20 +6026,26 @@ basic_induction_var (x, mode, dest_reg, p, inc_val, mult_val, location) if (set == 0) break; - if ((SET_DEST (set) == x - || (GET_CODE (SET_DEST (set)) == SUBREG - && (GET_MODE_SIZE (GET_MODE (SET_DEST (set))) - <= UNITS_PER_WORD) - && (GET_MODE_CLASS (GET_MODE (SET_DEST (set))) - == MODE_INT) - && SUBREG_REG (SET_DEST (set)) == x)) - && basic_induction_var (SET_SRC (set), - (GET_MODE (SET_SRC (set)) == VOIDmode - ? GET_MODE (x) - : GET_MODE (SET_SRC (set))), - dest_reg, insn, - inc_val, mult_val, location)) - return 1; + dest = SET_DEST (set); + if (dest == x + || (GET_CODE (dest) == SUBREG + && (GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD) + && (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT) + && SUBREG_REG (dest) == x)) + return basic_induction_var (SET_SRC (set), + (GET_MODE (SET_SRC (set)) == VOIDmode + ? GET_MODE (x) + : GET_MODE (SET_SRC (set))), + dest_reg, insn, + inc_val, mult_val, location); + + while (GET_CODE (dest) == SIGN_EXTRACT + || GET_CODE (dest) == ZERO_EXTRACT + || GET_CODE (dest) == SUBREG + || GET_CODE (dest) == STRICT_LOW_PART) + dest = XEXP (dest, 0); + if (dest == x) + break; } /* ... fall through ... */ @@ -8155,6 +8193,40 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info) bl->nonneg = 1; } + /* No insn may reference both the reversed and another biv or it + will fail (see comment near the top of the loop reversal + code). + Earlier on, we have verified that the biv has no use except + counting, or it is the only biv in this function. + However, the code that computes no_use_except_counting does + not verify reg notes. It's possible to have an insn that + references another biv, and has a REG_EQUAL note with an + expression based on the reversed biv. To avoid this case, + remove all REG_EQUAL notes based on the reversed biv + here. */ + for (p = loop_start; p != loop_end; p = NEXT_INSN (p)) + if (GET_RTX_CLASS (GET_CODE (p)) == 'i') + { + rtx *pnote; + rtx set = single_set (p); + /* If this is a set of a GIV based on the reversed biv, any + REG_EQUAL notes should still be correct. */ + if (! set + || GET_CODE (SET_DEST (set)) != REG + || (size_t) REGNO (SET_DEST (set)) >= reg_iv_type->num_elements + || REG_IV_TYPE (REGNO (SET_DEST (set))) != GENERAL_INDUCT + || REG_IV_INFO (REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg) + for (pnote = ®_NOTES (p); *pnote;) + { + if (REG_NOTE_KIND (*pnote) == REG_EQUAL + && reg_mentioned_p (regno_reg_rtx[bl->regno], + XEXP (*pnote, 0))) + *pnote = XEXP (*pnote, 1); + else + pnote = &XEXP (*pnote, 1); + } + } + /* Mark that this biv has been reversed. Each giv which depends on this biv, and which is also live past the end of the loop will have to be fixed up. */ @@ -9314,6 +9386,7 @@ instrument_loop_bct (loop_start, loop_end, loop_num_iterations) emit_jump_insn_before (gen_decrement_and_branch_on_count (counter_reg, start_label), loop_end); + JUMP_LABEL (prev_nonnote_insn (loop_end)) = start_label; LABEL_NUSES (start_label)++; } diff --git a/contrib/gcc/objc/lang-specs.h b/contrib/gcc/objc/lang-specs.h index 41dc097b5023..b0d873144c39 100644 --- a/contrib/gcc/objc/lang-specs.h +++ b/contrib/gcc/objc/lang-specs.h @@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */ {".m", {"@objective-c"}}, {"@objective-c", #if USE_CPPLIB - {"%{E|M|MM:cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ + {"%{E|M|MM:cpp0 -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ -D__OBJC__ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\ @@ -55,7 +55,7 @@ Boston, MA 02111-1307, USA. */ %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}\ %{!pipe:%g.s} %A\n }}}}"} #else /* ! USE_CPPLIB */ - {"cpp -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ + {"cpp0 -lang-objc %{nostdinc*} %{C} %{v} %{A*} %{I*} %{P} %{$} %I\ %{C:%{!E:%eGNU C does not support -C without using -E}}\ %{M} %{MM} %{MD:-MD %b.d} %{MMD:-MMD %b.d} %{MG}\ -D__OBJC__ %{!no-gcc:-D__GNUC__=%v1 -D__GNUC_MINOR__=%v2}\ diff --git a/contrib/gcc/optabs.c b/contrib/gcc/optabs.c index 2b9091bcf4e0..bb875ee3cb3f 100644 --- a/contrib/gcc/optabs.c +++ b/contrib/gcc/optabs.c @@ -2887,8 +2887,14 @@ emit_libcall_block (insns, target, result, equiv) rtx result; rtx equiv; { + rtx final_dest = target; rtx prev, next, first, last, insn; + /* If this is a reg with REG_USERVAR_P set, then it could possibly turn + into a MEM later. Protect the libcall block from this change. */ + if (! REG_P (target) || REG_USERVAR_P (target)) + target = gen_reg_rtx (GET_MODE (target)); + /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION reg note to indicate that this call cannot throw. (Unless there is already a REG_EH_REGION note.) */ @@ -2952,6 +2958,9 @@ emit_libcall_block (insns, target, result, equiv) != CODE_FOR_nothing) set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv)); + if (final_dest != target) + emit_move_insn (final_dest, target); + if (prev == 0) first = get_insns (); else diff --git a/contrib/gcc/reload.h b/contrib/gcc/reload.h index 968d3124af49..7bc6ccab89ae 100644 --- a/contrib/gcc/reload.h +++ b/contrib/gcc/reload.h @@ -296,7 +296,7 @@ extern rtx find_equiv_reg PROTO((rtx, rtx, enum reg_class, int, short *, int, enum machine_mode)); /* Return 1 if register REGNO is the subject of a clobber in insn INSN. */ -extern int regno_clobbered_p PROTO((int, rtx)); +extern int regno_clobbered_p PROTO((int, rtx, enum machine_mode, int)); /* Functions in reload1.c: */ @@ -342,3 +342,5 @@ extern void save_call_clobbered_regs PROTO((void)); /* Replace (subreg (reg)) with the appropriate (reg) for any operands. */ extern void cleanup_subreg_operands PROTO ((rtx)); + +extern int earlyclobber_operand_p PROTO((rtx)); diff --git a/contrib/gcc/reload1.c b/contrib/gcc/reload1.c index d9245b0595c0..027accf195c3 100644 --- a/contrib/gcc/reload1.c +++ b/contrib/gcc/reload1.c @@ -420,9 +420,13 @@ static void clear_reload_reg_in_use PROTO((int, int, enum reload_type, enum machine_mode)); static int reload_reg_free_p PROTO((int, int, enum reload_type)); static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int, int)); +static int free_for_value_p PROTO((int, enum machine_mode, int, + enum reload_type, rtx, rtx, + int, int)); static int reload_reg_reaches_end_p PROTO((int, int, enum reload_type)); static int allocate_reload_reg PROTO((struct insn_chain *, int, int, int)); +static int conflicts_with_override PROTO((rtx)); static void choose_reload_regs PROTO((struct insn_chain *)); static void merge_assigned_reloads PROTO((rtx)); static void emit_reload_insns PROTO((struct insn_chain *)); @@ -4518,7 +4522,10 @@ forget_old_reloads_1 (x, ignored) reload reg in the current instruction. */ if (n_reloads == 0 || ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i)) - CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i); + { + CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i); + spill_reg_store[regno + i] = 0; + } } /* Since value of X has changed, @@ -4577,6 +4584,8 @@ reload_reg_class_lower (r1p, r2p) /* The following HARD_REG_SETs indicate when each hard register is used for a reload of various parts of the current insn. */ +/* If reg is unavailable for all reloads. */ +static HARD_REG_SET reload_reg_unavailable; /* If reg is in use as a reload reg for a RELOAD_OTHER reload. */ static HARD_REG_SET reload_reg_used; /* If reg is in use for a RELOAD_FOR_INPUT_ADDRESS reload for operand I. */ @@ -4799,8 +4808,8 @@ reload_reg_free_p (regno, opnum, type) { int i; - /* In use for a RELOAD_OTHER means it's not available for anything. */ - if (TEST_HARD_REG_BIT (reload_reg_used, regno)) + if (TEST_HARD_REG_BIT (reload_reg_used, regno) + || TEST_HARD_REG_BIT (reload_reg_unavailable, regno)) return 0; switch (type) @@ -5133,7 +5142,7 @@ reloads_conflict (r1, r2) return (r2_type == RELOAD_FOR_INSN || r2_type == RELOAD_FOR_OUTPUT || ((r2_type == RELOAD_FOR_OUTPUT_ADDRESS || r2_type == RELOAD_FOR_OUTADDR_ADDRESS) - && r2_opnum >= r1_opnum)); + && r2_opnum <= r1_opnum)); case RELOAD_FOR_INSN: return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_OUTPUT @@ -5171,25 +5180,8 @@ rtx reload_override_in[MAX_RELOADS]; or -1 if we did not need a register for this reload. */ int reload_spill_index[MAX_RELOADS]; -/* Return 1 if the value in reload reg REGNO, as used by a reload - needed for the part of the insn specified by OPNUM and TYPE, - may be used to load VALUE into it. +/* Subroutine of free_for_value_p, used to check a single register. */ - Other read-only reloads with the same value do not conflict - unless OUT is non-zero and these other reloads have to live while - output reloads live. - If OUT is CONST0_RTX, this is a special case: it means that the - test should not be for using register REGNO as reload register, but - for copying from register REGNO into the reload register. - - RELOADNUM is the number of the reload we want to load this value for; - a reload does not conflict with itself. - - When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with - reloads that load an address for the very reload we are considering. - - The caller has to make sure that there is no conflict with the return - register. */ static int reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, ignore_address_reloads) @@ -5201,6 +5193,10 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, int ignore_address_reloads; { int time1; + /* Set if we see an input reload that must not share its reload register + with any new earlyclobber, but might otherwise share the reload + register with an output or input-output reload. */ + int check_earlyclobber = 0; int i; int copy = 0; @@ -5208,7 +5204,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, available as spill registers, including hard registers that are earlyclobbered in asms. As a temporary measure, reject anything in reload_reg_used. */ - if (TEST_HARD_REG_BIT (reload_reg_used, regno)) + if (TEST_HARD_REG_BIT (reload_reg_unavailable, regno)) return 0; if (out == const0_rtx) @@ -5235,7 +5231,8 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, switch (type) { case RELOAD_FOR_OTHER_ADDRESS: - time1 = 0; + /* RELOAD_FOR_OTHER_ADDRESS conflicts with RELOAD_OTHER reloads. */ + time1 = copy ? 0 : 1; break; case RELOAD_OTHER: time1 = copy ? 1 : MAX_RECOG_OPERANDS * 5 + 5; @@ -5327,6 +5324,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, break; case RELOAD_FOR_INPUT: time2 = reload_opnum[i] * 4 + 4; + check_earlyclobber = 1; break; /* reload_opnum[i] * 4 + 4 <= (MAX_RECOG_OPERAND - 1) * 4 + 4 == MAX_RECOG_OPERAND * 4 */ @@ -5339,6 +5337,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, break; case RELOAD_FOR_OPERAND_ADDRESS: time2 = MAX_RECOG_OPERANDS * 4 + 2; + check_earlyclobber = 1; break; case RELOAD_FOR_INSN: time2 = MAX_RECOG_OPERANDS * 4 + 3; @@ -5367,6 +5366,9 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, if (! reload_in[i] || rtx_equal_p (reload_in[i], value)) { time2 = MAX_RECOG_OPERANDS * 4 + 4; + /* Earlyclobbered outputs must conflict with inputs. */ + if (earlyclobber_operand_p (reload_out[i])) + time2 = MAX_RECOG_OPERANDS * 4 + 3; break; } time2 = 1; @@ -5389,9 +5391,71 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, } } } + + /* Earlyclobbered outputs must conflict with inputs. */ + if (check_earlyclobber && out && earlyclobber_operand_p (out)) + return 0; + return 1; } +/* Return 1 if the value in reload reg REGNO, as used by a reload + needed for the part of the insn specified by OPNUM and TYPE, + may be used to load VALUE into it. + + MODE is the mode in which the register is used, this is needed to + determine how many hard regs to test. + + Other read-only reloads with the same value do not conflict + unless OUT is non-zero and these other reloads have to live while + output reloads live. + If OUT is CONST0_RTX, this is a special case: it means that the + test should not be for using register REGNO as reload register, but + for copying from register REGNO into the reload register. + + RELOADNUM is the number of the reload we want to load this value for; + a reload does not conflict with itself. + + When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with + reloads that load an address for the very reload we are considering. + + The caller has to make sure that there is no conflict with the return + register. */ + +static int +free_for_value_p (regno, mode, opnum, type, value, out, reloadnum, + ignore_address_reloads) + int regno; + enum machine_mode mode; + int opnum; + enum reload_type type; + rtx value, out; + int reloadnum; + int ignore_address_reloads; +{ + int nregs = HARD_REGNO_NREGS (regno, mode); + while (nregs-- > 0) + if (! reload_reg_free_for_value_p (regno + nregs, opnum, type, value, out, + reloadnum, ignore_address_reloads)) + return 0; + return 1; +} + +/* Determine whether the reload reg X overlaps any rtx'es used for + overriding inheritance. Return nonzero if so. */ + +static int +conflicts_with_override (x) + rtx x; +{ + int i; + for (i = 0; i < n_reloads; i++) + if (reload_override_in[i] + && reg_overlap_mentioned_p (x, reload_override_in[i])) + return 1; + return 0; +} + /* Find a spill register to use as a reload register for reload R. LAST_RELOAD is non-zero if this is the last reload for the insn being processed. @@ -5472,11 +5536,10 @@ allocate_reload_reg (chain, r, last_reload, noerror) /* We check reload_reg_used to make sure we don't clobber the return register. */ && ! TEST_HARD_REG_BIT (reload_reg_used, regnum) - && reload_reg_free_for_value_p (regnum, - reload_opnum[r], - reload_when_needed[r], - reload_in[r], - reload_out[r], r, 1))) + && free_for_value_p (regnum, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], reload_out[r], r, 1))) && TEST_HARD_REG_BIT (reg_class_contents[class], regnum) && HARD_REGNO_MODE_OK (regnum, reload_mode[r]) /* Look first for regs to share, then for unshared. But @@ -5669,7 +5732,7 @@ choose_reload_regs (chain) CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]); } - IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs); + COMPL_HARD_REG_SET (reload_reg_unavailable, chain->used_spill_regs); #if 0 /* Not needed, now that we can always retry without inheritance. */ /* See if we have more mandatory reloads than spill regs. @@ -5931,10 +5994,9 @@ choose_reload_regs (chain) && (reload_nregs[r] == max_group_size || ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class], i)) - && reload_reg_free_for_value_p (i, reload_opnum[r], - reload_when_needed[r], - reload_in[r], - const0_rtx, r, 1)) + && free_for_value_p (i, reload_mode[r], reload_opnum[r], + reload_when_needed[r], reload_in[r], + const0_rtx, r, 1)) { /* If a group is needed, verify that all the subsequent registers still have their values intact. */ @@ -5968,9 +6030,11 @@ choose_reload_regs (chain) break; if (i1 != n_earlyclobbers - || ! (reload_reg_free_for_value_p - (i, reload_opnum[r], reload_when_needed[r], - reload_in[r], reload_out[r], r, 1)) + || ! (free_for_value_p (i, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], + reload_out[r], r, 1)) /* Don't use it if we'd clobber a pseudo reg. */ || (TEST_HARD_REG_BIT (reg_used_in_insn, i) && reload_out[r] @@ -5992,9 +6056,12 @@ choose_reload_regs (chain) && rtx_equal_p (reload_out[r], reload_reg_rtx[r]))) { - reload_override_in[r] = last_reg; - reload_inheritance_insn[r] - = reg_reloaded_insn[i]; + if (! reload_optional[r]) + { + reload_override_in[r] = last_reg; + reload_inheritance_insn[r] + = reg_reloaded_insn[i]; + } } else { @@ -6072,10 +6139,11 @@ choose_reload_regs (chain) and of the desired class. */ if (equiv != 0 && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno) - && ! reload_reg_free_for_value_p (regno, reload_opnum[r], - reload_when_needed[r], - reload_in[r], - reload_out[r], r, 1)) + && ! free_for_value_p (regno, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], reload_out[r], r, + 1)) || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]], regno))) equiv = 0; @@ -6093,7 +6161,8 @@ choose_reload_regs (chain) if (reg_overlap_mentioned_for_reload_p (equiv, reload_earlyclobbers[i])) { - reload_override_in[r] = equiv; + if (! reload_optional[r]) + reload_override_in[r] = equiv; equiv = 0; break; } @@ -6104,7 +6173,8 @@ choose_reload_regs (chain) In particular, we then can't use EQUIV for a RELOAD_FOR_OUTPUT_ADDRESS reload. */ - if (equiv != 0 && regno_clobbered_p (regno, insn)) + if (equiv != 0 && regno_clobbered_p (regno, insn, + reload_mode[r], 0)) { switch (reload_when_needed[r]) { @@ -6116,13 +6186,32 @@ choose_reload_regs (chain) case RELOAD_OTHER: case RELOAD_FOR_INPUT: case RELOAD_FOR_OPERAND_ADDRESS: - reload_override_in[r] = equiv; + if (! reload_optional[r]) + reload_override_in[r] = equiv; /* Fall through. */ default: equiv = 0; break; } } + else if (regno_clobbered_p (regno, insn, reload_mode[r], 1)) + switch (reload_when_needed[r]) + { + case RELOAD_FOR_OTHER_ADDRESS: + case RELOAD_FOR_INPADDR_ADDRESS: + case RELOAD_FOR_INPUT_ADDRESS: + case RELOAD_FOR_OPADDR_ADDR: + case RELOAD_FOR_OPERAND_ADDRESS: + case RELOAD_FOR_INPUT: + break; + case RELOAD_OTHER: + if (! reload_optional[r]) + reload_override_in[r] = equiv; + /* Fall through. */ + default: + equiv = 0; + break; + } /* If we found an equivalent reg, say no code need be generated to load it, and use it as our reload reg. */ @@ -6283,13 +6372,12 @@ choose_reload_regs (chain) check_reg = reload_override_in[r]; else continue; - if (! reload_reg_free_for_value_p (true_regnum (check_reg), - reload_opnum[r], - reload_when_needed[r], - reload_in[r], - (reload_inherited[r] - ? reload_out[r] : const0_rtx), - r, 1)) + if (! free_for_value_p (true_regnum (check_reg), reload_mode[r], + reload_opnum[r], reload_when_needed[r], + reload_in[r], + (reload_inherited[r] + ? reload_out[r] : const0_rtx), + r, 1)) { if (pass) continue; @@ -6646,10 +6734,10 @@ emit_reload_insns (chain) /* Don't use OLDEQUIV if any other reload changes it at an earlier stage of this insn or at this stage. */ - if (! reload_reg_free_for_value_p (regno, reload_opnum[j], - reload_when_needed[j], - reload_in[j], const0_rtx, j, - 0)) + if (! free_for_value_p (regno, reload_mode[j], + reload_opnum[j], + reload_when_needed[j], + reload_in[j], const0_rtx, j, 0)) oldequiv = 0; /* If it is no cheaper to copy from OLDEQUIV into the @@ -6799,11 +6887,10 @@ emit_reload_insns (chain) && dead_or_set_p (insn, old) /* This is unsafe if some other reload uses the same reg first. */ - && reload_reg_free_for_value_p (REGNO (reloadreg), - reload_opnum[j], - reload_when_needed[j], - old, reload_out[j], - j, 0)) + && ! conflicts_with_override (reloadreg) + && free_for_value_p (REGNO (reloadreg), reload_mode[j], + reload_opnum[j], reload_when_needed[j], + old, reload_out[j], j, 0)) { rtx temp = PREV_INSN (insn); while (temp && GET_CODE (temp) == NOTE) @@ -7112,7 +7199,8 @@ emit_reload_insns (chain) /* We don't need to test full validity of last_regno for inherit here; we only want to know if the store actually matches the pseudo. */ - if (reg_reloaded_contents[last_regno] == pseudo_no + if (TEST_HARD_REG_BIT (reg_reloaded_valid, last_regno) + && reg_reloaded_contents[last_regno] == pseudo_no && spill_reg_store[last_regno] && rtx_equal_p (pseudo, spill_reg_stored_to[last_regno])) delete_output_reload (insn, j, last_regno); @@ -7288,7 +7376,7 @@ emit_reload_insns (chain) || !(set = single_set (insn)) || rtx_equal_p (old, SET_DEST (set)) || !reg_mentioned_p (old, SET_SRC (set)) - || !regno_clobbered_p (REGNO (old), insn)) + || !regno_clobbered_p (REGNO (old), insn, reload_mode[j], 0)) gen_reload (old, reloadreg, reload_opnum[j], reload_when_needed[j]); } diff --git a/contrib/gcc/rtl.h b/contrib/gcc/rtl.h index 8eba5eab5d9d..0f43e87dc751 100644 --- a/contrib/gcc/rtl.h +++ b/contrib/gcc/rtl.h @@ -1084,6 +1084,7 @@ extern int for_each_rtx PROTO((rtx *, rtx_function, void *)); extern rtx regno_use_in PROTO((int, rtx)); extern int auto_inc_p PROTO((rtx)); extern void remove_node_from_expr_list PROTO((rtx, rtx *)); +extern int insns_safe_to_move_p PROTO((rtx, rtx, rtx *)); /* flow.c */ diff --git a/contrib/gcc/rtlanal.c b/contrib/gcc/rtlanal.c index fb4f87c07de3..49131a4efedc 100644 --- a/contrib/gcc/rtlanal.c +++ b/contrib/gcc/rtlanal.c @@ -2289,3 +2289,82 @@ auto_inc_p (x) } return 0; } + +/* Return 1 if the sequence of instructions beginning with FROM and up + to and including TO is safe to move. If NEW_TO is non-NULL, and + the sequence is not already safe to move, but can be easily + extended to a sequence which is safe, then NEW_TO will point to the + end of the extended sequence. + + For now, this function only checks that the region contains whole + exception regiongs, but it could be extended to check additional + conditions as well. */ + +int +insns_safe_to_move_p (from, to, new_to) + rtx from; + rtx to; + rtx *new_to; +{ + int eh_region_count = 0; + int past_to_p = 0; + rtx r = from; + + /* By default, assume the end of the region will be what was + suggested. */ + if (new_to) + *new_to = to; + + while (r) + { + if (GET_CODE (r) == NOTE) + { + switch (NOTE_LINE_NUMBER (r)) + { + case NOTE_INSN_EH_REGION_BEG: + ++eh_region_count; + break; + + case NOTE_INSN_EH_REGION_END: + if (eh_region_count == 0) + /* This sequence of instructions contains the end of + an exception region, but not he beginning. Moving + it will cause chaos. */ + return 0; + + --eh_region_count; + break; + + default: + break; + } + } + else if (past_to_p) + /* If we've passed TO, and we see a non-note instruction, we + can't extend the sequence to a movable sequence. */ + return 0; + + if (r == to) + { + if (!new_to) + /* It's OK to move the sequence if there were matched sets of + exception region notes. */ + return eh_region_count == 0; + + past_to_p = 1; + } + + /* It's OK to move the sequence if there were matched sets of + exception region notes. */ + if (past_to_p && eh_region_count == 0) + { + *new_to = r; + return 1; + } + + /* Go to the next instruction. */ + r = NEXT_INSN (r); + } + + return 0; +} diff --git a/contrib/gcc/stmt.c b/contrib/gcc/stmt.c index f55b2c955ded..914117c85e02 100644 --- a/contrib/gcc/stmt.c +++ b/contrib/gcc/stmt.c @@ -1351,7 +1351,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) } else { - output_rtx[i] = assign_temp (type, 0, 0, 0); + output_rtx[i] = assign_temp (type, 0, 0, 1); TREE_VALUE (tail) = make_tree (type, output_rtx[i]); } diff --git a/contrib/gcc/version.c b/contrib/gcc/version.c index 877d64d8f865..e415651bbb18 100644 --- a/contrib/gcc/version.c +++ b/contrib/gcc/version.c @@ -1 +1 @@ -char *version_string = "2.95.2 19991024 (release)"; +char *version_string = "2.95.3 20010101 (prerelease)";