aboutsummaryrefslogtreecommitdiff
path: root/gcc/rtlanal.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2003-04-18 01:31:41 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2003-04-17 23:31:41 +0000
commit04c5580f371b08c0cccb05a520b69097512e3f62 (patch)
tree0bb84f63ed128b54b740a46b5532d57a1116b085 /gcc/rtlanal.c
parentc409ea0d30ef28e68ff6b4fcb699ba013ee947f1 (diff)
downloadgcc-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.c71
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)