This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Non-representable subregs of subword pseudoregs
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc at gcc dot gnu dot org
- Cc: Jan Hubicka <jh at suse dot cz>
- Date: Sat, 13 Nov 2004 10:45:50 +0100
- Subject: Non-representable subregs of subword pseudoregs
Hello,
I've run into a surprising (to me) behavior of the reload pass: it apparently
doesn't know how to reload non-representable subregs of subword pseudoregs.
For example on SPARC64:
(insn 22 21 23 1 (set (reg:SI 109 [ D.1130 ])
(subreg:SI (reg:DI 126) 0)) 51 {*movsi_insn} (nil)
(nil))
leads to
Reloads for insn # 22
Reload 0: reload_in (SI) = (reg:SI 1 %g1)
GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 1), can't combine
reload_in_reg: (subreg:SI (reg:DI 1 %g1 [126]) 0)
reload_reg_rtx: (reg:SI 5 %g5)
(insn 61 21 22 1 (set (reg:SI 5 %g5)
(reg:SI 1 %g1)) 51 {*movsi_insn} (nil)
(nil))
(insn 22 61 23 1 (set (reg:SI 4 %g4 [orig:109 D.1130 ] [109])
(reg:SI 5 %g5)) 51 {*movsi_insn} (nil)
(nil))
which is of course wrong since the target is big-endian.
A reload is scheduled because find_reload correctly diagnoses that the subreg
is not representable:
while (GET_CODE (operand) == SUBREG)
{
/* Offset only matters when operand is a REG and
it is a hard reg. This is because it is passed
to reg_fits_class_p if it is a REG and all pseudos
return 0 from that function. */
if (REG_P (SUBREG_REG (operand))
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
if (!subreg_offset_representable_p
(REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
GET_MODE (operand)))
force_reload = 1;
However, reload_inner_reg_of_subreg returns false for it (for 2 reasons: it's
an input reload and the function only looks at output reloads, and subregs of
subword regs are rejected) so push_reload silently turns the invalid subreg
into the low part:
/* If IN is a SUBREG of a hard register, make a new REG. This
simplifies some of the cases below. */
if (in != 0 && GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& ! dont_remove_subreg)
in = gen_rtx_REG (GET_MODE (in), subreg_regno (in));
Is this a known limitation of the reload pass or am I missing anything else?
[Jan, I've CCed you because you devised subreg_offset_representable_p.]
The non-representable subreg is created by emit_move_insn_1 when it is invoked
on pseudo regs and CONCATs with complex modes. Note that it already has a
special provision in order not to create non-representable subregs of hard
regs:
/* If this is a complex value with each part being smaller than a
word, the usual calling sequence will likely pack the pieces into
a single register. Unfortunately, SUBREG of hard registers only
deals in terms of words, so we have a problem converting input
arguments to the CONCAT of two registers that is used elsewhere
for complex values. If this is before reload, we can copy it into
memory and reload. FIXME, we should see about using extract and
insert on integer registers, but complex short and complex char
variables should be rarely used. */
if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
&& (reload_in_progress | reload_completed) == 0)
{
int packed_dest_p
= (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
int packed_src_p
= (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
if (packed_dest_p || packed_src_p)
but it doesn't apply here because we are dealing with pseudo regs.
How is this supposed to work? Is it simply illegal to create non-lowpart
subregs of subword pseudo regs?
Thanks in advance.
--
Eric Botcazou