From: Bernd Schmidt Date: Thu, 25 Jan 2001 13:12:20 +0000 (+0000) Subject: Backport RTL sharing fixes X-Git-Tag: prereleases/gcc-2.95.3-test3~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8a3ad2d534366f48692c9189b1f42d1dab0dd241;p=thirdparty%2Fgcc.git Backport RTL sharing fixes From-SVN: r39263 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 42c6103f310c..a0908c97565d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -4,6 +4,33 @@ constant pool, also put it on forced_labels list so that it won't be deleted. + 2000-05-25 Alexandre Oliva + * emit-rtl.c (reset_used_decls): New function. + (unshare_all_rtl_again): Call it. + + 2000-05-24 Alexandre Oliva + * emit-rtl.c (unshare_all_decls): New function. + (unshare_all_rtl): Call it. + + 2000-05-20 Alexandre Oliva + * emit-rtl.c (unshare_all_rtl): Store the copied rtx. + + 2000-04-15 Richard Earnshaw (rearnsah@arm.com) + * emit-rtl.c (unshare_all_rtl_again): Unmark everything, then + call unshare_all_rtl. + + 2000-01-27 Geoffrey Keating + * emit-rtl.c (unshare_all_rtl): Unshare virtual parameters too. + Use unshare_all_rtl_1. + (unshare_all_rtl_again): New function. + (unshare_all_rtl_1): New function split out of unshare_all_rtl. + * function.c (purge_addressof_1): Use unshare_all_rtl_again + rather than resetting the 'used' flags ourself. + * toplev.c (rest_of_compilation): Add current_function_decl + to the unshare_all_rtl call. + * tree.h: Prototype unshare_all_rtl. + * rtl.h: Prototype unshare_all_rtl_again here. + 2001-01-12 Bernd Schmidt * version.c: Bump. diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 54cee163738a..58029ab87b9a 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -248,6 +248,9 @@ extern int emit_lineno; static rtx make_jump_insn_raw PROTO((rtx)); static rtx make_call_insn_raw PROTO((rtx)); static rtx find_line_note PROTO((rtx)); +static void unshare_all_rtl_1 PROTO((rtx)); +static void unshare_all_decls PROTO((tree)); +static void reset_used_decls PROTO((tree)); rtx gen_rtx_CONST_INT (mode, arg) @@ -1767,23 +1770,29 @@ restore_emit_status (p) free_insn = 0; } -/* Go through all the RTL insn bodies and copy any invalid shared structure. - It does not work to do this twice, because the mark bits set here - are not cleared afterwards. */ +/* Go through all the RTL insn bodies and copy any invalid shared + structure. This routine should only be called once. */ void -unshare_all_rtl (insn) - register rtx insn; +unshare_all_rtl (fndecl, insn) + tree fndecl; + rtx insn; { - for (; insn; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN - || GET_CODE (insn) == CALL_INSN) - { - PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn)); - REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn)); - LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn)); - } + tree decl; + + /* Make sure that virtual stack slots are not shared. */ + reset_used_decls (DECL_INITIAL (current_function_decl)); + + /* Make sure that virtual parameters are not shared. */ + for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl)) + DECL_RTL (decl) = copy_rtx_if_shared (DECL_RTL (decl)); + /* Make sure that virtual stack slots are not shared. */ + unshare_all_decls (DECL_INITIAL (fndecl)); + + /* Unshare just about everything else. */ + unshare_all_rtl_1 (insn); + /* Make sure the addresses of stack slots found outside the insn chain (such as, in DECL_RTL of a variable) are not shared with the insn chain. @@ -1791,8 +1800,76 @@ unshare_all_rtl (insn) This special care is necessary when the stack slot MEM does not actually appear in the insn chain. If it does appear, its address is unshared from all else at that point. */ + stack_slot_list = copy_rtx_if_shared (stack_slot_list); +} + +/* Go through all the RTL insn bodies and copy any invalid shared + structure, again. This is a fairly expensive thing to do so it + should be done sparingly. */ + +void +unshare_all_rtl_again (insn) + rtx insn; +{ + rtx p; + for (p = insn; p; p = NEXT_INSN (p)) + if (GET_RTX_CLASS (GET_CODE (p)) == 'i') + { + reset_used_flags (PATTERN (p)); + reset_used_flags (REG_NOTES (p)); + reset_used_flags (LOG_LINKS (p)); + } + unshare_all_rtl_1 (insn); +} + +/* Go through all the RTL insn bodies and copy any invalid shared structure. + Assumes the mark bits are cleared at entry. */ + +static void +unshare_all_rtl_1 (insn) + rtx insn; +{ + for (; insn; insn = NEXT_INSN (insn)) + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') + { + PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn)); + REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn)); + LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn)); + } +} + +/* Go through all virtual stack slots of a function and copy any + shared structure. */ +static void +unshare_all_decls (blk) + tree blk; +{ + tree t; + + /* Copy shared decls. */ + for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t)) + DECL_RTL (t) = copy_rtx_if_shared (DECL_RTL (t)); + + /* Now process sub-blocks. */ + for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t)) + unshare_all_decls (t); +} + +/* Go through all virtual stack slots of a function and mark them as + not shared. */ +static void +reset_used_decls (blk) + tree blk; +{ + tree t; + + /* Mark decls. */ + for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t)) + reset_used_flags (DECL_RTL (t)); - copy_rtx_if_shared (stack_slot_list); + /* Now process sub-blocks. */ + for (t = BLOCK_SUBBLOCKS (blk); t; t = TREE_CHAIN (t)) + reset_used_decls (t); } /* Mark ORIG as in use, and return a copy of it if it was already in use. diff --git a/gcc/function.c b/gcc/function.c index a4033a9a6b83..1bcb3060a993 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3221,13 +3221,7 @@ purge_addressof_1 (loc, insn, force, store, ht) /* Make sure to unshare any shared rtl that store_bit_field might have created. */ - for (p = get_insns(); p; p = NEXT_INSN (p)) - { - reset_used_flags (PATTERN (p)); - reset_used_flags (REG_NOTES (p)); - reset_used_flags (LOG_LINKS (p)); - } - unshare_all_rtl (get_insns ()); + unshare_all_rtl_again (get_insns ()); seq = gen_sequence (); end_sequence (); @@ -3479,6 +3473,20 @@ purge_addressof (insns) hash_table_free (&ht); purge_bitfield_addressof_replacements = 0; purge_addressof_replacements = 0; + + /* REGs are shared. purge_addressof will destructively replace a REG + with a MEM, which creates shared MEMs. + + Unfortunately, the children of put_reg_into_stack assume that MEMs + referring to the same stack slot are shared (fixup_var_refs and + the associated hash table code). + + So, we have to do another unsharing pass after we have flushed any + REGs that had their address taken into the stack. + + It may be worth tracking whether or not we converted any REGs into + MEMs to avoid this overhead when it is not needed. */ + unshare_all_rtl_again (get_insns ()); } /* Pass through the INSNS of function FNDECL and convert virtual register diff --git a/gcc/rtl.h b/gcc/rtl.h index 0f43e87dc751..377dc54e8b58 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1391,7 +1391,7 @@ extern int subreg_realpart_p PROTO ((rtx)); extern void reverse_comparison PROTO ((rtx)); extern void set_new_first_and_last_insn PROTO ((rtx, rtx)); extern void set_new_first_and_last_label_num PROTO ((int, int)); -extern void unshare_all_rtl PROTO ((rtx)); +extern void unshare_all_rtl_again PROTO ((rtx)); extern void set_last_insn PROTO ((rtx)); extern void link_cc0_insns PROTO ((rtx)); extern void add_insn PROTO ((rtx)); diff --git a/gcc/toplev.c b/gcc/toplev.c index 242a73cb8608..b50288e80305 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -3816,7 +3816,7 @@ rest_of_compilation (decl) /* Copy any shared structure that should not be shared. */ - unshare_all_rtl (insns); + unshare_all_rtl (current_function_decl, insns); #ifdef SETJMP_VIA_SAVE_AREA /* This must be performed before virutal register instantiation. */ diff --git a/gcc/tree.h b/gcc/tree.h index 0d7ea84aafc4..1a916e2047f5 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2207,6 +2207,7 @@ extern tree reorder_blocks PROTO ((tree *, tree, struct rtx_def *)); extern void free_temps_for_rtl_expr PROTO ((tree)); extern void instantiate_virtual_regs PROTO ((tree, struct rtx_def *)); +extern void unshare_all_rtl PROTO ((tree, struct rtx_def *)); extern int max_parm_reg_num PROTO ((void)); extern void push_function_context PROTO ((void)); extern void pop_function_context PROTO ((void));