This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Register allocation and paradoxical subregs on SPARC64
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc at gcc dot gnu dot org
- Date: Fri, 23 May 2003 11:10:40 +0200
- Subject: Register allocation and paradoxical subregs on SPARC64
Hi,
This is PR optimization/10904. GCC 3.3 and mainline generate illegal assembly
fdtox %f10, %f7 (illegal, odd-numbered FP reg)
at -O2 for
int a = (long)(b * ((double) 0.1));
under certain circumstances on SPARC64. Note that this is a progression from
GCC 3.2.x which silently generates wrong code in the same situation.
Here's the chain of events: the combiner turns
(insn 30 29 31 0 0x40182fc0 (set (reg:DI 118)
(fix:DI (fix:DF (reg:DF 117)))) 167 {fix_truncdfdi2} (insn_list 29
(nil))
(expr_list:REG_DEAD (reg:DF 117)
(nil)))
(insn 31 30 33 0 0x40182fc0 (set (reg/v:SI 112)
(subreg:SI (reg:DI 118) 4)) 51 {*movsi_insn} (insn_list 30 (nil))
(expr_list:REG_DEAD (reg:DI 118)
(nil)))
into
(insn 31 30 33 0 0x40182fc0 (set (subreg:DI (reg/v:SI 112) 0)
(fix:DI (fix:DF (reg:DF 117)))) 167 {fix_truncdfdi2} (insn_list 29
(nil))
(expr_list:REG_DEAD (reg:DF 117)
(nil)))
which I think is correct on big-endian targets.
Then the (global) register allocator allocates %f8 to (reg/v:SI 112) because
it doesn't know that the pseudo has been paradoxically subreged. So
(subreg:DI (reg/v:SI 112) 0) ends up being assigned %f7-%f8.
How is this supposed to work? I think that the register allocator must be
taught to consider the constraints introduced by the subreg-ization. I see
that the machinery (subregs_of_mode, cannot_change_mode_set_regs in
regclass.c) has already been added by Aldy Hernandez. However,
(1) Even if I define CANNOT_CHANGE_MODE_CLASS for Sparc, it won't be
sufficient since the register classes of the Sparc port don't differentiate
between odd- and even-numbered regs. That information is only contained in
the HARD_REGNO_MODE_OK macro.
(2) cannot_change_mode_set_regs can't handle paradoxical subregs on
big-endian targets.
I think (1) can be fixed by instructing REG_CANNOT_CHANGE_MODE_P
/* Given a hard REGN a FROM mode and a TO mode, return nonzero if
REGN cannot change modes between the specified modes. */
#define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO) \
CANNOT_CHANGE_MODE_CLASS (FROM, TO, REGNO_REG_CLASS (REGN))
to additionally check whether HARD_REGNO_MODE_OK(REGN, TO) is true.
(2) could be fixed by adding explicit code to cannot_change_mode_set_regs in
order to check that the first register overlapped by the paradoxical subreg,
and not the base register, can be used in the 'to' mode. In the present
situation, it would mark all even-numbered FP regs as used so that the
pseudo (reg/v:SI 112) gets an odd-numbered FP reg.
Does it seem like a sensible solution?
--
Eric Botcazou