Kenneth Zadeck - [dataflow]: PATCH COMMITTED to make arm-elf work. (original) (raw)
This is the mail archive of the gcc-patches@gcc.gnu.orgmailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
- From: Kenneth Zadeck
- To: gcc-patches , Seongbae Park , Daniel Berlin , Richard Earnshaw , "Zadeck, Kenneth" , Steven Bosscher
- Date: Fri, 02 Feb 2007 09:28:05 -0500
- Subject: [dataflow]: PATCH COMMITTED to make arm-elf work.
The arm-elf is now regression free on the dataflow branch. This patch has been bootstrapped and regression tested on x86-64, x86-32, ppc and ia-64 linux.
Most of the changes to make the arm work were not actually in the arm port.
ASM_INPUT with no parameters is no longer a acceptable substitute for gen_blockage. Gen_blockage, with no parameters is now required on all platforms. Thanks to stevenb for removing the non conforming parameter to this on the x86s.
The use-def chain version of dce no longer deletes clobbers. These always look dead to a use-def based algorithm regardless of whether they are needed or not.
There are now no FULLY uninitialized pseudos. What was initially done for subregs has now been completely rewritten and renamed init-regs.c. Rather than putting the load of 0 at the top of the function, it is added at the top of the block before the offending use. Note that nothing is done at all for partially initialized uses. The compiler is and has been tolerant of this.
The straw that broke the camels back on this is that the arm (and possibly the ppc) have insns whose constraints cannot be expressed in gcc md language. Specifically they need constraints that say that two parameters cannot be the same register. As it turns out this can only happen in the current allocator if one of the operands happens to be a fully uninitialized use.
It has been discussed that this code should really be changed to use a new rtl type that could then be removed late in the compilation. iant says that this is hard. Currently this is left as an exercise for a new gcc hacker.
In a later commit, i will move this code so that it is before the loop optimizations so that they have a chance to hoist this out of loops. However, this is pretty rare code since it is only added if there are no values that reach the use.
- There was also a change in the way that the LR register and
INCOMING_RETURN_ADDR_RTX are processed.
Minor bug fixes include code that properly adds reg_dead notes if the function is passed a multiword register and the return stores into only part of it and fixing the version of dce that runs as part of df to always process it changes immediately, regardless of what the pass that wants the analysis has set. Otherwise there is confusion deleting reg_equal notes and lastly, fixing the code that numbers the libcalls to not double number some calls.
2007-01-02 Kenneth Zadeck zadeck@naturalbridge.com
* optabs.c (emit_no_conflict_block): Removed redundant code to
number libcalls.
* tree-pass.h (pass_initialize_subregs): Renamed to
pass_initialize_regs.
* passes.c (init_optimization_passes): Ditto.
* builtins.c (expand_builtin_setjmp_receiver): Changed
gen_rtx_ASM_INPUT to gen_blockage.
* function.c (expand_function_end): Ditto.
* stmt.c (gen_non_local_got_receiver): Ditto.
* config/i386.md (blockage): Don't take an operand.
(prologue_use): New.
* config/i386.c (ix86_expand_prologue): Don't build a blockage
insn with an operand. If the PIC reg is used, use a prologue_use
insn to protect it from being removed.
* df-scan.c (df_get_entry_block_def_set): Generate ref for
INCOMING_RETURN_ADDR_RTX after reload_completed.
* df-core.c (df_ref_debug): Fixed formatting.
* init-regs.c: Renamed from subregs_init.c and changed to
initialize all fully uninitialized registers.
* bt-load.c (compute_defs_uses_and_gen): Changed check for
ASM_INPUT to UNSPEC_VOLATILE.
* df-problems.c (df_set_unused_notes_for_mw,
df_set_dead_notes_for_mw, df_ri_bb_compute): Cleaned up reg_notes
debugging info.
(df_set_dead_notes_for_mw): Added do_not_gen to test of all notes
dead.
* Makefile.in (subregs-init.*): Renamed to init-regs.*.
* config/arm/arm.c (arm_expand_prologue, thumb_expand_prologue):
Removed code to generate explicit uses of LR_REGNUM from prologue.
* config/arm/arm.h (EPILOGUE_USES): Made LR_REGNUM unconditionally
added.
* dce.c (deletable_insn_p): Made clobbers always live for use-def
based dce.
(prescan_insns_for_dce, prescan_insns_for_dse): Added fast
parameter to deletable_insn_p.
(run_fast_df_dce): Temporarily turn off DF_DEFER_INSN_RESCAN
during this subphase.
Index: optabs.c
--- optabs.c (revision 121500) +++ optabs.c (working copy) @@ -3437,13 +3437,6 @@ emit_no_conflict_block (rtx insns, rtx t maybe_encapsulate_block (first, last, equiv); - next = NEXT_INSN (last); - for (insn = first; insn != next; insn = NEXT_INSN (insn)) - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LIBCALL_ID, - GEN_INT (libcall_id), - REG_NOTES (insn)); - libcall_id++;
return last; } Index: tree-pass.h
--- tree-pass.h (revision 121500) +++ tree-pass.h (working copy) @@ -365,7 +365,7 @@ extern struct tree_opt_pass pass_subregs extern struct tree_opt_pass pass_inc_dec; extern struct tree_opt_pass pass_no_new_pseudos; extern struct tree_opt_pass pass_stack_ptr_mod; -extern struct tree_opt_pass pass_initialize_subregs; +extern struct tree_opt_pass pass_initialize_regs; extern struct tree_opt_pass pass_combine; extern struct tree_opt_pass pass_if_after_combine; extern struct tree_opt_pass pass_partition_blocks; Index: passes.c
--- passes.c (revision 121500) +++ passes.c (working copy) @@ -681,7 +681,7 @@ init_optimization_passes (void) NEXT_PASS (pass_subregs_of_mode_init); NEXT_PASS (pass_inc_dec); NEXT_PASS (pass_stack_ptr_mod); - NEXT_PASS (pass_initialize_subregs); + NEXT_PASS (pass_initialize_regs); NEXT_PASS (pass_no_new_pseudos); NEXT_PASS (pass_combine); NEXT_PASS (pass_rtl_dse2); Index: builtins.c
--- builtins.c (revision 121500) +++ builtins.c (working copy) @@ -734,12 +734,10 @@ expand_builtin_setjmp_receiver (rtx rece #endif { /* Nothing / } - / @@@ This is a kludge. Not all machine descriptions define a blockage - insn, but we must not allow the code we just generated to be reordered - by scheduling. Specifically, the update of the frame pointer must - happen immediately, not later. So emit an ASM_INPUT to act as blockage - insn. / - emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); + / We must not allow the code we just generated to be reordered by + scheduling. Specifically, the update of the frame pointer must + happen immediately, not later. / + emit_insn (gen_blockage ()); } / __builtin_longjmp is passed a pointer to an array of five words (not Index: function.c
--- function.c (revision 121500) +++ function.c (working copy) @@ -4399,13 +4399,11 @@ expand_function_end (void) } else { - /* @@@ This is a kludge. We want to ensure that instructions that - may trap are not moved into the epilogue by scheduling, because - we don't always emit unwind information for the epilogue. - However, not all machine descriptions define a blockage insn, so - emit an ASM_INPUT to act as one. / + / We want to ensure that instructions that may trap are not + moved into the epilogue by scheduling, because we don't + always emit unwind information for the epilogue. / if (flag_non_call_exceptions) - emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); + emit_insn (gen_blockage ()); } / If this is an implementation of throw, do what's necessary to Index: stmt.c
--- stmt.c (revision 121500) +++ stmt.c (working copy) @@ -1833,12 +1833,10 @@ expand_nl_goto_receiver (void) emit_insn (gen_nonlocal_goto_receiver ()); #endif - /* @@@ This is a kludge. Not all machine descriptions define a blockage - insn, but we must not allow the code we just generated to be reordered - by scheduling. Specifically, the update of the frame pointer must - happen immediately, not later. So emit an ASM_INPUT to act as blockage - insn. / - emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); + / We must not allow the code we just generated to be reordered by + scheduling. Specifically, the update of the frame pointer must + happen immediately, not later. / + emit_insn (gen_blockage ()); } / Generate RTL for the automatic variable declaration DECL. Index: config/i386/i386.c
--- config/i386/i386.c (revision 121500) +++ config/i386/i386.c (working copy) @@ -5709,7 +5709,11 @@ ix86_expand_prologue (void) /* Prevent function calls from be scheduled before the call to mcount. In the pic_reg_used case, make sure that the got load isn't deleted. / if (current_function_profile) - emit_insn (gen_blockage (pic_reg_used ? pic_offset_table_rtx : const0_rtx)); + { + if (pic_reg_used) + emit_insn (gen_prologue_use (pic_offset_table_rtx)); + emit_insn (gen_blockage ()); + } } / Emit code to restore saved registers using MOV insns. First register Index: config/i386/i386.md
--- config/i386/i386.md (revision 121500) +++ config/i386/i386.md (working copy) @@ -171,6 +171,7 @@ (define_constants (UNSPECV_CMPXCHG_2 11) (UNSPECV_XCHG 12) (UNSPECV_LOCK 13) + (UNSPECV_PROLOGUE_USE 14) ]) ;; Registers by name. @@ -14282,7 +14283,7 @@ (define_expand "untyped_call" registers we stored in the result block. We avoid problems by claiming that all hard registers are used and clobbered at this point. */ - emit_insn (gen_blockage (const0_rtx)); + emit_insn (gen_blockage ()); DONE; }) @@ -14293,7 +14294,15 @@ (define_expand "untyped_call" ;; all of memory. This blocks insns from being moved across this point. (define_insn "blockage" - [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_BLOCKAGE)] + [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] + "" + "" + [(set_attr "length" "0")]) + +;; As USE insns aren't meaningful after reload, this is used instead +;; to prevent deleting instructions setting registers for PIC code +(define_insn "prologue_use" + [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_PROLOGUE_USE)] "" "" [(set_attr "length" "0")]) Index: df-scan.c
--- df-scan.c (revision 121500) +++ df-scan.c (working copy) @@ -3286,11 +3286,6 @@ df_get_entry_block_def_set (bitmap entry /* The always important stack pointer. */ bitmap_set_bit (entry_block_defs, STACK_POINTER_REGNUM); -#ifdef INCOMING_RETURN_ADDR_RTX - if (REG_P (INCOMING_RETURN_ADDR_RTX)) - bitmap_set_bit (entry_block_defs, REGNO (INCOMING_RETURN_ADDR_RTX)); -#endif
/* If STATIC_CHAIN_INCOMING_REGNUM == STATIC_CHAIN_REGNUM
only STATIC_CHAIN_REGNUM is defined. If they are different,
we only care about the STATIC_CHAIN_INCOMING_REGNUM. */
@@ -3348,6 +3343,11 @@ df_get_entry_block_def_set (bitmap entry
#endif
}
+#ifdef INCOMING_RETURN_ADDR_RTX
+ if (REG_P (INCOMING_RETURN_ADDR_RTX))
+ bitmap_set_bit (entry_block_defs, REGNO (INCOMING_RETURN_ADDR_RTX));
+#endif
+
targetm.live_on_entry (entry_block_defs);
/* If the function has an incoming STATIC_CHAIN,
Index: df-core.c
--- df-core.c (revision 121500) +++ df-core.c (working copy) @@ -2148,7 +2148,7 @@ df_ref_debug (struct df_ref *ref, FILE * fprintf (file, "%c%d ", DF_REF_REG_DEF_P (ref) ? 'd' : 'u', DF_REF_ID (ref)); - fprintf (file, "reg %d bb %d insn %d flag %x type %x ", + fprintf (file, "reg %d bb %d insn %d flag 0x%x type 0x%x ", DF_REF_REGNO (ref), DF_REF_BBNO (ref), DF_REF_INSN (ref) ? INSN_UID (DF_REF_INSN (ref)) : -1, Index: init-regs.c
--- init-regs.c (revision 121474) +++ init-regs.c (working copy) @@ -1,6 +1,5 @@ -/* Initialization of partially used subregs. - Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +/* Initialization of uninitialized regs. + Copyright (C) 2007 Free Software Foundation, Inc. This file is part of GCC. @@ -33,145 +32,117 @@ Software Foundation, 51 Franklin Street, #include "flags.h" #include "df.h" -/* Add a store of 0 before any subreg load that my reference undefined - bits. This makes combine happy. */
-/* This structure is used to pass parameters to and from the - the function find_regno_partial(). It is used to pass in the - register number we are looking, as well as to return any rtx - we find. */
-static int find_regno_partial (rtx *, void *);
-typedef struct { - unsigned regno_to_find; - rtx retval; -} find_regno_partial_param;
- -/* Find the rtx for the reg numbers specified in 'data' if it is
- part of an expression which only uses part of the register. Return
- it in the structure passed in. */ -static int -find_regno_partial (rtx *ptr, void *data) -{
- find_regno_partial_param *param = (find_regno_partial_param *)data;
- unsigned reg = param->regno_to_find;
- param->retval = NULL_RTX;
- if (*ptr == NULL_RTX)
- return 0;
- switch (GET_CODE (*ptr))
- {
- case ZERO_EXTRACT:
- case SIGN_EXTRACT:
- case STRICT_LOW_PART:
if (REG_P (XEXP (*ptr, 0)) && REGNO (XEXP (*ptr, 0)) == reg)
- {
param->retval = XEXP (*ptr, 0);
return 1;
- }
break;
- case SUBREG:
if (REG_P (SUBREG_REG (*ptr))
&& REGNO (SUBREG_REG (*ptr)) == reg)
- {
param->retval = SUBREG_REG (*ptr);
return 1;
- }
break;
- default:
break;
- }
- return 0; -}
- -/* Process all immediate successors of the entry block looking for pseudo
- registers which are live on entry. Find all of those whose first
- instance is a partial register reference of some kind, and initialize
- them to 0 after the entry block. This will prevent bit sets within
- registers whose value is unknown, and may contain some kind of sticky
- bits we don't want. / +/ Check all of the uses of pseudo variables. If any use that is MUST
- uninitialized, add a store of 0 before it. For subregs, this makes
- combine happy. For full word regs, this makes other optimizations,
- like the register allocator and the reg-stack happy as well as
- papers over some problems on the arm and other processors where
- certain isa constraints cannot be handled by gcc. These are of the
- form where two operands to an insn my not be the same. The ra will
- only make them the same if they do not interfere, and this can only
- happen if one is not initialized.
- There is also the unfortunate consequence that this may mask some
- buggy programs where people forget to initialize stack variable.
- Any programmer with half a brain would look at the uninitialized
- variable warnings. */
static void -initialize_uninitialized_subregs (void) +initialize_uninitialized_regs (void) { - rtx insn; - edge e; - unsigned reg; + basic_block bb; bool did_something = false; - find_regno_partial_param param; - edge_iterator ei; + bitmap already_genned = BITMAP_ALLOC (NULL); + df_analyze (); - FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) + FOR_EACH_BB (bb) { - basic_block bb = e->dest; - regset map = DF_LIVE_IN (bb); - reg_set_iterator rsi; + rtx first_insn = NULL; + rtx insn; + bitmap lr = DF_LR_IN (bb); + bitmap ur = DF_UR_IN (bb); + bitmap_clear (already_genned); - EXECUTE_IF_SET_IN_REG_SET (map, FIRST_PSEUDO_REGISTER, reg, rsi) + FOR_BB_INSNS (bb, insn) { - int uid = REGNO_FIRST_UID (reg); - rtx i; + unsigned int uid = INSN_UID (insn); + struct df_ref *use_rec; + if (!INSN_P (insn)) + continue; + + / find a place to insert the move. / + if (!first_insn) + first_insn = insn; - / Find an insn which mentions the register we are looking for. - Its preferable to have an instance of the register's rtl since - there may be various flags set which we need to duplicate. - If we can't find it, its probably an automatic whose initial - value doesn't matter, or hopefully something we don't care about. */ - for (i = get_insns (); i && INSN_UID (i) != uid; i = NEXT_INSN (i)) - ; - if (i != NULL_RTX) + for (use_rec = DF_INSN_UID_USES (uid); use_rec; use_rec++) { - / Found the insn, now get the REG rtx, if we can. */ - param.regno_to_find = reg; - for_each_rtx (&i, find_regno_partial, ¶m); - if (param.retval != NULL_RTX) + struct df_ref *use = use_rec; + unsigned int regno = DF_REF_REGNO (use); + + / Only do this for the pseudos. / + if (regno < FIRST_PSEUDO_REGISTER) + continue; + + /* Do not generate multiple moves for the same regno. + This is common for sequences of subreg operations. + They would be deleted during combine but there is no + reason to churn the system. */ + if (bitmap_bit_p (already_genned, regno)) + continue; + + /* A use is MUST uninitialized if it reaches the top of + the block from the inside of the block (the lr test) + and no def for it reaches the top of the block from + outside of the block (the ur test). */ + if (bitmap_bit_p (lr, regno) + && (!bitmap_bit_p (ur, regno))) { + rtx move_insn; + rtx reg = DF_REF_REAL_REG (use); + + bitmap_set_bit (already_genned, regno); + start_sequence (); - emit_move_insn (param.retval, - CONST0_RTX (GET_MODE (param.retval))); - insn = get_insns (); + emit_move_insn (reg, CONST0_RTX (GET_MODE (reg))); + move_insn = get_insns (); end_sequence (); - insert_insn_on_edge (insn, e); + add_insn_before (move_insn, first_insn, bb); did_something = true; + if (dump_file) + fprintf (dump_file, + "adding initialization of reg %d at top of block %d for insn %d.\n", + regno, bb->index, uid); } } } } + BITMAP_FREE (already_genned); if (did_something) - { - commit_edge_insertions (); - allocate_reg_life_data (); - } + allocate_reg_life_data (); } static bool -gate_initialize_subregs (void) +gate_initialize_regs (void) { return optimize > 0; } static unsigned int -rest_of_handle_initialize_subregs (void) +rest_of_handle_initialize_regs (void) { no_new_pseudos = 0; - initialize_uninitialized_subregs (); + initialize_uninitialized_regs (); no_new_pseudos = 1; return 0; } -struct tree_opt_pass pass_initialize_subregs = +struct tree_opt_pass pass_initialize_regs = { - "init-subreg", / name / - gate_initialize_subregs, / gate / - rest_of_handle_initialize_subregs, / execute / + "init-regs", / name / + gate_initialize_regs, / gate / + rest_of_handle_initialize_regs, / execute / NULL, / sub / NULL, / next / 0, / static_pass_number / @@ -180,6 +151,7 @@ struct tree_opt_pass pass_initialize_sub 0, / properties_provided / 0, / properties_destroyed / 0, / todo_flags_start / - 0, / todo_flags_finish / + TODO_dump_func | + TODO_df_finish, / todo_flags_finish / 0 / letter */ }; Index: bt-load.c
--- bt-load.c (revision 121500) +++ bt-load.c (working copy) @@ -512,7 +512,7 @@ compute_defs_uses_and_gen (fibheap_t all } /* Check for the blockage emitted by expand_nl_goto_receiver. */ else if (current_function_has_nonlocal_label - && GET_CODE (PATTERN (insn)) == ASM_INPUT) + && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE) { btr_user user; Index: subregs-init.c
--- subregs-init.c (revision 121500) +++ subregs-init.c (working copy) @@ -1,185 +0,0 @@ -/* Initialization of partially used subregs. - Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, - Inc.
-This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version.
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details.
-You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */
-#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "tree.h" -#include "rtl.h" -#include "regs.h" -#include "expr.h" -#include "tree-pass.h" -#include "basic-block.h" -#include "flags.h" -#include "df.h"
-/* Add a store of 0 before any subreg load that my reference undefined - bits. This makes combine happy. */
-/* This structure is used to pass parameters to and from the - the function find_regno_partial(). It is used to pass in the - register number we are looking, as well as to return any rtx - we find. */
-static int find_regno_partial (rtx *, void *);
-typedef struct { - unsigned regno_to_find; - rtx retval; -} find_regno_partial_param;
- -/* Find the rtx for the reg numbers specified in 'data' if it is
- part of an expression which only uses part of the register. Return
- it in the structure passed in. */ -static int -find_regno_partial (rtx *ptr, void *data) -{
- find_regno_partial_param *param = (find_regno_partial_param *)data;
- unsigned reg = param->regno_to_find;
- param->retval = NULL_RTX;
- if (*ptr == NULL_RTX)
- return 0;
- switch (GET_CODE (*ptr))
- {
- case ZERO_EXTRACT:
- case SIGN_EXTRACT:
- case STRICT_LOW_PART:
if (REG_P (XEXP (*ptr, 0)) && REGNO (XEXP (*ptr, 0)) == reg)
- {
param->retval = XEXP (*ptr, 0);
return 1;
- }
break;
- case SUBREG:
if (REG_P (SUBREG_REG (*ptr))
&& REGNO (SUBREG_REG (*ptr)) == reg)
- {
param->retval = SUBREG_REG (*ptr);
return 1;
- }
break;
- default:
break;
- }
- return 0; -}
- -/* Process all immediate successors of the entry block looking for pseudo
- registers which are live on entry. Find all of those whose first
- instance is a partial register reference of some kind, and initialize
- them to 0 after the entry block. This will prevent bit sets within
- registers whose value is unknown, and may contain some kind of sticky
- bits we don't want. */
- -static void -initialize_uninitialized_subregs (void) -{
- rtx insn;
- edge e;
- unsigned reg;
- bool did_something = false;
- find_regno_partial_param param;
- edge_iterator ei;
- df_analyze ();
- FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
- {
basic_block bb = e->dest;
regset map = DF_LIVE_IN (bb);
reg_set_iterator rsi;
EXECUTE_IF_SET_IN_REG_SET (map, FIRST_PSEUDO_REGISTER, reg, rsi)
- {
int uid = REGNO_FIRST_UID (reg);
rtx i;
/* Find an insn which mentions the register we are looking for.
Its preferable to have an instance of the register's rtl since
there may be various flags set which we need to duplicate.
If we can't find it, its probably an automatic whose initial
value doesn't matter, or hopefully something we don't care about. */
for (i = get_insns (); i && INSN_UID (i) != uid; i = NEXT_INSN (i))
;
if (i != NULL_RTX)
{
/* Found the insn, now get the REG rtx, if we can. */
param.regno_to_find = reg;
for_each_rtx (&i, find_regno_partial, ¶m);
if (param.retval != NULL_RTX)
{
start_sequence ();
emit_move_insn (param.retval,
CONST0_RTX (GET_MODE (param.retval)));
insn = get_insns ();
end_sequence ();
insert_insn_on_edge (insn, e);
did_something = true;
}
}
- }
- }
- if (did_something)
- {
commit_edge_insertions ();
allocate_reg_life_data ();
- }
-}
-static bool -gate_initialize_subregs (void) -{ - return optimize > 0; -}
-static unsigned int -rest_of_handle_initialize_subregs (void) -{ - no_new_pseudos = 0; - initialize_uninitialized_subregs (); - no_new_pseudos = 1; - return 0; -}
-struct tree_opt_pass pass_initialize_subregs = -{ - "init-subreg", /* name / - gate_initialize_subregs, / gate / - rest_of_handle_initialize_subregs, / execute / - NULL, / sub / - NULL, / next / - 0, / static_pass_number / - 0, / tv_id / - 0, / properties_required / - 0, / properties_provided / - 0, / properties_destroyed / - 0, / todo_flags_start / - 0, / todo_flags_finish / - 0 / letter */ -}; Index: df-problems.c
--- df-problems.c (revision 121500)
+++ df-problems.c (working copy)
@@ -1,5 +1,5 @@
/* Standard problems for dataflow support routines.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Originally contributed by Michael P. Hayes
(m.hayes@elec.canterbury.ac.nz, mhayes@redhat.com)
@@ -44,11 +44,11 @@ Software Foundation, 51 Franklin Street,
#include "df.h"
#include "except.h"
#include "dce.h"
+#include "vecprim.h"
#if 0
#define REG_DEAD_DEBUGGING
#endif
-#include "vecprim.h"
#define DF_SPARSE_THRESHOLD 32
@@ -4111,10 +4111,8 @@ df_set_unused_notes_for_mw (rtx insn, st
#ifdef REG_DEAD_DEBUGGING
if (dump_file)
- {
- fprintf (dump_file, "mw unused looking at %d\n", DF_REF_REGNO (regs->ref));
- df_ref_debug (regs->ref, dump_file);
- }
+ fprintf (dump_file, "mw_set_unused looking at mws[%d..%d]\n",
+ mws->start_regno, mws->end_regno);
#endif
for (r=mws->start_regno; r <= mws->end_regno; r++)
if ((bitmap_bit_p (live, r))
@@ -4171,19 +4169,25 @@ df_set_dead_notes_for_mw (rtx insn, stru
bitmap artificial_uses, enum df_ri_flags flags)
{
bool all_dead = true;
- unsigned int r = mws->start_regno;
+ unsigned int r;
#ifdef REG_DEAD_DEBUGGING
if (dump_file)
{
- fprintf (dump_file, "mw looking at %d\n", regno);
- df_ref_debug (regs->ref, dump_file);
+ fprintf (dump_file, "mw_set_dead looking at mws[%d..%d]\n do_not_gen =",
+ mws->start_regno, mws->end_regno);
+ df_print_regset (dump_file, do_not_gen);
+ fprintf (dump_file, " live =");
+ df_print_regset (dump_file, live);
+ fprintf (dump_file, " artificial uses =");
+ df_print_regset (dump_file, artificial_uses);
}
#endif
for (r = mws->start_regno; r <= mws->end_regno; r++)
if ((bitmap_bit_p (live, r))
- || bitmap_bit_p (artificial_uses, r))
+ || bitmap_bit_p (artificial_uses, r)
+ || bitmap_bit_p (do_not_gen, r))
{
all_dead = false;
break;
@@ -4209,19 +4213,21 @@ df_set_dead_notes_for_mw (rtx insn, stru
else
{
for (r = mws->start_regno; r <= mws->end_regno; r++)
- if ((!bitmap_bit_p (live, r))
- && (!bitmap_bit_p (artificial_uses, r))
- && (!bitmap_bit_p (do_not_gen, r)))
- {
- rtx note = alloc_EXPR_LIST (REG_DEAD, regno_reg_rtx[r],
- REG_NOTES (insn));
- REG_NOTES (insn) = note;
- if (flags & DF_RI_LIFE)
- REG_N_DEATHS (r)++;
+ {
+ if ((!bitmap_bit_p (live, r))
+ && (!bitmap_bit_p (artificial_uses, r))
+ && (!bitmap_bit_p (do_not_gen, r)))
+ {
+ rtx note = alloc_EXPR_LIST (REG_DEAD, regno_reg_rtx[r],
+ REG_NOTES (insn));
+ REG_NOTES (insn) = note;
+ if (flags & DF_RI_LIFE)
+ REG_N_DEATHS (r)++;
#ifdef REG_DEAD_DEBUGGING
- print_note ("adding 2: ", insn, note);
+ print_note ("adding 2: ", insn, note);
#endif
- }
+ }
+ }
}
}
@@ -4320,6 +4326,14 @@ df_ri_bb_compute (unsigned int bb_index,
bitmap_copy (live, DF_LIVE_OUT (bb));
bitmap_clear (artificial_uses);
+#ifdef REG_DEAD_DEBUGGING
+ if (dump_file)
+ {
+ fprintf (dump_file, "live at bottom ");
+ df_print_regset (dump_file, live);
+ }
+#endif
+
if (df_ri_problem_p (DF_RI_LIFE))
{
/* Process the regs live at the end of the block. Mark them as
@@ -4335,6 +4349,9 @@ df_ri_bb_compute (unsigned int bb_index,
for (def_rec = df_get_artificial_defs (bb_index); *def_rec; def_rec++)
{
struct df_ref *def = def_rec;
+ if (dump_file)
+ fprintf (dump_file, "artificial def %d\n", DF_REF_REGNO (def));
+
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
bitmap_clear_bit (live, DF_REF_REGNO (def));
}
@@ -4353,6 +4370,14 @@ df_ri_bb_compute (unsigned int bb_index,
}
}
+#ifdef REG_DEAD_DEBUGGING
+ if (dump_file)
+ {
+ fprintf (dump_file, "live before artificials out ");
+ df_print_regset (dump_file, live);
+ }
+#endif
+
FOR_BB_INSNS_REVERSE (bb, insn)
{
unsigned int uid = INSN_UID (insn);
@@ -4383,6 +4408,13 @@ df_ri_bb_compute (unsigned int bb_index,
/ Process the defs. /
if (CALL_P (insn))
{
+#ifdef REG_DEAD_DEBUGGING
+ if (dump_file)
+ {
+ fprintf (dump_file, "processing call %d\n live =", INSN_UID (insn));
+ df_print_regset (dump_file, live);
+ }
+#endif
if (df_ri_problem_p (DF_RI_LIFE | DF_RI_SETJMP))
{
bool can_throw = can_throw_internal (insn);
@@ -4412,7 +4444,7 @@ df_ri_bb_compute (unsigned int bb_index,
}
/ We only care about real sets for calls. Clobbers only
- may clobber and cannot be depended on. */
+ may clobbers cannot be depended on. */
mws_rec = DF_INSN_UID_MWS (uid);
while (*mws_rec)
{
Index: Makefile.in
--- Makefile.in (revision 121500)
+++ Makefile.in (working copy)
@@ -1002,10 +1002,11 @@ OBJS-common =
dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o
expmed.o expr.o final.o fold-const.o function.o fwprop.o gcse.o
genrtl.o ggc-common.o global.o graph.o gtype-desc.o
- haifa-sched.o hooks.o ifcvt.o insn-attrtab.o insn-emit.o insn-modes.o
+ haifa-sched.o hooks.o ifcvt.o init-regs.o
+ insn-attrtab.o insn-emit.o insn-modes.o
insn-extract.o insn-opinit.o insn-output.o insn-peep.o insn-recog.o
integrate.o intl.o jump.o langhooks.o lcm.o lists.o local-alloc.o
- mode-switching.o modulo-sched.o optabs.o options.o opts.o opts-common.o
+ mode-switching.o modulo-sched.o optabs.o options.o opts.o opts-common.o
params.o postreload.o postreload-gcse.o predict.o
insn-preds.o insn-automata.o pointer-set.o
print-rtl.o print-tree.o profile.o value-prof.o var-tracking.o
@@ -1014,7 +1015,7 @@ OBJS-common =
sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o
see.o simplify-rtx.o sreal.o stack-ptr-mod.o stmt.o stor-layout.o
stringpool.o
- struct-equiv.o subregs-init.o targhooks.o timevar.o toplev.o tracer.o
+ struct-equiv.o targhooks.o timevar.o toplev.o tracer.o
tree.o tree-dump.o
varasm.o varray.o vec.o version.o vmsdbgout.o xcoffout.o alloc-pool.o
et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o passes.o
@@ -2569,7 +2570,7 @@ alias.o : alias.c (CONFIGH)(CONFIG_H) (CONFIGH)(SYSTEM_H
stack-ptr-mod.o : stack-ptr-mod.c (CONFIGH)(CONFIG_H) (CONFIGH)(SYSTEM_H) coretypes.h
(TMH)(TM_H) (TMH)(TREE_H) (RTLH)(RTL_H) (RTLH)(REGS_H) $(EXPR_H) tree-pass.h
(BASICBLOCKH)(BASIC_BLOCK_H) (BASICBLOCKH)(FLAGS_H) output.h $(DF_H)
-subregs-init.o : subregs-init.c (CONFIGH)(CONFIG_H) (CONFIGH)(SYSTEM_H) coretypes.h
+init-regs.o : init-regs.c (CONFIGH)(CONFIG_H) (CONFIGH)(SYSTEM_H) coretypes.h
(TMH)(TM_H) (TMH)(TREE_H) (RTLH)(RTL_H) (RTLH)(REGS_H) $(EXPR_H) tree-pass.h
(BASICBLOCKH)(BASIC_BLOCK_H) (BASICBLOCKH)(FLAGS_H) $(DF_H)
regmove.o : regmove.c (CONFIGH)(CONFIG_H) (CONFIGH)(SYSTEM_H) coretypes.h (TMH)(TM_H) (TMH)(RTL_H)
Index: config/arm/arm.c
--- config/arm/arm.c (revision 121500) +++ config/arm/arm.c (working copy) @@ -10920,10 +10920,7 @@ arm_expand_prologue (void) /* If the link register is being kept alive, with the return address in it, then make sure that it does not get reused by the ce2 pass. / if ((live_regs_mask & (1 << LR_REGNUM)) == 0) - { - emit_insn (gen_prologue_use (gen_rtx_REG (SImode, LR_REGNUM))); - cfun->machine->lr_save_eliminated = 1; - } + cfun->machine->lr_save_eliminated = 1; } / If CODE is 'd', then the X is a condition operand and the instruction @@ -13816,11 +13813,6 @@ thumb_expand_prologue (void) cfun->machine->lr_save_eliminated = !thumb_force_lr_save (); if (live_regs_mask & 0xff) cfun->machine->lr_save_eliminated = 0;
- /* If the link register is being kept alive, with the return address in it,
then make sure that it does not get reused by the ce2 pass. */
- if (cfun->machine->lr_save_eliminated)
- emit_insn (gen_prologue_use (gen_rtx_REG (SImode, LR_REGNUM)));
} Index: config/arm/arm.h
--- config/arm/arm.h (revision 121500) +++ config/arm/arm.h (working copy) @@ -1566,7 +1566,7 @@ typedef struct frame. / #define EXIT_IGNORE_STACK 1 -#define EPILOGUE_USES(REGNO) (reload_completed && (REGNO) == LR_REGNUM) +#define EPILOGUE_USES(REGNO) ((REGNO) == LR_REGNUM) / Determine if the epilogue should be output as RTL. You should override this if you define FUNCTION_EXTRA_EPILOGUE. */ Index: dce.c
--- dce.c (revision 121500) +++ dce.c (working copy) @@ -59,7 +59,7 @@ static bitmap marked = NULL; DCE pass. */
static bool -deletable_insn_p (rtx insn) +deletable_insn_p (rtx insn, bool fast) { rtx x;
@@ -78,11 +78,19 @@ deletable_insn_p (rtx insn) return false;
case CLOBBER:
/* A CLOBBER of a dead pseudo register serves no purpose.
That is not necessarily true for hard registers until
after reload. */
x = XEXP (PATTERN (insn), 0);
return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed);
if (fast)
{
/* A CLOBBER of a dead pseudo register serves no purpose.
That is not necessarily true for hard registers until
after reload. */
x = XEXP (PATTERN (insn), 0);
return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed);
}
else
/* Because of the way that use-def chains are built, it is not
possible to tell if the clobber is dead because it can
never be the target of a use-def chain. */
return false;
default: if (!NONJUMP_INSN_P (insn))
@@ -344,7 +352,7 @@ prescan_insns_for_dce (void) FOR_BB_INSNS (bb, insn) if (INSN_P (insn)) { - if (deletable_insn_p (insn)) + if (deletable_insn_p (insn, true)) mark_nonreg_stores (PATTERN (insn), insn, true); else { @@ -732,11 +740,16 @@ rest_of_handle_fast_dce (void) void run_fast_df_dce (void) {
- /* If dce is able to delete something, it has to happen immediately.
Otherwise there will be problems handling the eq_notes. */
- enum df_changeable_flags old_flags = df_clear_flags (DF_DEFER_INSN_RESCAN);
- df_in_progress = true; init_dce (true); fast_dce (); BITMAP_FREE (marked); df_in_progress = false;
- df_set_flags (old_flags); }
@@ -1699,7 +1712,7 @@ prescan_insns_for_dse (void) { if (INSN_P (insn)) { - if (!deletable_insn_p (insn)) + if (!deletable_insn_p (insn, false)) { rtx note = find_reg_note (insn, REG_LIBCALL_ID, NULL_RTX); if (note)
- Follow-Ups:
- Re: [dataflow]: PATCH COMMITTED to make arm-elf work.
* From: Paolo Bonzini
- Re: [dataflow]: PATCH COMMITTED to make arm-elf work.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |