mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-11 20:55:25 +08:00
rtlanal.c (struct subreg_info, [...]): New.
* rtlanal.c (struct subreg_info, subreg_get_info, subreg_nregs): New. (subreg_regno_offset, subreg_offset_representable_p): Change to wrappers about subreg_get_info. (refers_to_regno_p, reg_overlap_mentioned_p): Use subreg_nregs. * rtl.h (subreg_nregs): Declare. * doc/tm.texi (HARD_REGNO_NREGS_HAS_PADDING): Update to refer to subreg_get_info. * caller-save.c (mark_set_regs, add_stored_regs): Use subreg_nregs. * df-scan.c (df_ref_record): Use subreg_nregs. * flow.c (mark_set_1): Use subreg_nregs. * postreload.c (move2add_note_store): Use subreg_nregs. * reload.c (decompose, refers_to_regno_for_reload_p, reg_overlap_mentioned_for_reload_p): Use subreg_nregs. * resource.c (update_live_status, mark_referenced_resources, mark_set_resources): Use subreg_nregs. From-SVN: r120076
This commit is contained in:
parent
ee8c1b05d5
commit
f1f4e530a5
@ -1,3 +1,23 @@
|
|||||||
|
2006-12-20 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
|
* rtlanal.c (struct subreg_info, subreg_get_info, subreg_nregs):
|
||||||
|
New.
|
||||||
|
(subreg_regno_offset, subreg_offset_representable_p): Change to
|
||||||
|
wrappers about subreg_get_info.
|
||||||
|
(refers_to_regno_p, reg_overlap_mentioned_p): Use subreg_nregs.
|
||||||
|
* rtl.h (subreg_nregs): Declare.
|
||||||
|
* doc/tm.texi (HARD_REGNO_NREGS_HAS_PADDING): Update to refer to
|
||||||
|
subreg_get_info.
|
||||||
|
* caller-save.c (mark_set_regs, add_stored_regs): Use
|
||||||
|
subreg_nregs.
|
||||||
|
* df-scan.c (df_ref_record): Use subreg_nregs.
|
||||||
|
* flow.c (mark_set_1): Use subreg_nregs.
|
||||||
|
* postreload.c (move2add_note_store): Use subreg_nregs.
|
||||||
|
* reload.c (decompose, refers_to_regno_for_reload_p,
|
||||||
|
reg_overlap_mentioned_for_reload_p): Use subreg_nregs.
|
||||||
|
* resource.c (update_live_status, mark_referenced_resources,
|
||||||
|
mark_set_resources): Use subreg_nregs.
|
||||||
|
|
||||||
2006-12-20 Zdenek Dvorak <dvorakz@suse.cz>
|
2006-12-20 Zdenek Dvorak <dvorakz@suse.cz>
|
||||||
|
|
||||||
* loop-unswitch.c (unswitch_loop): Update arguments of
|
* loop-unswitch.c (unswitch_loop): Update arguments of
|
||||||
|
@ -508,15 +508,17 @@ mark_set_regs (rtx reg, rtx setter ATTRIBUTE_UNUSED, void *data)
|
|||||||
if (!REG_P (inner) || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
|
if (!REG_P (inner) || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
|
||||||
return;
|
return;
|
||||||
regno = subreg_regno (reg);
|
regno = subreg_regno (reg);
|
||||||
|
endregno = regno + subreg_nregs (reg);
|
||||||
}
|
}
|
||||||
else if (REG_P (reg)
|
else if (REG_P (reg)
|
||||||
&& REGNO (reg) < FIRST_PSEUDO_REGISTER)
|
&& REGNO (reg) < FIRST_PSEUDO_REGISTER)
|
||||||
regno = REGNO (reg);
|
{
|
||||||
|
regno = REGNO (reg);
|
||||||
|
endregno = regno + hard_regno_nregs[regno][mode];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
endregno = regno + hard_regno_nregs[regno][mode];
|
|
||||||
|
|
||||||
for (i = regno; i < endregno; i++)
|
for (i = regno; i < endregno; i++)
|
||||||
SET_HARD_REG_BIT (*this_insn_sets, i);
|
SET_HARD_REG_BIT (*this_insn_sets, i);
|
||||||
}
|
}
|
||||||
@ -542,13 +544,17 @@ add_stored_regs (rtx reg, rtx setter, void *data)
|
|||||||
SUBREG_BYTE (reg),
|
SUBREG_BYTE (reg),
|
||||||
GET_MODE (reg));
|
GET_MODE (reg));
|
||||||
reg = SUBREG_REG (reg);
|
reg = SUBREG_REG (reg);
|
||||||
|
regno = REGNO (reg) + offset;
|
||||||
|
endregno = regno + subreg_nregs (reg);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
|
regno = REGNO (reg) + offset;
|
||||||
return;
|
endregno = regno + hard_regno_nregs[regno][mode];
|
||||||
|
}
|
||||||
regno = REGNO (reg) + offset;
|
|
||||||
endregno = regno + hard_regno_nregs[regno][mode];
|
|
||||||
|
|
||||||
for (i = regno; i < endregno; i++)
|
for (i = regno; i < endregno; i++)
|
||||||
SET_REGNO_REG_SET ((regset) data, i);
|
SET_REGNO_REG_SET ((regset) data, i);
|
||||||
|
@ -1083,15 +1083,14 @@ df_ref_record (struct dataflow *dflow, rtx reg, rtx *loc,
|
|||||||
if (!(dflow->flags & DF_HARD_REGS))
|
if (!(dflow->flags & DF_HARD_REGS))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* GET_MODE (reg) is correct here. We do not want to go into a SUBREG
|
|
||||||
for the mode, because we only want to add references to regs, which
|
|
||||||
are really referenced. E.g., a (subreg:SI (reg:DI 0) 0) does _not_
|
|
||||||
reference the whole reg 0 in DI mode (which would also include
|
|
||||||
reg 1, at least, if 0 and 1 are SImode registers). */
|
|
||||||
endregno = hard_regno_nregs[regno][GET_MODE (reg)];
|
|
||||||
if (GET_CODE (reg) == SUBREG)
|
if (GET_CODE (reg) == SUBREG)
|
||||||
regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
|
{
|
||||||
SUBREG_BYTE (reg), GET_MODE (reg));
|
regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
|
||||||
|
SUBREG_BYTE (reg), GET_MODE (reg));
|
||||||
|
endregno = subreg_nregs (reg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
endregno = hard_regno_nregs[regno][GET_MODE (reg)];
|
||||||
endregno += regno;
|
endregno += regno;
|
||||||
|
|
||||||
/* If this is a multiword hardreg, we create some extra datastructures that
|
/* If this is a multiword hardreg, we create some extra datastructures that
|
||||||
|
@ -1991,7 +1991,7 @@ registers but takes up 128 bits in memory, then this would be
|
|||||||
nonzero.
|
nonzero.
|
||||||
|
|
||||||
This macros only needs to be defined if there are cases where
|
This macros only needs to be defined if there are cases where
|
||||||
@code{subreg_regno_offset} and @code{subreg_offset_representable_p}
|
@code{subreg_get_info}
|
||||||
would otherwise wrongly determine that a @code{subreg} can be
|
would otherwise wrongly determine that a @code{subreg} can be
|
||||||
represented by an offset to the register number, when in fact such a
|
represented by an offset to the register number, when in fact such a
|
||||||
@code{subreg} would contain some of the padding not stored in
|
@code{subreg} would contain some of the padding not stored in
|
||||||
|
@ -2791,8 +2791,7 @@ mark_set_1 (struct propagate_block_info *pbi, enum rtx_code code, rtx reg, rtx c
|
|||||||
regno_first += subreg_regno_offset (regno_first, inner_mode,
|
regno_first += subreg_regno_offset (regno_first, inner_mode,
|
||||||
SUBREG_BYTE (reg),
|
SUBREG_BYTE (reg),
|
||||||
outer_mode);
|
outer_mode);
|
||||||
regno_last = (regno_first
|
regno_last = regno_first + subreg_nregs (reg) - 1;
|
||||||
+ hard_regno_nregs[regno_first][outer_mode] - 1);
|
|
||||||
|
|
||||||
/* Since we've just adjusted the register number ranges, make
|
/* Since we've just adjusted the register number ranges, make
|
||||||
sure REG matches. Otherwise some_was_live will be clear
|
sure REG matches. Otherwise some_was_live will be clear
|
||||||
|
@ -1429,6 +1429,7 @@ static void
|
|||||||
move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED)
|
move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
unsigned int regno = 0;
|
unsigned int regno = 0;
|
||||||
|
unsigned int nregs = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
enum machine_mode mode = GET_MODE (dst);
|
enum machine_mode mode = GET_MODE (dst);
|
||||||
|
|
||||||
@ -1438,6 +1439,7 @@ move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED)
|
|||||||
GET_MODE (SUBREG_REG (dst)),
|
GET_MODE (SUBREG_REG (dst)),
|
||||||
SUBREG_BYTE (dst),
|
SUBREG_BYTE (dst),
|
||||||
GET_MODE (dst));
|
GET_MODE (dst));
|
||||||
|
nregs = subreg_nregs (dst);
|
||||||
dst = SUBREG_REG (dst);
|
dst = SUBREG_REG (dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1455,9 +1457,11 @@ move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
regno += REGNO (dst);
|
regno += REGNO (dst);
|
||||||
|
if (!nregs)
|
||||||
|
nregs = hard_regno_nregs[regno][mode];
|
||||||
|
|
||||||
if (SCALAR_INT_MODE_P (GET_MODE (dst))
|
if (SCALAR_INT_MODE_P (GET_MODE (dst))
|
||||||
&& hard_regno_nregs[regno][mode] == 1 && GET_CODE (set) == SET
|
&& nregs == 1 && GET_CODE (set) == SET
|
||||||
&& GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
|
&& GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
|
||||||
&& GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
|
&& GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
|
||||||
{
|
{
|
||||||
@ -1557,7 +1561,7 @@ move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int endregno = regno + hard_regno_nregs[regno][mode];
|
unsigned int endregno = regno + nregs;
|
||||||
|
|
||||||
for (i = regno; i < endregno; i++)
|
for (i = regno; i < endregno; i++)
|
||||||
/* Reset the information about this register. */
|
/* Reset the information about this register. */
|
||||||
|
17
gcc/reload.c
17
gcc/reload.c
@ -2414,7 +2414,7 @@ decompose (rtx x)
|
|||||||
return decompose (SUBREG_REG (x));
|
return decompose (SUBREG_REG (x));
|
||||||
else
|
else
|
||||||
/* A hard reg. */
|
/* A hard reg. */
|
||||||
val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];
|
val.end = val.start + subreg_nregs (x);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCRATCH:
|
case SCRATCH:
|
||||||
@ -6381,7 +6381,7 @@ refers_to_regno_for_reload_p (unsigned int regno, unsigned int endregno,
|
|||||||
unsigned int inner_regno = subreg_regno (x);
|
unsigned int inner_regno = subreg_regno (x);
|
||||||
unsigned int inner_endregno
|
unsigned int inner_endregno
|
||||||
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
|
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
|
||||||
? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
|
? subreg_nregs (x) : 1);
|
||||||
|
|
||||||
return endregno > inner_regno && regno < inner_endregno;
|
return endregno > inner_regno && regno < inner_endregno;
|
||||||
}
|
}
|
||||||
@ -6479,6 +6479,10 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
|
|||||||
GET_MODE (SUBREG_REG (x)),
|
GET_MODE (SUBREG_REG (x)),
|
||||||
SUBREG_BYTE (x),
|
SUBREG_BYTE (x),
|
||||||
GET_MODE (x));
|
GET_MODE (x));
|
||||||
|
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
|
||||||
|
? subreg_nregs (x) : 1);
|
||||||
|
|
||||||
|
return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
|
||||||
}
|
}
|
||||||
else if (REG_P (x))
|
else if (REG_P (x))
|
||||||
{
|
{
|
||||||
@ -6494,6 +6498,10 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
|
|||||||
gcc_assert (reg_equiv_constant[regno]);
|
gcc_assert (reg_equiv_constant[regno]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endregno = regno + hard_regno_nregs[regno][GET_MODE (x)];
|
||||||
|
|
||||||
|
return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
|
||||||
}
|
}
|
||||||
else if (MEM_P (x))
|
else if (MEM_P (x))
|
||||||
return refers_to_mem_for_reload_p (in);
|
return refers_to_mem_for_reload_p (in);
|
||||||
@ -6520,10 +6528,7 @@ reg_overlap_mentioned_for_reload_p (rtx x, rtx in)
|
|||||||
|| reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
|
|| reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
|
||||||
}
|
}
|
||||||
|
|
||||||
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
|
gcc_unreachable ();
|
||||||
? hard_regno_nregs[regno][GET_MODE (x)] : 1);
|
|
||||||
|
|
||||||
return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return nonzero if anything in X contains a MEM. Look also for pseudo
|
/* Return nonzero if anything in X contains a MEM. Look also for pseudo
|
||||||
|
@ -99,11 +99,17 @@ update_live_status (rtx dest, rtx x, void *data ATTRIBUTE_UNUSED)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (GET_CODE (dest) == SUBREG)
|
if (GET_CODE (dest) == SUBREG)
|
||||||
first_regno = subreg_regno (dest);
|
{
|
||||||
else
|
first_regno = subreg_regno (dest);
|
||||||
first_regno = REGNO (dest);
|
last_regno = first_regno + subreg_nregs (dest);
|
||||||
|
|
||||||
last_regno = first_regno + hard_regno_nregs[first_regno][GET_MODE (dest)];
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first_regno = REGNO (dest);
|
||||||
|
last_regno
|
||||||
|
= first_regno + hard_regno_nregs[first_regno][GET_MODE (dest)];
|
||||||
|
}
|
||||||
|
|
||||||
if (GET_CODE (x) == CLOBBER)
|
if (GET_CODE (x) == CLOBBER)
|
||||||
for (i = first_regno; i < last_regno; i++)
|
for (i = first_regno; i < last_regno; i++)
|
||||||
@ -229,8 +235,7 @@ mark_referenced_resources (rtx x, struct resources *res,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int regno = subreg_regno (x);
|
unsigned int regno = subreg_regno (x);
|
||||||
unsigned int last_regno
|
unsigned int last_regno = regno + subreg_nregs (x);
|
||||||
= regno + hard_regno_nregs[regno][GET_MODE (x)];
|
|
||||||
|
|
||||||
gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER);
|
gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER);
|
||||||
for (r = regno; r < last_regno; r++)
|
for (r = regno; r < last_regno; r++)
|
||||||
@ -763,8 +768,7 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int regno = subreg_regno (x);
|
unsigned int regno = subreg_regno (x);
|
||||||
unsigned int last_regno
|
unsigned int last_regno = regno + subreg_nregs (x);
|
||||||
= regno + hard_regno_nregs[regno][GET_MODE (x)];
|
|
||||||
|
|
||||||
gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER);
|
gcc_assert (last_regno <= FIRST_PSEUDO_REGISTER);
|
||||||
for (r = regno; r < last_regno; r++)
|
for (r = regno; r < last_regno; r++)
|
||||||
|
@ -1041,6 +1041,7 @@ extern unsigned int subreg_regno_offset (unsigned int, enum machine_mode,
|
|||||||
extern bool subreg_offset_representable_p (unsigned int, enum machine_mode,
|
extern bool subreg_offset_representable_p (unsigned int, enum machine_mode,
|
||||||
unsigned int, enum machine_mode);
|
unsigned int, enum machine_mode);
|
||||||
extern unsigned int subreg_regno (rtx);
|
extern unsigned int subreg_regno (rtx);
|
||||||
|
extern unsigned int subreg_nregs (rtx);
|
||||||
extern unsigned HOST_WIDE_INT nonzero_bits (rtx, enum machine_mode);
|
extern unsigned HOST_WIDE_INT nonzero_bits (rtx, enum machine_mode);
|
||||||
extern unsigned int num_sign_bit_copies (rtx, enum machine_mode);
|
extern unsigned int num_sign_bit_copies (rtx, enum machine_mode);
|
||||||
extern bool constant_pool_constant_p (rtx);
|
extern bool constant_pool_constant_p (rtx);
|
||||||
|
215
gcc/rtlanal.c
215
gcc/rtlanal.c
@ -38,6 +38,18 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
|||||||
#include "regs.h"
|
#include "regs.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
|
|
||||||
|
/* Information about a subreg of a hard register. */
|
||||||
|
struct subreg_info
|
||||||
|
{
|
||||||
|
/* Offset of first hard register involved in the subreg. */
|
||||||
|
int offset;
|
||||||
|
/* Number of hard registers involved in the subreg. */
|
||||||
|
int nregs;
|
||||||
|
/* Whether this subreg can be represented as a hard reg with the new
|
||||||
|
mode. */
|
||||||
|
bool representable_p;
|
||||||
|
};
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static void set_of_1 (rtx, rtx, void *);
|
static void set_of_1 (rtx, rtx, void *);
|
||||||
static bool covers_regno_p (rtx, unsigned int);
|
static bool covers_regno_p (rtx, unsigned int);
|
||||||
@ -45,6 +57,9 @@ static bool covers_regno_no_parallel_p (rtx, unsigned int);
|
|||||||
static int rtx_referenced_p_1 (rtx *, void *);
|
static int rtx_referenced_p_1 (rtx *, void *);
|
||||||
static int computed_jump_p_1 (rtx);
|
static int computed_jump_p_1 (rtx);
|
||||||
static void parms_set (rtx, rtx, void *);
|
static void parms_set (rtx, rtx, void *);
|
||||||
|
static void subreg_get_info (unsigned int, enum machine_mode,
|
||||||
|
unsigned int, enum machine_mode,
|
||||||
|
struct subreg_info *);
|
||||||
|
|
||||||
static unsigned HOST_WIDE_INT cached_nonzero_bits (rtx, enum machine_mode,
|
static unsigned HOST_WIDE_INT cached_nonzero_bits (rtx, enum machine_mode,
|
||||||
rtx, enum machine_mode,
|
rtx, enum machine_mode,
|
||||||
@ -1176,7 +1191,7 @@ refers_to_regno_p (unsigned int regno, unsigned int endregno, rtx x,
|
|||||||
unsigned int inner_regno = subreg_regno (x);
|
unsigned int inner_regno = subreg_regno (x);
|
||||||
unsigned int inner_endregno
|
unsigned int inner_endregno
|
||||||
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
|
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
|
||||||
? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
|
? subreg_nregs (x) : 1);
|
||||||
|
|
||||||
return endregno > inner_regno && regno < inner_endregno;
|
return endregno > inner_regno && regno < inner_endregno;
|
||||||
}
|
}
|
||||||
@ -1266,13 +1281,15 @@ reg_overlap_mentioned_p (rtx x, rtx in)
|
|||||||
regno = REGNO (SUBREG_REG (x));
|
regno = REGNO (SUBREG_REG (x));
|
||||||
if (regno < FIRST_PSEUDO_REGISTER)
|
if (regno < FIRST_PSEUDO_REGISTER)
|
||||||
regno = subreg_regno (x);
|
regno = subreg_regno (x);
|
||||||
|
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
|
||||||
|
? subreg_nregs (x) : 1);
|
||||||
goto do_reg;
|
goto do_reg;
|
||||||
|
|
||||||
case REG:
|
case REG:
|
||||||
regno = REGNO (x);
|
regno = REGNO (x);
|
||||||
do_reg:
|
|
||||||
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
|
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
|
||||||
? hard_regno_nregs[regno][GET_MODE (x)] : 1);
|
? hard_regno_nregs[regno][GET_MODE (x)] : 1);
|
||||||
|
do_reg:
|
||||||
return refers_to_regno_p (regno, endregno, in, (rtx*) 0);
|
return refers_to_regno_p (regno, endregno, in, (rtx*) 0);
|
||||||
|
|
||||||
case MEM:
|
case MEM:
|
||||||
@ -2926,69 +2943,27 @@ subreg_lsb (rtx x)
|
|||||||
SUBREG_BYTE (x));
|
SUBREG_BYTE (x));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function returns the regno offset of a subreg expression.
|
/* Fill in information about a subreg of a hard register.
|
||||||
xregno - A regno of an inner hard subreg_reg (or what will become one).
|
xregno - A regno of an inner hard subreg_reg (or what will become one).
|
||||||
xmode - The mode of xregno.
|
xmode - The mode of xregno.
|
||||||
offset - The byte offset.
|
offset - The byte offset.
|
||||||
ymode - The mode of a top level SUBREG (or what may become one).
|
ymode - The mode of a top level SUBREG (or what may become one).
|
||||||
RETURN - The regno offset which would be used. */
|
info - Pointer to structure to fill in. */
|
||||||
unsigned int
|
static void
|
||||||
subreg_regno_offset (unsigned int xregno, enum machine_mode xmode,
|
subreg_get_info (unsigned int xregno, enum machine_mode xmode,
|
||||||
unsigned int offset, enum machine_mode ymode)
|
unsigned int offset, enum machine_mode ymode,
|
||||||
|
struct subreg_info *info)
|
||||||
{
|
{
|
||||||
int nregs_xmode, nregs_ymode;
|
int nregs_xmode, nregs_ymode;
|
||||||
int mode_multiple, nregs_multiple;
|
int mode_multiple, nregs_multiple;
|
||||||
int y_offset;
|
int offset_adj, y_offset, y_offset_adj;
|
||||||
|
|
||||||
gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
|
|
||||||
|
|
||||||
/* Adjust nregs_xmode to allow for 'holes'. */
|
|
||||||
if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
|
|
||||||
nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
|
|
||||||
else
|
|
||||||
nregs_xmode = hard_regno_nregs[xregno][xmode];
|
|
||||||
|
|
||||||
nregs_ymode = hard_regno_nregs[xregno][ymode];
|
|
||||||
|
|
||||||
/* If this is a big endian paradoxical subreg, which uses more actual
|
|
||||||
hard registers than the original register, we must return a negative
|
|
||||||
offset so that we find the proper highpart of the register. */
|
|
||||||
if (offset == 0
|
|
||||||
&& nregs_ymode > nregs_xmode
|
|
||||||
&& (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
|
|
||||||
? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
|
|
||||||
return nregs_xmode - nregs_ymode;
|
|
||||||
|
|
||||||
if (offset == 0 || nregs_xmode == nregs_ymode)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Size of ymode must not be greater than the size of xmode. */
|
|
||||||
mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
|
|
||||||
gcc_assert (mode_multiple != 0);
|
|
||||||
|
|
||||||
y_offset = offset / GET_MODE_SIZE (ymode);
|
|
||||||
nregs_multiple = nregs_xmode / nregs_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 - Whether the offset is representable. */
|
|
||||||
bool
|
|
||||||
subreg_offset_representable_p (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;
|
|
||||||
int regsize_xmode, regsize_ymode;
|
int regsize_xmode, regsize_ymode;
|
||||||
|
bool rknown;
|
||||||
|
|
||||||
gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
|
gcc_assert (xregno < FIRST_PSEUDO_REGISTER);
|
||||||
|
|
||||||
|
rknown = false;
|
||||||
|
|
||||||
/* If there are holes in a non-scalar mode in registers, we expect
|
/* If there are holes in a non-scalar mode in registers, we expect
|
||||||
that it is made up of its units concatenated together. */
|
that it is made up of its units concatenated together. */
|
||||||
if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
|
if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
|
||||||
@ -3021,7 +2996,10 @@ subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
|
|||||||
&& (offset / GET_MODE_SIZE (xmode_unit)
|
&& (offset / GET_MODE_SIZE (xmode_unit)
|
||||||
!= ((offset + GET_MODE_SIZE (ymode) - 1)
|
!= ((offset + GET_MODE_SIZE (ymode) - 1)
|
||||||
/ GET_MODE_SIZE (xmode_unit))))
|
/ GET_MODE_SIZE (xmode_unit))))
|
||||||
return false;
|
{
|
||||||
|
info->representable_p = false;
|
||||||
|
rknown = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nregs_xmode = hard_regno_nregs[xregno][xmode];
|
nregs_xmode = hard_regno_nregs[xregno][xmode];
|
||||||
@ -3029,24 +3007,57 @@ subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
|
|||||||
nregs_ymode = hard_regno_nregs[xregno][ymode];
|
nregs_ymode = hard_regno_nregs[xregno][ymode];
|
||||||
|
|
||||||
/* Paradoxical subregs are otherwise valid. */
|
/* Paradoxical subregs are otherwise valid. */
|
||||||
if (offset == 0
|
if (!rknown
|
||||||
&& nregs_ymode > nregs_xmode
|
&& offset == 0
|
||||||
&& (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
|
&& GET_MODE_SIZE (ymode) > GET_MODE_SIZE (xmode))
|
||||||
? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
|
{
|
||||||
return true;
|
info->representable_p = true;
|
||||||
|
/* If this is a big endian paradoxical subreg, which uses more
|
||||||
|
actual hard registers than the original register, we must
|
||||||
|
return a negative offset so that we find the proper highpart
|
||||||
|
of the register. */
|
||||||
|
if (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
|
||||||
|
? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN)
|
||||||
|
info->offset = nregs_xmode - nregs_ymode;
|
||||||
|
else
|
||||||
|
info->offset = 0;
|
||||||
|
info->nregs = nregs_ymode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* If registers store different numbers of bits in the different
|
/* If registers store different numbers of bits in the different
|
||||||
modes, we cannot generally form this subreg. */
|
modes, we cannot generally form this subreg. */
|
||||||
regsize_xmode = GET_MODE_SIZE (xmode) / nregs_xmode;
|
if (!HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode)
|
||||||
regsize_ymode = GET_MODE_SIZE (ymode) / nregs_ymode;
|
&& !HARD_REGNO_NREGS_HAS_PADDING (xregno, ymode))
|
||||||
if (regsize_xmode > regsize_ymode && nregs_ymode > 1)
|
{
|
||||||
return false;
|
regsize_xmode = GET_MODE_SIZE (xmode) / nregs_xmode;
|
||||||
if (regsize_ymode > regsize_xmode && nregs_xmode > 1)
|
gcc_assert (regsize_xmode * nregs_xmode == GET_MODE_SIZE (xmode));
|
||||||
return false;
|
regsize_ymode = GET_MODE_SIZE (ymode) / nregs_ymode;
|
||||||
|
gcc_assert (regsize_ymode * nregs_ymode == GET_MODE_SIZE (ymode));
|
||||||
|
if (!rknown && regsize_xmode > regsize_ymode && nregs_ymode > 1)
|
||||||
|
{
|
||||||
|
info->representable_p = false;
|
||||||
|
info->nregs
|
||||||
|
= (GET_MODE_SIZE (ymode) + regsize_xmode - 1) / regsize_xmode;
|
||||||
|
info->offset = offset / regsize_xmode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!rknown && regsize_ymode > regsize_xmode && nregs_xmode > 1)
|
||||||
|
{
|
||||||
|
info->representable_p = false;
|
||||||
|
info->nregs
|
||||||
|
= (GET_MODE_SIZE (ymode) + regsize_xmode - 1) / regsize_xmode;
|
||||||
|
info->offset = offset / regsize_xmode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Lowpart subregs are otherwise valid. */
|
/* Lowpart subregs are otherwise valid. */
|
||||||
if (offset == subreg_lowpart_offset (ymode, xmode))
|
if (!rknown && offset == subreg_lowpart_offset (ymode, xmode))
|
||||||
return true;
|
{
|
||||||
|
info->representable_p = true;
|
||||||
|
rknown = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* This should always pass, otherwise we don't know how to verify
|
/* This should always pass, otherwise we don't know how to verify
|
||||||
the constraint. These conditions may be relaxed but
|
the constraint. These conditions may be relaxed but
|
||||||
@ -3057,22 +3068,61 @@ subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
|
|||||||
/* The XMODE value can be seen as a vector of NREGS_XMODE
|
/* The XMODE value can be seen as a vector of NREGS_XMODE
|
||||||
values. The subreg must represent a lowpart of given field.
|
values. The subreg must represent a lowpart of given field.
|
||||||
Compute what field it is. */
|
Compute what field it is. */
|
||||||
offset -= subreg_lowpart_offset (ymode,
|
offset_adj = offset;
|
||||||
mode_for_size (GET_MODE_BITSIZE (xmode)
|
offset_adj -= subreg_lowpart_offset (ymode,
|
||||||
/ nregs_xmode,
|
mode_for_size (GET_MODE_BITSIZE (xmode)
|
||||||
MODE_INT, 0));
|
/ nregs_xmode,
|
||||||
|
MODE_INT, 0));
|
||||||
|
|
||||||
/* Size of ymode must not be greater than the size of xmode. */
|
/* Size of ymode must not be greater than the size of xmode. */
|
||||||
mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
|
mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
|
||||||
gcc_assert (mode_multiple != 0);
|
gcc_assert (mode_multiple != 0);
|
||||||
|
|
||||||
y_offset = offset / GET_MODE_SIZE (ymode);
|
y_offset = offset / GET_MODE_SIZE (ymode);
|
||||||
nregs_multiple = nregs_xmode / nregs_ymode;
|
y_offset_adj = offset_adj / GET_MODE_SIZE (ymode);
|
||||||
|
nregs_multiple = nregs_xmode / nregs_ymode;
|
||||||
|
|
||||||
gcc_assert ((offset % GET_MODE_SIZE (ymode)) == 0);
|
gcc_assert ((offset_adj % GET_MODE_SIZE (ymode)) == 0);
|
||||||
gcc_assert ((mode_multiple % nregs_multiple) == 0);
|
gcc_assert ((mode_multiple % nregs_multiple) == 0);
|
||||||
|
|
||||||
return (!(y_offset % (mode_multiple / nregs_multiple)));
|
if (!rknown)
|
||||||
|
{
|
||||||
|
info->representable_p = (!(y_offset_adj % (mode_multiple / nregs_multiple)));
|
||||||
|
rknown = true;
|
||||||
|
}
|
||||||
|
info->offset = (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
|
||||||
|
info->nregs = nregs_ymode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function returns the regno offset of a subreg expression.
|
||||||
|
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. */
|
||||||
|
unsigned int
|
||||||
|
subreg_regno_offset (unsigned int xregno, enum machine_mode xmode,
|
||||||
|
unsigned int offset, enum machine_mode ymode)
|
||||||
|
{
|
||||||
|
struct subreg_info info;
|
||||||
|
subreg_get_info (xregno, xmode, offset, ymode, &info);
|
||||||
|
return info.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 - Whether the offset is representable. */
|
||||||
|
bool
|
||||||
|
subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
|
||||||
|
unsigned int offset, enum machine_mode ymode)
|
||||||
|
{
|
||||||
|
struct subreg_info info;
|
||||||
|
subreg_get_info (xregno, xmode, offset, ymode, &info);
|
||||||
|
return info.representable_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the final regno that a subreg expression refers to. */
|
/* Return the final regno that a subreg expression refers to. */
|
||||||
@ -3090,6 +3140,21 @@ subreg_regno (rtx x)
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the number of registers that a subreg expression refers
|
||||||
|
to. */
|
||||||
|
unsigned int
|
||||||
|
subreg_nregs (rtx x)
|
||||||
|
{
|
||||||
|
struct subreg_info info;
|
||||||
|
rtx subreg = SUBREG_REG (x);
|
||||||
|
int regno = REGNO (subreg);
|
||||||
|
|
||||||
|
subreg_get_info (regno, GET_MODE (subreg), SUBREG_BYTE (x), GET_MODE (x),
|
||||||
|
&info);
|
||||||
|
return info.nregs;
|
||||||
|
}
|
||||||
|
|
||||||
struct parms_set_data
|
struct parms_set_data
|
||||||
{
|
{
|
||||||
int nregs;
|
int nregs;
|
||||||
|
Loading…
Reference in New Issue
Block a user