diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2001-12-05 01:39:41 +0000 |
---|---|---|
committer | Andrew Macleod <amacleod@gcc.gnu.org> | 2001-12-05 01:39:41 +0000 |
commit | 0626ef8add9823d3f8714e3a00d6372ba4f4ff4a (patch) | |
tree | c7ac63b712fa3bf7681fd15b7941fa3e71cdc688 /gcc | |
parent | ee0a48c5e8998fba3a4050c77794ef234793a1d2 (diff) | |
download | gcc-0626ef8add9823d3f8714e3a00d6372ba4f4ff4a.zip gcc-0626ef8add9823d3f8714e3a00d6372ba4f4ff4a.tar.gz gcc-0626ef8add9823d3f8714e3a00d6372ba4f4ff4a.tar.bz2 |
rtl.h (initialize_uninitialized_subregs): New prototype.
2001-12-04 Andrew MacLeod <amacleod@redhat.com>
* rtl.h (initialize_uninitialized_subregs): New prototype.
* toplev.c (rest_of_compilation): Call initialize_uninitialized_subregs
when optimization is on.
* flow.c (find_regno_partial): Find subregs within an expression.
(initialize_uninitialized_subregs): Initialize live on entry registers
which are used in subreg expressions.
From-SVN: r47644
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/flow.c | 108 | ||||
-rw-r--r-- | gcc/rtl.h | 7 | ||||
-rw-r--r-- | gcc/toplev.c | 11 |
4 files changed, 132 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7996d8b..b390614 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2001-12-04 Andrew MacLeod <amacleod@redhat.com> + + * rtl.h (initialize_uninitialized_subregs): New prototype. + * toplev.c (rest_of_compilation): Call initialize_uninitialized_subregs + when optimization is on. + * flow.c (find_regno_partial): Find subregs within an expression. + (initialize_uninitialized_subregs): Initialize live on entry registers + which are used in subreg expressions. + 2001-12-04 Phil Edwards <pme@gcc.gnu.org> * Makefile.in: Add INSTALL_SCRIPT using INSTALL definition. @@ -306,6 +306,8 @@ static void mark_set_regs PARAMS ((struct propagate_block_info *, static void mark_set_1 PARAMS ((struct propagate_block_info *, enum rtx_code, rtx, rtx, rtx, int)); +static int find_regno_partial PARAMS ((rtx *, void *)); + #ifdef HAVE_conditional_execution static int mark_regno_cond_dead PARAMS ((struct propagate_block_info *, int, rtx)); @@ -1290,6 +1292,112 @@ calculate_global_regs_live (blocks_in, blocks_out, flags) free (queue); } + + +/* This structure is used to pass parameters to an 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. */ + +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 (ptr, data) + 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 (GET_CODE (XEXP (*ptr, 0)) == REG && REGNO (XEXP (*ptr, 0)) == reg) + { + param->retval = *ptr; + return 1; + } + break; + + case SUBREG: + if (GET_CODE (SUBREG_REG (*ptr)) == REG + && REGNO (SUBREG_REG (*ptr)) == reg) + { + param->retval = *ptr; + return 1; + } + 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. */ + +int +initialize_uninitialized_subregs () +{ + rtx insn; + edge e; + int reg, did_something = 0; + find_regno_partial_param param; + + for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next) + { + basic_block bb = e->dest; + regset map = bb->global_live_at_start; + EXECUTE_IF_SET_IN_REG_SET (map, + FIRST_PSEUDO_REGISTER, reg, + { + 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 doesnt matter, or hopefully something we dont 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) + { + insn = gen_move_insn (param.retval, + CONST0_RTX (GET_MODE (param.retval))); + insert_insn_on_edge (insn, e); + did_something = 1; + } + } + }); + } + + if (did_something) + commit_edge_insertions (); + return did_something; +} + /* Subroutines of life analysis. */ @@ -1903,10 +1903,11 @@ extern void move_by_pieces PARAMS ((rtx, rtx, unsigned int)); /* In flow.c */ -extern void recompute_reg_usage PARAMS ((rtx, int)); +extern void recompute_reg_usage PARAMS ((rtx, int)); +extern int initialize_uninitialized_subregs PARAMS ((void)); #ifdef BUFSIZ -extern void print_rtl_with_bb PARAMS ((FILE *, rtx)); -extern void dump_flow_info PARAMS ((FILE *)); +extern void print_rtl_with_bb PARAMS ((FILE *, rtx)); +extern void dump_flow_info PARAMS ((FILE *)); #endif /* In expmed.c */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 54582dc..fc2e8b6 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -3017,6 +3017,17 @@ rest_of_compilation (decl) setjmp_args_warning (); } + if (optimize) + { + if (initialize_uninitialized_subregs ()) + { + /* Insns were inserted, so things might look a bit different. */ + insns = get_insns(); + life_analysis (insns, rtl_dump_file, + (PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES)); + } + } + close_dump_file (DFI_life, print_rtl_with_bb, insns); ggc_collect (); |