diff options
author | Jeffrey A Law <law@cygnus.com> | 1999-10-25 06:44:04 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1999-10-25 00:44:04 -0600 |
commit | 59487769132b49401a4d63754558d9c08172a287 (patch) | |
tree | 90b92346692e2b364eace0318b1709168984b340 /gcc/loop.c | |
parent | f9c4f105d5b6d9dd78f0d62cf730f523d85f55a2 (diff) | |
download | gcc-59487769132b49401a4d63754558d9c08172a287.tar.gz |
loop.c (note_set_pseudo_multiple_uses_retval): New variable.
* loop.c (note_set_pseudo_multiple_uses_retval): New variable.
(note_set_pseudo_multiple_uses): New function.
(check_dbra_loop): Use not_set_pseudo_multiple_uses to determine
if a pseudo set in the loop exit is used elsewhere.
From-SVN: r30155
Diffstat (limited to 'gcc/loop.c')
-rw-r--r-- | gcc/loop.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/gcc/loop.c b/gcc/loop.c index ea815fff847..5ef10bd5b67 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -269,6 +269,9 @@ static struct movable *the_movables; FILE *loop_dump_stream; +/* For communicating return values from note_set_pseudo_multiple_uses. */ +static int note_set_pseudo_multiple_uses_retval; + /* Forward declarations. */ static void verify_dominator PROTO((int)); @@ -283,6 +286,7 @@ static void count_one_set PROTO((rtx, rtx, varray_type, rtx *)); static void count_loop_regs_set PROTO((rtx, rtx, varray_type, varray_type, int *, int)); static void note_addr_stored PROTO((rtx, rtx)); +static void note_set_pseudo_multiple_uses PROTO((rtx, rtx)); static int loop_reg_used_before_p PROTO((rtx, rtx, rtx, rtx, rtx)); static void scan_loop PROTO((rtx, rtx, rtx, int, int)); #if 0 @@ -3172,6 +3176,36 @@ note_addr_stored (x, y) loop_store_mems = gen_rtx_EXPR_LIST (VOIDmode, x, loop_store_mems); } + +/* X is a value modified by an INSN that references a biv inside a loop + exit test (ie, X is somehow related to the value of the biv). If X + is a pseudo that is used more than once, then the biv is (effectively) + used more than once. */ + +static void +note_set_pseudo_multiple_uses (x, y) + rtx x; + rtx y ATTRIBUTE_UNUSED; +{ + if (x == 0) + return; + + while (GET_CODE (x) == STRICT_LOW_PART + || GET_CODE (x) == SIGN_EXTRACT + || GET_CODE (x) == ZERO_EXTRACT + || GET_CODE (x) == SUBREG) + x = XEXP (x, 0); + + if (GET_CODE (x) != REG || REGNO (x) < FIRST_PSEUDO_REGISTER) + return; + + /* If we do not have usage information, or if we know the register + is used more than once, note that fact for check_dbra_loop. */ + if (REGNO (x) >= max_reg_before_loop + || ! VARRAY_RTX (reg_single_usage, REGNO (x)) + || VARRAY_RTX (reg_single_usage, REGNO (x)) == const0_rtx) + note_set_pseudo_multiple_uses_retval = 1; +} /* Return nonzero if the rtx X is invariant over the current loop. @@ -7932,10 +7966,22 @@ check_dbra_loop (loop_end, insn_count, loop_start, loop_info) && REGNO (SET_DEST (set)) == bl->regno) /* An insn that sets the biv is okay. */ ; - else if (p == prev_nonnote_insn (prev_nonnote_insn (loop_end)) - || p == prev_nonnote_insn (loop_end)) - /* Don't bother about the end test. */ - ; + else if ((p == prev_nonnote_insn (prev_nonnote_insn (loop_end)) + || p == prev_nonnote_insn (loop_end)) + && reg_mentioned_p (bivreg, PATTERN (p))) + { + /* If either of these insns uses the biv and sets a pseudo + that has more than one usage, then the biv has uses + other than counting since it's used to derive a value + that is used more than one time. */ + note_set_pseudo_multiple_uses_retval = 0; + note_stores (PATTERN (p), note_set_pseudo_multiple_uses); + if (note_set_pseudo_multiple_uses_retval) + { + no_use_except_counting = 0; + break; + } + } else if (reg_mentioned_p (bivreg, PATTERN (p))) { no_use_except_counting = 0; |