diff options
author | Andrew Haley <aph@redhat.com> | 2000-09-18 19:27:37 +0000 |
---|---|---|
committer | Andrew Haley <aph@gcc.gnu.org> | 2000-09-18 19:27:37 +0000 |
commit | 659e47fb241303d55e264111360d41aa132947e1 (patch) | |
tree | 614e4aa4487dc0588a17968047aee0e298b20627 /gcc | |
parent | f2f90c63c8832dcf581120672567453b8e062d7a (diff) | |
download | gcc-659e47fb241303d55e264111360d41aa132947e1.zip gcc-659e47fb241303d55e264111360d41aa132947e1.tar.gz gcc-659e47fb241303d55e264111360d41aa132947e1.tar.bz2 |
toplev.c (rest_of_compilation): Call purge_hard_subreg_sets to remove all SETs of SUBREGs of hard registers.
2000-09-15 Andrew Haley <aph@redhat.com>
* toplev.c (rest_of_compilation): Call purge_hard_subreg_sets to
remove all SETs of SUBREGs of hard registers.
* function.c (purge_hard_subreg_sets): New function.
(purge_single_hard_subreg_set): New function.
* rtl.h: (purge_hard_subreg_sets): New function.
From-SVN: r36511
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/function.c | 66 | ||||
-rw-r--r-- | gcc/rtl.h | 1 | ||||
-rw-r--r-- | gcc/toplev.c | 11 |
4 files changed, 82 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4c0edc7..4e99ee9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2000-09-15 Andrew Haley <aph@redhat.com> + + * toplev.c (rest_of_compilation): Call purge_hard_subreg_sets to + remove all SETs of SUBREGs of hard registers. + * function.c (purge_hard_subreg_sets): New function. + (purge_single_hard_subreg_set): New function. + * rtl.h: (purge_hard_subreg_sets): New function. + 2000-09-18 Richard Henderson <rth@cygnus.com> * config/ia64/ia64-protos.h: Update. diff --git a/gcc/function.c b/gcc/function.c index 6a9bdc9..969887f 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -294,6 +294,7 @@ static void emit_return_into_block PARAMS ((basic_block, rtx)); static void put_addressof_into_stack PARAMS ((rtx, struct hash_table *)); static boolean purge_addressof_1 PARAMS ((rtx *, rtx, int, int, struct hash_table *)); +static void purge_single_hard_subreg_set PARAMS ((rtx)); #ifdef HAVE_epilogue static void keep_stack_depressed PARAMS ((rtx)); #endif @@ -3393,6 +3394,71 @@ purge_addressof (insns) unshare_all_rtl_again (get_insns ()); } +/* Convert a SET of a hard subreg to a set of the appropriet hard + register. A subroutine of purge_hard_subreg_sets. */ + +static void +purge_single_hard_subreg_set (pattern) + rtx pattern; +{ + rtx reg = SET_DEST (pattern); + enum machine_mode mode = GET_MODE (SET_DEST (pattern)); + int word = 0; + + while (GET_CODE (reg) == SUBREG) + { + word += SUBREG_WORD (reg); + reg = SUBREG_REG (reg); + } + + if (REGNO (reg) < FIRST_PSEUDO_REGISTER) + { + reg = gen_rtx_REG (mode, REGNO (reg) + word); + SET_DEST (pattern) = reg; + } +} + +/* Eliminate all occurrences of SETs of hard subregs from INSNS. The + only such SETs that we expect to see are those left in because + integrate can't handle sets of parts of a return value register. + + We don't use alter_subreg because we only want to eliminate subregs + of hard registers. */ + +void +purge_hard_subreg_sets (insn) + rtx insn; +{ + for (; insn; insn = NEXT_INSN (insn)) + { + if (INSN_P (insn)) + { + rtx pattern = PATTERN (insn); + switch (GET_CODE (pattern)) + { + case SET: + if (GET_CODE (SET_DEST (pattern)) == SUBREG) + purge_single_hard_subreg_set (pattern); + break; + case PARALLEL: + { + int j; + for (j = XVECLEN (pattern, 0) - 1; j >= 0; j--) + { + rtx inner_pattern = XVECEXP (pattern, 0, j); + if (GET_CODE (inner_pattern) == SET + && GET_CODE (SET_DEST (inner_pattern)) == SUBREG) + purge_single_hard_subreg_set (inner_pattern); + } + } + break; + default: + break; + } + } + } +} + /* Pass through the INSNS of function FNDECL and convert virtual register references to hard register references. */ @@ -1776,6 +1776,7 @@ extern void preserve_rtl_expr_result PARAMS ((rtx)); extern void mark_temp_addr_taken PARAMS ((rtx)); extern void update_temp_slot_address PARAMS ((rtx, rtx)); extern void purge_addressof PARAMS ((rtx)); +extern void purge_hard_subreg_sets PARAMS ((rtx)); /* In reload.c */ extern int operands_match_p PARAMS ((rtx, rtx)); diff --git a/gcc/toplev.c b/gcc/toplev.c index 333cde6..74e0e3eb 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -2829,11 +2829,14 @@ rest_of_compilation (decl) if (! DECL_DEFER_OUTPUT (decl)) TREE_ASM_WRITTEN (decl) = 1; - /* Now that integrate will no longer see our rtl, we need not distinguish - between the return value of this function and the return value of called - functions. */ + /* Now that integrate will no longer see our rtl, we need not + distinguish between the return value of this function and the + return value of called functions. Also, we can remove all SETs + of subregs of hard registers; they are only here because of + integrate.*/ rtx_equal_function_value_matters = 0; - + purge_hard_subreg_sets (get_insns ()); + /* Don't return yet if -Wreturn-type; we need to do jump_optimize. */ if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type) goto exit_rest_of_compilation; |