diff options
author | Jan Hubicka <jh@suse.cz> | 2003-04-18 01:31:41 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2003-04-17 23:31:41 +0000 |
commit | 04c5580f371b08c0cccb05a520b69097512e3f62 (patch) | |
tree | 0bb84f63ed128b54b740a46b5532d57a1116b085 /gcc/rtlanal.c | |
parent | c409ea0d30ef28e68ff6b4fcb699ba013ee947f1 (diff) | |
download | gcc-04c5580f371b08c0cccb05a520b69097512e3f62.zip gcc-04c5580f371b08c0cccb05a520b69097512e3f62.tar.gz gcc-04c5580f371b08c0cccb05a520b69097512e3f62.tar.bz2 |
emit-rtl.c (subreg_hard_regno): Check that register is representable.
* emit-rtl.c (subreg_hard_regno): Check that register is representable.
* reload.c (reload_inner_reg_of_subreg): When register is not
representable, reload the whole thing.
(find_reloads): Likewsie.
* rtlanal.c (subreg_representable_p): New function.
* profile.c (compute_branch_probabilities): Cleanup sanity checking;
allow negative probabilities for edges from the call to exit.
(branch_prob): Do not add fake edges for functions that may return twice
From-SVN: r65757
Diffstat (limited to 'gcc/rtlanal.c')
-rw-r--r-- | gcc/rtlanal.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index f7923c2..3b024ad 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -3387,6 +3387,77 @@ subreg_regno_offset (xregno, xmode, offset, ymode) return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode; } +/* This function returns true when the offset is representable via + subreg_offset in the given regno. + xregno - A regno of an inner hard subreg_reg (or what will become one). + xmode - The mode of xregno. + offset - The byte offset. + ymode - The mode of a top level SUBREG (or what may become one). + RETURN - The regno offset which would be used. */ +bool +subreg_offset_representable_p (xregno, xmode, offset, ymode) + unsigned int xregno; + enum machine_mode xmode; + unsigned int offset; + enum machine_mode ymode; +{ + int nregs_xmode, nregs_ymode; + int mode_multiple, nregs_multiple; + int y_offset; + + if (xregno >= FIRST_PSEUDO_REGISTER) + abort (); + + nregs_xmode = HARD_REGNO_NREGS (xregno, xmode); + nregs_ymode = HARD_REGNO_NREGS (xregno, ymode); + + /* paradoxical subregs are always valid. */ + if (offset == 0 + && nregs_ymode > nregs_xmode + && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD + ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN)) + return true; + + /* Lowpart subregs are always valid. */ + if (offset == subreg_lowpart_offset (ymode, xmode)) + return true; + +#ifdef ENABLE_CHECKING + /* This should always pass, otherwise we don't know how to verify the + constraint. + + These conditions may be relaxed but subreg_offset would need to be + redesigned. */ + if (GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode) + || GET_MODE_SIZE (ymode) % nregs_ymode + || mode_for_size (GET_MODE_SIZE (ymode) / nregs_ymode, + MODE_INT, 0) == VOIDmode + || nregs_xmode % nregs_ymode) + abort (); +#endif + + /* The XMODE value can be seen as an vector of NREGS_XMODE + values. The subreg must represent an lowpart of given field. + Compute what field it is. */ + offset -= subreg_lowpart_offset (mode_for_size (GET_MODE_SIZE (ymode) + / nregs_ymode, + MODE_INT, 0), xmode); + + /* size of ymode must not be greater than the size of xmode. */ + mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode); + if (mode_multiple == 0) + abort (); + + y_offset = offset / GET_MODE_SIZE (ymode); + nregs_multiple = nregs_xmode / nregs_ymode; +#ifdef ENABLE_CHECKING + if (offset % GET_MODE_SIZE (ymode) + || mode_multiple % nregs_multiple) + abort (); +#endif + return (!(y_offset % (mode_multiple / nregs_multiple))); +} + /* Return the final regno that a subreg expression refers to. */ unsigned int subreg_regno (x) |