diff options
author | Jim Wilson <wilson@gcc.gnu.org> | 1996-10-04 12:56:02 -0700 |
---|---|---|
committer | Jim Wilson <wilson@gcc.gnu.org> | 1996-10-04 12:56:02 -0700 |
commit | 4787bce0e940cb9b732878dbe7784e475ddab158 (patch) | |
tree | 3b9477c194c4b153f777c14c9034b59687afc818 /gcc | |
parent | 227665e760b1e42a16c8c6cbe884dee48182515b (diff) | |
download | gcc-4787bce0e940cb9b732878dbe7784e475ddab158.zip gcc-4787bce0e940cb9b732878dbe7784e475ddab158.tar.gz gcc-4787bce0e940cb9b732878dbe7784e475ddab158.tar.bz2 |
(sfunc_uses_reg): New function.
(noncall_uses_reg, machine_dependent_reorg, final_prescan_insn):
Handle special functions like function calls for purposes of relaxing.
(noncall_uses_reg): Added some missing cases of registers
being used in non-call instructions.
From-SVN: r12901
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/sh/sh.c | 107 |
1 files changed, 90 insertions, 17 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index c7e34d8..9b236c8 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -1925,6 +1925,45 @@ find_barrier (from) return found_barrier; } +/* If the instruction INSN is implemented by a special function, and we can + positively find the register that is used to call the sfunc, and this + register is not used anywhere else in this instruction - except as the + destination of a set, return this register; else, return 0. */ +static rtx +sfunc_uses_reg (insn) + rtx insn; +{ + int i; + rtx pattern, part, reg_part, reg; + + if (GET_CODE (insn) != INSN) + return 0; + pattern = PATTERN (insn); + if (GET_CODE (pattern) != PARALLEL || get_attr_type (insn) != TYPE_SFUNC) + return 0; + + for (reg_part = 0, i = XVECLEN (pattern, 0) - 1; i >= 1; i--) + { + part = XVECEXP (pattern, 0, i); + if (GET_CODE (part) == USE) + reg_part = part; + } + if (! reg_part) + return 0; + reg = XEXP (reg_part, 0); + for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--) + { + part = XVECEXP (pattern, 0, i); + if (part == reg_part) + continue; + if (reg_mentioned_p (reg, ((GET_CODE (part) == SET + && GET_CODE (SET_DEST (part)) == REG) + ? SET_SRC (part) : part))) + return 0; + } + return reg; +} + /* See if the only way in which INSN uses REG is by calling it, or by setting it while calling it. Set *SET to a SET rtx if the register is set by INSN. */ @@ -1935,10 +1974,20 @@ noncall_uses_reg (reg, insn, set) rtx insn; rtx *set; { - rtx pattern; + rtx pattern, reg2; *set = NULL_RTX; + reg2 = sfunc_uses_reg (insn); + if (reg2 && REGNO (reg2) == REGNO (reg)) + { + pattern = single_set (insn); + if (pattern + && GET_CODE (SET_DEST (pattern)) == REG + && REGNO (reg) == REGNO (SET_DEST (pattern))) + *set = pattern; + return 0; + } if (GET_CODE (insn) != CALL_INSN) { /* We don't use rtx_equal_p because we don't care if the mode is @@ -1948,8 +1997,19 @@ noncall_uses_reg (reg, insn, set) && GET_CODE (SET_DEST (pattern)) == REG && REGNO (reg) == REGNO (SET_DEST (pattern))) { + rtx par, part; + int i; + *set = pattern; - return 0; + par = PATTERN (insn); + if (GET_CODE (par) == PARALLEL) + for (i = XVECLEN (par, 0) - 1; i >= 0; i--) + { + part = XVECEXP (par, 0, i); + if (GET_CODE (part) != SET && reg_mentioned_p (reg, part)) + return 1; + } + return reg_mentioned_p (reg, SET_SRC (pattern)); } return 1; @@ -2032,21 +2092,28 @@ machine_dependent_reorg (first) rtx pattern, reg, link, set, scan, dies, label; int rescan = 0, foundinsn = 0; - if (GET_CODE (insn) != CALL_INSN) - continue; + if (GET_CODE (insn) == CALL_INSN) + { + pattern = PATTERN (insn); - pattern = PATTERN (insn); + if (GET_CODE (pattern) == PARALLEL) + pattern = XVECEXP (pattern, 0, 0); + if (GET_CODE (pattern) == SET) + pattern = SET_SRC (pattern); - if (GET_CODE (pattern) == PARALLEL) - pattern = XVECEXP (pattern, 0, 0); - if (GET_CODE (pattern) == SET) - pattern = SET_SRC (pattern); + if (GET_CODE (pattern) != CALL + || GET_CODE (XEXP (pattern, 0)) != MEM) + continue; - if (GET_CODE (pattern) != CALL - || GET_CODE (XEXP (pattern, 0)) != MEM) - continue; + reg = XEXP (XEXP (pattern, 0), 0); + } + else + { + reg = sfunc_uses_reg (insn); + if (! reg) + continue; + } - reg = XEXP (XEXP (pattern, 0), 0); if (GET_CODE (reg) != REG) continue; @@ -2148,7 +2215,8 @@ machine_dependent_reorg (first) if (scan == insn) foundinsn = 1; - if (scan != insn && GET_CODE (scan) == CALL_INSN) + if (scan != insn + && (GET_CODE (scan) == CALL_INSN || sfunc_uses_reg (scan))) { /* There is a function call to this register other than the one we are checking. If we optimize @@ -2205,10 +2273,14 @@ machine_dependent_reorg (first) scan = link; do { + rtx reg2; + scan = NEXT_INSN (scan); if (scan != insn - && GET_CODE (scan) == CALL_INSN - && reg_mentioned_p (reg, scan)) + && ((GET_CODE (scan) == CALL_INSN + && reg_mentioned_p (reg, scan)) + || ((reg2 = sfunc_uses_reg (scan)) + && REGNO (reg2) == REGNO (reg)))) REG_NOTES (scan) = gen_rtx (EXPR_LIST, REG_LABEL, label, REG_NOTES (scan)); } @@ -2319,7 +2391,8 @@ final_prescan_insn (insn, opvec, noperands) pattern = XVECEXP (pattern, 0, 0); if (GET_CODE (pattern) == CALL || (GET_CODE (pattern) == SET - && GET_CODE (SET_SRC (pattern)) == CALL)) + && (GET_CODE (SET_SRC (pattern)) == CALL + || get_attr_type (insn) == TYPE_SFUNC))) fprintf (asm_out_file, "\t.uses L%d\n", CODE_LABEL_NUMBER (XEXP (note, 0))); else if (GET_CODE (pattern) == SET) |