summaryrefslogtreecommitdiff
path: root/gcc/reload.c
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-26 13:54:13 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-26 13:54:13 +0000
commit8ffd11f4028d32356652c54a19e9a82f9dc74d90 (patch)
treed066abe1a45fa2c2f22ff463c528153ff122a592 /gcc/reload.c
parentd59975de6b684557150ca30b7ede75174a38db93 (diff)
downloadgcc-8ffd11f4028d32356652c54a19e9a82f9dc74d90.tar.gz
* reload.c (reload_inner_reg_of_subreg): Change type of return value
and type of OUTPUT parameter to bool and adjust. Document MODE and OUTPUT parameters. Use HARD_REGISTER_P. Reorder final condition and improve associated comment. (push_reload): Clarify and update comments about reloading of subregs. Adjust calls to reload_inner_reg_of_subreg. Compute the class upfront for the reloading of subregs in the out case as well. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180526 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reload.c')
-rw-r--r--gcc/reload.c91
1 files changed, 45 insertions, 46 deletions
diff --git a/gcc/reload.c b/gcc/reload.c
index 5928660746a..307bc3a91ef 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -256,7 +256,6 @@ static int push_secondary_reload (int, rtx, int, int, enum reg_class,
enum insn_code *, secondary_reload_info *);
static enum reg_class find_valid_class (enum machine_mode, enum machine_mode,
int, unsigned int);
-static int reload_inner_reg_of_subreg (rtx, enum machine_mode, int);
static void push_replacement (rtx *, int, enum machine_mode);
static void dup_replacements (rtx *, rtx *);
static void combine_reloads (void);
@@ -791,39 +790,39 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
return n_reloads;
}
-/* Return nonzero if X is a SUBREG which will require reloading of its
- SUBREG_REG expression. */
+/* Return true if X is a SUBREG that will need reloading of its SUBREG_REG
+ expression. MODE is the mode that X will be used in. OUTPUT is true if
+ the function is invoked for the output part of an enclosing reload. */
-static int
-reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
+static bool
+reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, bool output)
{
rtx inner;
/* Only SUBREGs are problematical. */
if (GET_CODE (x) != SUBREG)
- return 0;
+ return false;
inner = SUBREG_REG (x);
- /* If INNER is a constant or PLUS, then INNER must be reloaded. */
+ /* If INNER is a constant or PLUS, then INNER will need reloading. */
if (CONSTANT_P (inner) || GET_CODE (inner) == PLUS)
- return 1;
+ return true;
- /* If INNER is not a hard register, then INNER will not need to
- be reloaded. */
- if (!REG_P (inner)
- || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
- return 0;
+ /* If INNER is not a hard register, then INNER will not need reloading. */
+ if (!(REG_P (inner) && HARD_REGISTER_P (inner)))
+ return false;
/* If INNER is not ok for MODE, then INNER will need reloading. */
- if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
- return 1;
-
- /* If the outer part is a word or smaller, INNER larger than a
- word and the number of regs for INNER is not the same as the
- number of words in INNER, then INNER will need reloading. */
- return (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
- && output
+ if (!HARD_REGNO_MODE_OK (subreg_regno (x), mode))
+ return true;
+
+ /* If this is for an output, and the outer part is a word or smaller,
+ INNER is larger than a word and the number of registers in INNER is
+ not the same as the number of words in INNER, then INNER will need
+ reloading (with an in-out reload). */
+ return (output
+ && GET_MODE_SIZE (mode) <= UNITS_PER_WORD
&& GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
&& ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
!= (int) hard_regno_nregs[REGNO (inner)][GET_MODE (inner)]));
@@ -990,9 +989,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
For machines that extend byte loads, do this for any SUBREG of a pseudo
where both M1 and M2 are a word or smaller, M1 is wider than M2, and
M2 is an integral mode that gets extended when loaded.
- Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where either M1 is not valid for R or M2 is wider than a word but we
+ only need one register to store an M2-sized quantity in R.
(However, if OUT is nonzero, we need to reload the reg *and*
the subreg, so do nothing here, and let following statement handle it.)
@@ -1082,17 +1081,16 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
inmode = GET_MODE (in);
}
- /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where M1 is not valid for R if it was not handled by the code above.
+
+ Similar issue for (SUBREG constant ...) if it was not handled by the
+ code above. This can happen if SUBREG_BYTE != 0.
However, we must reload the inner reg *as well as* the subreg in
that case. */
- /* Similar issue for (SUBREG constant ...) if it was not handled by the
- code above. This can happen if SUBREG_BYTE != 0. */
-
- if (in != 0 && reload_inner_reg_of_subreg (in, inmode, 0))
+ if (in != 0 && reload_inner_reg_of_subreg (in, inmode, false))
{
enum reg_class in_class = rclass;
@@ -1168,31 +1166,32 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
outmode = GET_MODE (out);
}
- /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where either M1 is not valid for R or M2 is wider than a word but we
+ only need one register to store an M2-sized quantity in R.
However, we must reload the inner reg *as well as* the subreg in
- that case. In this case, the inner reg is an in-out reload. */
+ that case and the inner reg is an in-out reload. */
- if (out != 0 && reload_inner_reg_of_subreg (out, outmode, 1))
+ if (out != 0 && reload_inner_reg_of_subreg (out, outmode, true))
{
+ enum reg_class in_out_class
+ = find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
+ subreg_regno_offset (REGNO (SUBREG_REG (out)),
+ GET_MODE (SUBREG_REG (out)),
+ SUBREG_BYTE (out),
+ GET_MODE (out)),
+ REGNO (SUBREG_REG (out)));
+
/* This relies on the fact that emit_reload_insns outputs the
instructions for output reloads of type RELOAD_OTHER in reverse
order of the reloads. Thus if the outer reload is also of type
RELOAD_OTHER, we are guaranteed that this inner reload will be
output after the outer reload. */
- dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
- &SUBREG_REG (out),
- find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
- subreg_regno_offset (REGNO (SUBREG_REG (out)),
- GET_MODE (SUBREG_REG (out)),
- SUBREG_BYTE (out),
- GET_MODE (out)),
- REGNO (SUBREG_REG (out))),
- VOIDmode, VOIDmode, 0, 0,
- opnum, RELOAD_OTHER);
+ &SUBREG_REG (out), in_out_class, VOIDmode, VOIDmode,
+ 0, 0, opnum, RELOAD_OTHER);
+ dont_remove_subreg = 1;
}
/* If IN appears in OUT, we can't share any input-only reload for IN. */