From 04c5580f371b08c0cccb05a520b69097512e3f62 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 18 Apr 2003 01:31:41 +0200 Subject: 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 --- gcc/rtlanal.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'gcc/rtlanal.c') 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) -- cgit v1.1